Skip to content

Conversation

Copilot
Copy link

@Copilot Copilot AI commented Aug 29, 2025

This PR implements a comprehensive OMERO upload system that enables streaming image tiles to OMERO servers in parallel to acquisition, with full support for timelapse and z-stack experiments. The implementation addresses the critical need for real-time data availability without filling up Raspberry Pi storage.

Key Features

Universal OMERO Support for All Experiment Types

OMERO upload functionality is now available for all experiment modes with proper multi-dimensional support:

  • startFastStageScanAcquisition (performance mode with hardware triggering)
  • startWellplateExperiment (normal mode with workflow-based acquisition)
  • Timelapse experiments - All timepoints stored in single dataset along t-channel
  • Z-stack acquisitions - All z-planes properly indexed along z-channel
  • Multi-position scanning - Coordinated upload across scan positions

Timelapse and Z-Stack Integration

The implementation properly handles multi-dimensional experiments:

Single Dataset Strategy: Timelapse and z-stack experiments create one OMERO dataset containing all timepoints/z-planes with proper indexing along t and z axes, instead of creating separate datasets per timepoint.

Shared OMERO Uploaders: A registry system coordinates uploads across timepoints, ensuring the first timepoint creates the dataset/image and subsequent timepoints reuse the same OMERO objects.

Proper Dimension Configuration: OMERO images are created with correct size_t and size_z dimensions to accommodate the full experiment scope.

Parallelized Upload Architecture with Robust Threading

  • Background thread: OMERO upload runs in a separate thread, ensuring acquisition is never blocked
  • Bounded queue: Configurable in-memory queue with automatic disk spillover when full
  • Complete queue drainage: Worker thread continues processing until all tiles are uploaded, even after acquisition completes
  • Thread coordination: Proper signaling between acquisition and upload threads prevents premature cleanup
  • Robust connection management: Handles timeouts, retries, and graceful degradation

ROMIO Backend Compatibility

The implementation properly supports both OMERO backend types:

Pyramid backends: Use efficient tile-based writes with RawPixelsStore.setTile() for individual tiles

ROMIO backends: Use row-stripe writes that collect tiles by row and merge them horizontally before upload. The key insight is that ROMIO backends enforce a constraint: "ROMIO pixel buffer only supports full row writes". Our solution implements intelligent row buffering with automatic padding for incomplete rows.

Threading Race Condition Fixes

Addresses critical issues where image scanning could finish faster than uploading:

  • Queue drainage: Worker thread now continues processing until both stop is requested AND queue is empty
  • Lock safety: Added timeout-based lock acquisition in row buffer management to prevent deadlocks
  • Completion signaling: OMEWriter calls signal_completion() when acquisition finishes to coordinate shutdown
  • Incomplete row handling: Automatically pads missing tiles with zeros during finalization

Multiple Storage Backend Support

Users can now select multiple storage backends simultaneously:

  • Local OME-TIFF files
  • Local OME-Zarr for browser streaming
  • Stitched OME-TIFF files (Fiji compatible)
  • Direct OMERO upload (available for all experiment types)

Robust Error Handling

  • Graceful fallback: Continues with local storage if OMERO is unavailable
  • Disk spillover: Prevents acquisition blocking when network is slow
  • Connection retry: Automatic retry with proper timeout handling
  • Resource cleanup: Proper connection and temporary file management
  • Dataset validation: Automatically handles non-existent dataset references

Implementation Details

Multi-Dimensional Coordination

  • Dataset Reuse: Added reuse_dataset_id and reuse_image_id parameters to OMEROConnectionParams for coordinating uploads across timepoints
  • Shared Uploader Registry: Class-level registry in OMEWriter manages shared OMERO uploaders using unique experiment keys
  • Dimension Validation: Enhanced setup to validate existing image dimensions when reusing OMERO objects

Threading Coordination

  • Worker persistence: Uses get(timeout=0.1) to periodically check stop condition while continuing to process remaining tiles
  • Event signaling: _worker_finished event ensures main thread waits for complete processing
  • Stop coordination: _stop_requested flag prevents new tile enqueueing while allowing queue drainage

Row Buffer Management

  • Thread-safe operations: Lock acquisition with timeout prevents deadlocks
  • Incomplete row padding: Missing tiles are filled with zeros to complete row uploads
  • Memory cleanup: Proper cleanup of row buffers after successful upload

The implementation exactly matches the reference code provided in the issue, enabling streaming of tiles to OMERO using either RawPixelsStore.setTile for pyramid backends or row-stripe writes for ROMIO backends, with automatic backend detection and robust handling of threading race conditions.

Fixes #149.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 2 commits August 29, 2025 10:04
Co-authored-by: openuc2-gmbh <218447657+openuc2-gmbh@users.noreply.github.com>
Co-authored-by: openuc2-gmbh <218447657+openuc2-gmbh@users.noreply.github.com>
@Copilot Copilot AI changed the title [WIP] Parallelized OMERO Upload via ExperimentController Queue Implement parallelized OMERO upload via ExperimentController queue Aug 29, 2025
@Copilot Copilot AI requested a review from openuc2-gmbh August 29, 2025 10:11
Copilot finished work on behalf of openuc2-gmbh August 29, 2025 10:11
@openuc2-gmbh
Copy link

@copilot, currently, the implementation of saving to omero is only working for the startFastStageScanAcquisitionFilePath, but it should also be available for the startWellplateExperiment().

- Add ome_write_omero field to ParameterValue model for API configuration
- Update ExperimentController to handle _ome_write_omero flag in wellplate experiments
- Add prepare_omero_connection_params method to ExperimentModeBase
- Update create_writer_config to include write_omero parameter
- Modify ExperimentNormalMode to prepare and pass OMERO connection parameters to OMEWriter
- Enable OMERO upload functionality for both single TIFF and multi-tile modes in normal mode

This extends OMERO upload capability from startFastStageScanAcquisition to
startWellplateExperiment, enabling parallelized OMERO upload for all experiment types.

Co-authored-by: openuc2-gmbh <218447657+openuc2-gmbh@users.noreply.github.com>
Copy link
Author

Copilot AI commented Aug 29, 2025

@copilot, currently, the implementation of saving to omero is only working for the startFastStageScanAcquisitionFilePath, but it should also be available for the startWellplateExperiment().

I've extended the OMERO upload functionality to support startWellplateExperiment() as well. The changes include:

  • Added ome_write_omero parameter to the ParameterValue model for API configuration
  • Updated the normal mode execution path to prepare OMERO connection parameters
  • Enhanced the ExperimentModeBase class with a prepare_omero_connection_params() method
  • Modified ExperimentNormalMode to pass OMERO parameters to OME writers

The OMERO upload functionality now works consistently across both experiment types:

  • startFastStageScanAcquisition (performance mode)
  • startWellplateExperiment (normal mode)

Both methods now use the same OMERO upload infrastructure, enabling parallelized streaming to OMERO servers for all experiment execution modes.

Commit: 2f2e7c5

@Copilot Copilot AI changed the title Implement parallelized OMERO upload via ExperimentController queue Implement parallelized OMERO upload for all experiment types via ExperimentController Aug 29, 2025
Copilot finished work on behalf of openuc2-gmbh August 29, 2025 12:51
@openuc2-gmbh
Copy link

@copilot, as stated with an TOOD: the following line
`self.connection.getUpdateService().saveAndReturnObject(link, self.connection.SERVICE_OPTS)'

fails with

            WARNING:omero.gateway:ValidationException on <class 'omero.gateway.OmeroGatewaySafeCallWrapper'> to <eb90adcb-6699-42a3-bb22-39a3b744acf2omero.api.IUpdate> saveAndReturnObject((object #0 (::omero::model::DatasetImageLink)
{
    _id = <nil>
    _details = object #1 (::omero::model::Details)
    {
        _owner = <nil>
        _group = <nil>
        _creationEvent = <nil>
        _updateEvent = <nil>
        _permissions = <nil>
        _externalInfo = <nil>
        _call = {}
        _event = <nil>
    }
    _loaded = True
    _version = <nil>
    _parent = object #2 (::omero::model::Dataset)
    {
        _id = object #3 (::omero::RLong)
        {
            _val = 200
        }
        _details = <nil>
        _loaded = False
        _version = <nil>
        _projectLinksSeq = {}
        _projectLinksLoaded = False
        _projectLinksCountPerOwner = {}
        _imageLinksSeq = {}
        _imageLinksLoaded = False
        _imageLinksCountPerOwner = {}
        _annotationLinksSeq = {}
        _annotationLinksLoaded = False
        _annotationLinksCountPerOwner = {}
        _name = <nil>
        _description = <nil>
    }
    _child = object #4 (::omero::model::Image)
    {
        _id = object #5 (::omero::RLong)
        {
            _val = 54
        }
        _details = <nil>
        _loaded = False
        _version = <nil>
        _series = <nil>
        _acquisitionDate = <nil>
        _archived = <nil>
        _partial = <nil>
        _format = <nil>
        _imagingEnvironment = <nil>
        _objectiveSettings = <nil>
        _instrument = <nil>
        _stageLabel = <nil>
        _experiment = <nil>
        _pixelsSeq = {}
        _pixelsLoaded = False
        _wellSamplesSeq = {}
        _wellSamplesLoaded = False
        _roisSeq = {}
        _roisLoaded = False
        _datasetLinksSeq = {}
        _datasetLinksLoaded = False
        _datasetLinksCountPerOwner = {}
        _folderLinksSeq = {}
        _folderLinksLoaded = False
        _folderLinksCountPerOwner = {}
        _fileset = <nil>
        _annotationLinksSeq = {}
        _annotationLinksLoaded = False
        _annotationLinksCountPerOwner = {}
        _name = <nil>
        _description = <nil>
    }
}, <ServiceOptsDict: {'omero.client.uuid': 'eb90adcb-6699-42a3-bb22-39a3b744acf2', 'omero.session.uuid': '9823d4ce-95e1-425d-9f77-65fb96ec9642'}>), {})
Traceback (most recent call last):
  File "/Users/bene/mambaforge/envs/microeye/lib/python3.10/site-packages/omero/gateway/__init__.py", line 4870, in __call__
    return self.f(*args, **kwargs)
  File "/Users/bene/mambaforge/envs/microeye/lib/python3.10/site-packages/omero_api_IUpdate_ice.py", line 163, in saveAndReturnObject
    return _M_omero.api.IUpdate._op_saveAndReturnObject.invoke(self, ((obj, ), _ctx))
omero.ValidationException: exception ::omero::ValidationException
{
    serverStackTrace = ome.conditions.ValidationException: No row with the given identifier exists: [ome.model.containers.Dataset#200]; nested exception is org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [ome.model.containers.Dataset#200]
        at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:693)
        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.$Proxy100.saveAndReturnObject(Unknown Source)
        at jdk.internal.reflect.GeneratedMethodAccessor420.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 ome.security.basic.BasicSecurityWiring.invoke(BasicSecurityWiring.java:93)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at ome.services.blitz.fire.AopContextInitializer.invoke(AopContextInitializer.java:43)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
        at com.sun.proxy.$Proxy100.saveAndReturnObject(Unknown Source)
        at jdk.internal.reflect.GeneratedMethodAccessor444.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 ome.services.blitz.util.IceMethodInvoker.invoke(IceMethodInvoker.java:172)
        at ome.services.throttling.Callback.run(Callback.java:56)
        at ome.services.throttling.InThreadThrottlingStrategy.callInvokerOnRawArgs(InThreadThrottlingStrategy.java:56)
        at ome.services.blitz.impl.AbstractAmdServant.callInvokerOnRawArgs(AbstractAmdServant.java:140)
        at ome.services.blitz.impl.UpdateI.saveAndReturnObject_async(UpdateI.java:62)
        at jdk.internal.reflect.GeneratedMethodAccessor443.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.$Proxy101.saveAndReturnObject_async(Unknown Source)
        at omero.api._IUpdateTie.saveAndReturnObject_async(_IUpdateTie.java:92)
        at omero.api._IUpdateDisp.___saveAndReturnObject(_IUpdateDisp.java:229)
        at omero.api._IUpdateDisp.__dispatch(_IUpdateDisp.java:423)
        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
    message = No row with the given identifier exists: [ome.model.containers.Dataset#200]; nested exception is org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [ome.model.containers.Dataset#200]
}

…re linking

Co-authored-by: openuc2-gmbh <218447657+openuc2-gmbh@users.noreply.github.com>
Copy link
Author

Copilot AI commented Aug 29, 2025

@copilot, as stated with an TOOD: the following line
`self.connection.getUpdateService().saveAndReturnObject(link, self.connection.SERVICE_OPTS)'

...

Fixed the OMERO dataset validation error by adding proper dataset existence checking before attempting to link images. The code now verifies that the specified dataset exists using connection.getObject("Dataset", dataset_id) and gracefully creates a new dataset if the requested one doesn't exist, preventing the ValidationException. Removed the TODO comment and error trace as the issue is resolved.

Commit: f8e6e8d

Copilot finished work on behalf of openuc2-gmbh August 29, 2025 15:51
…nthough the omero store is not available yet
@openuc2-gmbh
Copy link

@copilot, I have spotted the following error in the following function 

def _upload_tile_row_stripe(self, tile: TileMetadata):
    """Upload tile using row-stripe writes (ROMIO backend)."""
    # For row-stripe mode, we need to collect all tiles in a row before writing
    # This is a simplified implementation - in practice, you'd want to buffer row data
    try:
        x0 = tile.ix * self.tile_w
        y0 = tile.iy * self.tile_h
        
        # Write as a single row stripe
        buf = np.ascontiguousarray(tile.tile_data).tobytes()
        self.store.setTile(buf, tile.z, tile.c, tile.t, 
                         x0, y0, self.tile_w, self.tile_h)
                         
    except Exception as e:
        ''' TODO: 
        I think we need to collect tiles first and merge them into a row before uploading them to a omero object we get the follwoing error:
        tile.tile_data.shape

(300, 400)
but it should be a whole row instead

        excception ::omero::InternalException

{
serverStackTrace = ome.conditions.InternalException: Wrapped Exception: (java.lang.UnsupportedOperationException):
ROMIO pixel buffer only supports full row writes.
at ome.io.nio.RomioPixelBuffer.setTile(RomioPixelBuffer.java:908)
at ome.services.RawPixelsBean.setTile(RawPixelsBean.java:982)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
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 ome.security.basic.EventHandler.invoke(EventHandler.java:154)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at ome.tools.hibernate.SessionHandler.doStateful(SessionHandler.java:216)
at ome.tools.hibernate.SessionHandler.invoke(SessionHandler.java:200)
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.$Proxy113.setTile(Unknown Source)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
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 ome.security.basic.BasicSecurityWiring.invoke(BasicSecurityWiring.java:93)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at ome.services.blitz.fire.AopContextInitializer.invoke(AopContextInitializer.java:43)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy113.setTile(Unknown Source)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at ome.services.blitz.util.IceMethodInvoker.invoke(IceMethodInvoker.java:172)
at ome.services.throttling.Callback.run(Callback.java:56)
at ome.services.throttling.InThreadThrottlingStrategy.callInvokerOnRawArgs(InThreadThrottlingStrategy.java:56)
at ome.services.blitz.impl.AbstractAmdServant.callInvokerOnRawArgs(AbstractAmdServant.java:140)
at ome.services.blitz.impl.RawPixelsStoreI.setTile_async(RawPixelsStoreI.java:289)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
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.$Proxy114.setTile_async(Unknown Source)
at omero.api._RawPixelsStoreTie.setTile_async(_RawPixelsStoreTie.java:300)
at omero.api._RawPixelsStoreDisp.___setTile(_RawPixelsStoreDisp.java:1228)
at omero.api._RawPixelsStoreDisp.__dispatch(_RawPixelsStoreDisp.java:1788)
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.InternalException
message =  Wrapped Exception: (java.lang.UnsupportedOperationException):

ROMIO pixel buffer only supports full row writes.
}'''

Co-authored-by: openuc2-gmbh <218447657+openuc2-gmbh@users.noreply.github.com>
Copy link
Author

Copilot AI commented Aug 29, 2025

@copilot, I have spotted the following error in the following function 

def _upload_tile_row_stripe(self, tile: TileMetadata):

...

Fixed the ROMIO backend row buffering issue. The problem was that ROMIO requires full row writes spanning the entire image width, but the code was trying to upload individual tiles.

The solution implements:

  • Row buffering: Tiles are collected by row (same iy value) instead of uploaded immediately
  • Row assembly: When all tiles for a row are collected (len(row_tiles) == self.nx), they are merged horizontally using np.concatenate
  • Row-stripe upload: Complete rows are uploaded as full-width stripes to satisfy ROMIO's "full row writes" requirement
  • Thread-safe operations: Row buffering uses proper locking to prevent race conditions

The _upload_tile_row_stripe method now buffers tiles until a complete row is assembled, then calls _upload_complete_row to merge the tiles horizontally and upload as row stripes that span the full image width.

Commit: 27f9b91

@Copilot Copilot AI changed the title Implement parallelized OMERO upload for all experiment types via ExperimentController Implement parallelized OMERO upload for all experiment types with ROMIO backend support Aug 29, 2025
Copilot finished work on behalf of openuc2-gmbh August 29, 2025 18:24
Enhanced logging throughout the OMERO uploader for better debugging and status reporting. Added flags to prevent duplicate finalization and connection cleanup. Improved queue management and error handling, and clarified row buffer processing during finalization.
@openuc2-gmbh
Copy link

@copilot I think currently, the image scanning can finish faster than uploading the images. Especially if we first have to collect the rows and then upload these. This takes time. The way the locks are used currently, I think it prevents from uploading all the data that have been captured before the omero uploading thread finalizes. The result is that not all rows are uploaded and tiles are delted. This has to be resolved.
I think the function _upload_remaining_rows won't upload the remaining rows if the locks are not free. Then the thread stops and frees all buffers.

At one point (second row) it does not show these messages anymore:
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Added tile 4 to row 0, now has 5/5 tiles so no new rows are updated

A typical log:

INFO:     127.0.0.1:61856 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
INFO:     127.0.0.1:61856 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
INFO:     127.0.0.1:61865 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
INFO:     127.0.0.1:61869 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
DEBUG:imswitch:[ExperimentController] Normal mode is enabled. Creating workflow steps for precise control.
DEBUG:imswitch:[ExperimentController] OME-TIFF path: ~/Downloads/ExperimentController/20250830_174914/20250830_174914_experiment0_0_experiment_0_.ome.tif
DEBUG:imswitch:[ExperimentController] TIFF stitcher initialized: ~/Downloads/ExperimentController/20250830_174914/20250830_174914_experiment0_0_experiment_0_/stitched.ome.tif
2025-08-30 17:49:14 INFO OMERO uploader initialized with mosaic config: 5x5 tiles, 400x300 pixels per tile, Z=1, C=1, T=1, dtype=uint16
INFO:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:OMERO uploader initialized with mosaic config: 5x5 tiles, 400x300 pixels per tile, Z=1, C=1, T=1, dtype=uint16
2025-08-30 17:49:15 INFO Connected to OMERO as root
INFO:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Connected to OMERO as root
2025-08-30 17:49:15 WARNING Dataset 200 not found, creating new dataset
WARNING:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Dataset 200 not found, creating new dataset
2025-08-30 17:49:16 INFO OMERO backend detected: row-stripe writes (server tile size: 2000x262)
INFO:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:OMERO backend detected: row-stripe writes (server tile size: 2000x262)
2025-08-30 17:49:16 INFO Created OMERO image 81 in dataset 177
INFO:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Created OMERO image 81 in dataset 177
2025-08-30 17:49:16 INFO OMERO uploader thread started
INFO:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:OMERO uploader thread started
2025-08-30 17:49:16 INFO [ExperimentController] OMERO uploader initialized and started
INFO:imswitch:[ExperimentController] OMERO uploader initialized and started
DEBUG:imswitch:[ExperimentController] Moving stage to X=64657.45856353591, Y=50348.066298342535
DEBUG:imswitch:[WorkflowStep] Step Move to point 0 (0) completed in 0.00s (pre: 0.00s, main: 0.00s, post: 0.00s)
INFO:     127.0.0.1:61869 - "POST /ExperimentController/startWellplateExperiment HTTP/1.1" 200 OK
DEBUG:imswitch:[ExperimentController] Moving stage to Z=0
Defocus:0.0
DEBUG:imswitch:[WorkflowStep] Step Move to Z position (1) completed in 0.13s (pre: 0.12s, main: 0.01s, post: 0.00s)
DEBUG:imswitch:[ExperimentController] Setting laser power to 7 for channel LED
INFO:     127.0.0.1:61869 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
DEBUG:imswitch:[WorkflowStep] Step Turn on illumination (2) completed in 0.06s (pre: 0.00s, main: 0.00s, post: 0.06s)
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (0, 0) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (3) completed in 0.71s (pre: 0.00s, main: 0.45s, post: 0.25s)
DEBUG:imswitch:[ExperimentController] Moving stage to X=66657.45856353591, Y=50348.066298342535
DEBUG:imswitch:[WorkflowStep] Step Move to point 1 (4) completed in 0.00s (pre: 0.00s, main: 0.00s, post: 0.00s)
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Processing tile (0, 0) for row buffer, key: (0, 0, 0, 0)
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Created new row buffer for row 0
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Added tile 0 to row 0, now has 1/5 tiles
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Row 0 still incomplete (1/5 tiles), waiting for more tiles...
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (1, 0) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (5) completed in 0.50s (pre: 0.00s, main: 0.23s, post: 0.27s)
DEBUG:imswitch:[ExperimentController] Moving stage to X=68657.45856353591, Y=50348.066298342535
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Processing tile (1, 0) for row buffer, key: (0, 0, 0, 0)
DEBUG:imswitch:[WorkflowStep] Step Move to point 2 (6) completed in 0.01s (pre: 0.00s, main: 0.01s, post: 0.00s)
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Added tile 1 to row 0, now has 2/5 tiles
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Row 0 still incomplete (2/5 tiles), waiting for more tiles...
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (2, 0) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (7) completed in 0.52s (pre: 0.00s, main: 0.31s, post: 0.20s)
DEBUG:imswitch:[ExperimentController] Moving stage to X=70657.45856353591, Y=50348.066298342535
DEBUG:imswitch:[WorkflowStep] Step Move to point 3 (8) completed in 0.00s (pre: 0.00s, main: 0.00s, post: 0.00s)
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Processing tile (2, 0) for row buffer, key: (0, 0, 0, 0)
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Added tile 2 to row 0, now has 3/5 tiles
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Row 0 still incomplete (3/5 tiles), waiting for more tiles...
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (3, 0) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (9) completed in 0.59s (pre: 0.00s, main: 0.26s, post: 0.32s)
DEBUG:imswitch:[ExperimentController] Moving stage to X=72657.45856353591, Y=50348.066298342535
DEBUG:imswitch:[WorkflowStep] Step Move to point 4 (10) completed in 0.11s (pre: 0.00s, main: 0.11s, post: 0.00s)
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Processing tile (3, 0) for row buffer, key: (0, 0, 0, 0)
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Added tile 3 to row 0, now has 4/5 tiles
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Row 0 still incomplete (4/5 tiles), waiting for more tiles...
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
INFO:     127.0.0.1:61882 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (4, 0) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (11) completed in 0.63s (pre: 0.00s, main: 0.56s, post: 0.07s)
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Processing tile (4, 0) for row buffer, key: (0, 0, 0, 0)
DEBUG:imswitch:[ExperimentController] Moving stage to X=72657.45856353591, Y=51848.066298342535
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Added tile 4 to row 0, now has 5/5 tiles
DEBUG:imswitch:[WorkflowStep] Step Move to point 9 (12) completed in 0.04s (pre: 0.00s, main: 0.04s, post: 0.00s)
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Uploading complete row 0 at y=0, size=2000x300
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (4, 1) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (13) completed in 0.43s (pre: 0.00s, main: 0.26s, post: 0.16s)
DEBUG:imswitch:[ExperimentController] Moving stage to X=70657.45856353591, Y=51848.066298342535
DEBUG:imswitch:[WorkflowStep] Step Move to point 8 (14) completed in 0.01s (pre: 0.00s, main: 0.01s, post: 0.00s)
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (3, 1) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (15) completed in 0.38s (pre: 0.00s, main: 0.22s, post: 0.16s)
DEBUG:imswitch:[ExperimentController] Moving stage to X=68657.45856353591, Y=51848.066298342535
DEBUG:imswitch:[WorkflowStep] Step Move to point 7 (16) completed in 0.00s (pre: 0.00s, main: 0.00s, post: 0.00s)
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (2, 1) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (17) completed in 0.33s (pre: 0.00s, main: 0.21s, post: 0.12s)
DEBUG:imswitch:[ExperimentController] Moving stage to X=66657.45856353591, Y=51848.066298342535
DEBUG:imswitch:[WorkflowStep] Step Move to point 6 (18) completed in 0.00s (pre: 0.00s, main: 0.00s, post: 0.00s)
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (1, 1) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (19) completed in 0.36s (pre: 0.00s, main: 0.22s, post: 0.15s)
DEBUG:imswitch:[ExperimentController] Moving stage to X=64657.45856353591, Y=51848.066298342535
DEBUG:imswitch:[WorkflowStep] Step Move to point 5 (20) completed in 0.00s (pre: 0.00s, main: 0.00s, post: 0.00s)
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (0, 1) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (21) completed in 0.38s (pre: 0.00s, main: 0.25s, post: 0.13s)
DEBUG:imswitch:[ExperimentController] Moving stage to X=64657.45856353591, Y=53348.066298342535
DEBUG:imswitch:[WorkflowStep] Step Move to point 10 (22) completed in 0.01s (pre: 0.00s, main: 0.01s, post: 0.00s)
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (0, 2) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (23) completed in 0.36s (pre: 0.00s, main: 0.23s, post: 0.13s)
DEBUG:imswitch:[ExperimentController] Moving stage to X=66657.45856353591, Y=53348.066298342535
DEBUG:imswitch:[WorkflowStep] Step Move to point 11 (24) completed in 0.00s (pre: 0.00s, main: 0.00s, post: 0.00s)
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
INFO:     127.0.0.1:61882 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (1, 2) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (25) completed in 0.35s (pre: 0.00s, main: 0.20s, post: 0.15s)
DEBUG:imswitch:[ExperimentController] Moving stage to X=68657.45856353591, Y=53348.066298342535
DEBUG:imswitch:[WorkflowStep] Step Move to point 12 (26) completed in 0.00s (pre: 0.00s, main: 0.00s, post: 0.00s)
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (2, 2) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (27) completed in 0.39s (pre: 0.00s, main: 0.20s, post: 0.19s)
DEBUG:imswitch:[ExperimentController] Moving stage to X=70657.45856353591, Y=53348.066298342535
DEBUG:imswitch:[WorkflowStep] Step Move to point 13 (28) completed in 0.00s (pre: 0.00s, main: 0.00s, post: 0.00s)
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (3, 2) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (29) completed in 0.31s (pre: 0.00s, main: 0.21s, post: 0.10s)
DEBUG:imswitch:[ExperimentController] Moving stage to X=72657.45856353591, Y=53348.066298342535
DEBUG:imswitch:[WorkflowStep] Step Move to point 14 (30) completed in 0.00s (pre: 0.00s, main: 0.00s, post: 0.00s)
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (4, 2) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (31) completed in 0.42s (pre: 0.00s, main: 0.22s, post: 0.19s)
DEBUG:imswitch:[ExperimentController] Moving stage to X=72657.45856353591, Y=54848.066298342535
DEBUG:imswitch:[WorkflowStep] Step Move to point 19 (32) completed in 0.00s (pre: 0.00s, main: 0.00s, post: 0.00s)
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (4, 3) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (33) completed in 0.35s (pre: 0.00s, main: 0.25s, post: 0.10s)
DEBUG:imswitch:[ExperimentController] Moving stage to X=70657.45856353591, Y=54848.066298342535
DEBUG:imswitch:[WorkflowStep] Step Move to point 18 (34) completed in 0.00s (pre: 0.00s, main: 0.00s, post: 0.00s)
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (3, 3) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (35) completed in 0.33s (pre: 0.00s, main: 0.23s, post: 0.10s)
DEBUG:imswitch:[ExperimentController] Moving stage to X=68657.45856353591, Y=54848.066298342535
DEBUG:imswitch:[WorkflowStep] Step Move to point 17 (36) completed in 0.00s (pre: 0.00s, main: 0.00s, post: 0.00s)
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (2, 3) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (37) completed in 0.38s (pre: 0.00s, main: 0.21s, post: 0.17s)
DEBUG:imswitch:[ExperimentController] Moving stage to X=66657.45856353591, Y=54848.066298342535
DEBUG:imswitch:[WorkflowStep] Step Move to point 16 (38) completed in 0.00s (pre: 0.00s, main: 0.00s, post: 0.00s)
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (1, 3) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (39) completed in 0.44s (pre: 0.00s, main: 0.25s, post: 0.19s)
DEBUG:imswitch:[ExperimentController] Moving stage to X=64657.45856353591, Y=54848.066298342535
DEBUG:imswitch:[WorkflowStep] Step Move to point 15 (40) completed in 0.00s (pre: 0.00s, main: 0.00s, post: 0.00s)
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
INFO:     127.0.0.1:61889 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (0, 3) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (41) completed in 0.42s (pre: 0.00s, main: 0.23s, post: 0.18s)
DEBUG:imswitch:[ExperimentController] Moving stage to X=64657.45856353591, Y=56348.066298342535
DEBUG:imswitch:[WorkflowStep] Step Move to point 20 (42) completed in 0.00s (pre: 0.00s, main: 0.00s, post: 0.00s)
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (0, 4) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (43) completed in 0.32s (pre: 0.00s, main: 0.20s, post: 0.13s)
DEBUG:imswitch:[ExperimentController] Moving stage to X=66657.45856353591, Y=56348.066298342535
DEBUG:imswitch:[WorkflowStep] Step Move to point 21 (44) completed in 0.00s (pre: 0.00s, main: 0.00s, post: 0.00s)
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (1, 4) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (45) completed in 0.38s (pre: 0.00s, main: 0.19s, post: 0.19s)
DEBUG:imswitch:[ExperimentController] Moving stage to X=68657.45856353591, Y=56348.066298342535
DEBUG:imswitch:[WorkflowStep] Step Move to point 22 (46) completed in 0.00s (pre: 0.00s, main: 0.00s, post: 0.00s)
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (2, 4) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (47) completed in 0.31s (pre: 0.00s, main: 0.18s, post: 0.13s)
DEBUG:imswitch:[ExperimentController] Moving stage to X=70657.45856353591, Y=56348.066298342535
DEBUG:imswitch:[WorkflowStep] Step Move to point 23 (48) completed in 0.00s (pre: 0.00s, main: 0.00s, post: 0.00s)
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (3, 4) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (49) completed in 0.39s (pre: 0.00s, main: 0.23s, post: 0.16s)
DEBUG:imswitch:[ExperimentController] Moving stage to X=72657.45856353591, Y=56348.066298342535
DEBUG:imswitch:[WorkflowStep] Step Move to point 24 (50) completed in 0.00s (pre: 0.00s, main: 0.00s, post: 0.00s)
DEBUG:imswitch:[ExperimentController] Acquiring frame on channel Mono
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Enqueueing tile (4, 4) for upload (mosaic size: 5x5)
DEBUG:imswitch:[WorkflowStep] Step Acquire frame (51) completed in 0.35s (pre: 0.00s, main: 0.23s, post: 0.12s)
DEBUG:imswitch:[ExperimentController] Dummy main function called
2025-08-30 17:49:27 INFO [ExperimentController] Finalizing OME writer for tile: 0
INFO:imswitch:[ExperimentController] Finalizing OME writer for tile: 0
2025-08-30 17:49:27 INFO [ExperimentController] Stitched TIFF file completed
INFO:imswitch:[ExperimentController] Stitched TIFF file completed
INFO:     127.0.0.1:61894 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
INFO:     127.0.0.1:61894 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
INFO:     127.0.0.1:61898 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Cleaned up completed row buffer for row 0
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Processing tile (4, 1) for row buffer, key: (1, 0, 0, 0)
INFO:     127.0.0.1:61898 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
INFO:     127.0.0.1:61898 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
INFO:     127.0.0.1:61898 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
2025-08-30 17:49:45 INFO No incomplete rows found during finalization
INFO:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:No incomplete rows found during finalization
INFO:     127.0.0.1:61898 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Created new row buffer for row 1
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Added tile 4 to row 1, now has 1/5 tiles
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Row 1 still incomplete (1/5 tiles), waiting for more tiles...
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Processing tile (3, 1) for row buffer, key: (1, 0, 0, 0)
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Added tile 3 to row 1, now has 2/5 tiles
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Row 1 still incomplete (2/5 tiles), waiting for more tiles...
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Processing tile (2, 1) for row buffer, key: (1, 0, 0, 0)
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Added tile 2 to row 1, now has 3/5 tiles
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Row 1 still incomplete (3/5 tiles), waiting for more tiles...
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Processing tile (1, 1) for row buffer, key: (1, 0, 0, 0)
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Added tile 1 to row 1, now has 4/5 tiles
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Row 1 still incomplete (4/5 tiles), waiting for more tiles...
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Processing tile (0, 1) for row buffer, key: (1, 0, 0, 0)
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Added tile 0 to row 1, now has 5/5 tiles
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Uploading complete row 1 at y=300, size=2000x300
WARNING:omero.gateway:ApiUsageException on <class 'omero.gateway.OmeroGatewaySafeCallWrapper'> to <5eaa43db-e3e1-4d23-985a-d8e29a90ff10omero.api.RawPixelsStore> setTile((b'\x02\x00\x03\x00\x01\x00\x04\x00\x03\x00\x06\x00\x04\x00\x02\x00\x02\x00\x03\x00\x01\x00\x01\x00\x03\x00\x02\x00\x04\x00\x06\x00\x04\x00\x00\x00\x02\x00\x05\x00\x02\x00\x04\x00\x05\x00\x01\x00\x01\x00\x01\x00\x00\x00\x02\x00\x01\x00\x04\x00\x01\x00\x01\x00\x02\x00\x00\x00\x02\x00\x01\x00\x04\x00\x00\x00\x01\x00\x04\x00\x01\x00\x02\x00\x05\x00\x02\x00\x06\x00\x02\x00\x02\x00\x04\x00\x01\x00\x06\x00\x06\x00\x01\x00\x00\x00\x01\x00\x03\x00\x03\x00\x03\x00\x05\x00\x05\x00\x01\x00\x03\x00\x03\x00\x04\x00\x03\x00\x06\x00\x03\x00\x02\x00\x01\x00\x02\x00\x06\x00\x02\x00\x04\x00\x04\x00\x02\x00\x03\x00\x04\x00\x02\x00\x06\x00\x04\x00\x02\x00\x01\x00\x02\x00\x07\x00\x03\x00\x01\x00\x02\x00\x03\x00\x01\x00\x04\x00\x02\x00\x02\x00\x05\x00\x04\x00\x05\x00\x04\x00\x02\x00\x04\x00\x03\x00\x04\x00\x01\x00\x02\x00\x02\x00\x04\x00\x02\x00\x02\x00\x03\x00\x01\x00\x02\x00\x03\x00\x02\x00\x06\x00\x04\x00\x04\x00\x01\x00\x04\x00\x05\x00\x03\x00\x03\x00\x00\x00\x01\x00\x02\x00\x03\x00\x03\x00\x06\x00\x07\x00\x06\x00\x06\x00\x02\x00\x02\x00\x01\x00\x02\x00\x03\x00\x01\x00\x02\x00\x01\x00\x00\x00\x01\x00\x03\x00\x04\x00\x04\x00\x04\x00\x05\x00\x02\x00\x02\x00\x02\x00\x01\x00\x01\x00\x04\x00\x02\x00\x04\x00\x06\x00\x05\x00\x05\x00\x02\x00\x05\x00\x03\x00\x05\x00\x01\x00\x07\x00\x03\x00\x03\x00\x04\x00\x03\x00\x02\x00\x02\x00\x04\x00\x04\x00\x01\x00\x02\x00\x05\x00\x04\x00\x05\x00\x04\x00\x05\x00\x03\x00\x03\x00\x03\x00\x06\x00\x03\x00\x02\x00\x02\x00\x06\x00\x07\x00\x03\x00\x03\x00\x01\x00\x00\x00\x01\x00\x01\x00\x00\x00\x02\x00\x03\x00\x06\x00\x05\x00\x05\x00\x01\x00\x00\x00\x02\x00\x00\x00\x01\x00\x03\x00\x02\x00\x02\x00\x05\x00\x01\x00\x01\x00\x03\x00\x00\x00\x00\x00\x03\x00\x01\x00\x00\x00\x03\x00\x01\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x03\x00\x03\x00\x03\x00\x01\x00\x01\x00\x01\x00\x00\x00\x02\x00\x02\x00\x03\x00\x01\x00\x02\x00\x01\x00\x01\x00\x00\x00\x02\x00\x02\x00\x00\x00\x04\x00\x00\x00\x01\x00\x01\x00\x03\x00\x01\x00\x02\x00\x08\x00\x04\x00\x02\x00\x01\x00\x00\x00\x01\x00\x02\x00\x04\x00\x04\x00\x00\x00\x03\x00\x04\x00\x00\x00\x00\x00\x06\x00\x02\x00\x01\x00\x01\x00\x02\x00\x01\x00\x01\x00\x02\x00\x02\x00\x02\x00\x01\x00\x00\x00\x03\x00\x03\x00\x01\x00\x01\x00\x02\x00\x05\x00\x00\x00\x01\x00\x01\x00\x01\x00\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x01\x00\x04\x00\x02\x00\x01\x00\x01\x00\x02\x00\x02\x00\x01\x00\x02\x00\x02\x00\x01\x00\x00\x00\x03\x00\x02\x00\x02\x00\x05\x00\x01\x00\x05\x00\x04\x00\x01\x00\x01\x00\x04\x00\x05\x00\x01\x00\x00\x00\x06\x00\x05\x00\x01\x00\x04\x00\x05\x00\x05\x00\x02\x00\x02\x00\x03\x00\x01\x00\x01\x00\x02\x00\x02\x00\x00\x00\x00\x00\x02\x00\x01\x00\x00\x00\x02\x00\x01\x00\x02\x00\x00\x00\x01\x00\x04\x00\x05\x00\x04\x00\x03\x00\x01\x00\x05\x00\x08\x00\x06\x00\x02\x00\x03\x00\x02\x00\x05\x00\x06\x00\x03\x00\x02\x00\x02\x00\x04\x00\x02\x00\x00\x00\x01\x00\x01\x00\x03\x00\x01\x00\x01\x00\x02\x00\x01\x00\x04\x00\x04\x00\x05\x00\x07\x00\x06\x00\x03\x00\x02\x00\x02\x00\x06\x00\x03\x00\x03\x00\x04\x00\x05\x00\x01\x00\x08\x00\x01\x00\x00\x00\x04\x00\x02\x00\x05\x00\x02\x00\x06\x00\x03\x00\x01\x00\x04\x00\x06\x00\x06\x00\x05\x00\x05\x00\x05\x00\x03\x00\x02\x00\x04\x00\x02\x00\x04\x00\x07\x00\x03\x00\x01\x00\x04\x00\x02\x00\x02\x00\x01\x00\x02\x00\x03\x00\x04\x00\x0c\x00\x07\x00\x06\x00\x04\x00\x03\x00\x05\x00\x02\x00\x02\x00\x02\x00\x01\x00\x05\x00\x08\x00\x08\x00\x07\x00\x01\x00\x05\x00\x03\x00\x05\x00\x03\x00\x05\x00\x03\x00\x03\x00\x05\x00\x06\x00\x06\x00\x06\x00\x06\x00\x06\x00\x03\x00\x03\x00\x02\x00\x05\x00\x03\x00\x07\x00\x06\x00\x02\x00\x01\x00\x03\x00\x02\x00\x03\x00\x02\x00\x03\x00\x04\x00\x04\x00\x03\x00\x02\x00\x03\x00\x06\x00\t\x00\x08\x00\x05\x00\x02\x00\x08\x00\x05\x00\x06\x00\x08\x00\x04\x00\x01\x00\x03\x00\x06\x00\x0c\x00\x06\x00\x05\x00\x06\x00\x02\x00\x01\x00\x02\x00\x02\x00\x03\x00\x08\x00\x08\x00\x06\x00\x06\x00\x04\x00\x03\x00\x01\x00\x02\x00\x05\x00\x03\x00\x04\x00\x02\x00\x05\x00\x05\x00\x06\x00\x06\x00\x05\x00\x04\x00\x02\x00\x05\x00\x07\x00\x02\x00\x02\x00\x06\x00\x07\x00\x08\x00\x07\x00\x08\x00\x06\x00\x07\x00\x06\x00\x06\x00\t\x00\x05\x00\x01\x00\x03\x00\x08\x00\x01\x00\x05\x00\x02\x00\x02\x00\x02\x00\x07\x00\x04\x00\x08\x00\x04\x00\x05\x00\x05\x00\x01\x00\x05\x00\x08\x00\x05\x00\x05\x00\x01\x00\x05\x00\x06\x00\x05\x00\x01\x00\x04\x00\x07\x00\x06\x00\x01\x00\x02\x00\x02\x00\x00\x00\x00\x00\x03\x00\x02\x00\x01\x00\x01\x00\x03\x00\x04\x00\x06\x00\x05\x00\x08\x00\x07\x00\x05\x00\x02\x00\x02\x00\x00\x00\x02\x00\x08\x00\x03\x00\x03\x00\x03\x00\x05\x00\x05\x00\x06\x00\x05\x00\x04\x00\x02\x00\x01\x00\x00\x00\x01\x00\x02\x00\x03\x00\x02\x00\x02\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\x00\x01\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x01\x00\x05\x00\x03\x00\x02\x00\x02\x00\x01\x00\x01\x00\x03\x00\x01\x00\x00\x00\x03\x00\x03\x00\x04\x00\x04\x00\x02\x00\x02\x00\x03\x00\x02\x00\x03\x00\x04\x00\x01\x00\x01\x00\x01\x00\x03\x00\x04\x00\x02\x00\x02\x00\x03\x00\x07\x00\x02\x00\x01\x00\x01\x00\x04\x00\x03\x00\x01\x00\x03\x00\x02\x00\x01\x00\x01\x00\x00\x00\x01\x00\x01\x00\x03\x00\x02\x00\x01\x00\x02\x00\x02\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x05\x00\x03\x00\x00\x00\x04\x00\x01\x00\x01\x00\x02\x00\x02\x00\x02\x00\x02\x00\x03\x00\x03\x00\x05\x00\x04\x00\x00\x00\x01\x00\x02\x00\x02\x00\x02\x00\x02\x00\x00\x00\x05\x00\x02\x00\x03\x00\x01\x00\x01\x00\x05\x00\x02\x00\x02\x00\x06\x00\x03\x00\x06\x00\x03\x00\x02\x00\x04\x00\x01\x00\x02\x00\x01\x00\x00\x00\x00\x00\x03\x00\x03\x00\x01\x00\x05\x00\x00\x00\x01\x00\x02\x00\x01\x00\x05\x00\x02\x00\x04\x00\x02\x00\x01\x00\x01\x00\x02\x00\x01\x00\x01\x00\x03\x00\x04\x00\x00\x00\x01\x00\x03\x00\x07\x00\x00\x00\x01\x00\x06\x00\x01\x00\x03\x00\x01\x00\x03\x00\x07\x00\x01\x00\x00\x00\x00\x00\x03\x00\x01\x00\x00\x00\x04\x00\x03\x00\x02\x00\x02\x00\x01\x00\x01\x00\x05\x00\x05\x00\x02\x00\x01\x00\x03\x00\x01\x00\x06\x00\x03\x00\x04\x00\x01\x00\x01\x00\x03\x00\x02\x00\x00\x00\x04\x00\x00\x00\x03\x00\x03\x00\x03\x00\x01\x00\x02\x00\x00\x00\x01\x00\x01\x00\x01\x00\x00\x00\x00\x00\x01\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00\x02\x00\x00\x00\x00\x00\x01\x00\x02\x00\x01\x00\x00\x00\x03\x00\x03\x00\x02\x00\x02\x00\x01\x00\x01\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x00\x01\x00\x03\x00\x06\x00\x07\x00\x08\x00\x07\x00\x04\x00\x01\x00\x02\x00\x01\x00\x02\x00\x01\x00\x02\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00\x00\x02\x00\x01\x00\x00\x00\x01\x00\x01\x00\x03\x00\x00\x00\x00\x00\x00\x00\x03\x00\x01\x00\x03\x00\x03\x00\x04\x00\x05\x00\x05\x00\x06\x00\x06\x00\x05\x00\x06\x00\x06\x00\x06\x00\x04\x00\x04\x00\x04\x00\x00\x00\x03\x00\x02\x00\x02\x00\x04\x00\x03\x00\x02\x00\x04\x00\x02\x00\x01\x00\x02\x00\x02\x00\x02\x00\x04\x00\x07\x00\x06\x00\x05\x00\x04\x00\x03\x00\x02\x00\x04\x00\x02\x00\x04\x00\x03\x00\x03\x00\x03\x00\x05\x00\x04\x00\x02\x00\x04\x00\x06\x00\x02\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x00\x00\x00\x00\x03\x00\x04\x00\x02\x00\x03\x00\x01\x00\x00\x00\x02\x00\x00\x00\x01\x00\x02\x00\x01\x00\x03\x00\x02\x00\x05\x00\x05\x00\x04\x00\x04\x00\x06\x00\x04\x00\x04\x00\x03\x00\x03\x00\x02\x00\x03\x00\x04\x00\x05\x00\x07\x00\x06\x00\x07\x00\x06\x00\x04\x00\x04\x00\x04\x00\x02\x00\x04\x00\x02\x00\x03\x00\x02\x00\x03\x00\x03\x00\x06\x00\x02\x00\x02\x00\x03\x00\x04\x00\x03\x00\x03\x00\x02\x00\x06\x00\x02\x00\x00\x00\x00\x00\x01\x00\x03\x00\x01\x00\x00\x00\x01\x00\x02\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x05\x00\x02\x00\x04\x00\x05\x00\x02\x00\x00\x00\x00\x00\x02\x00\x04\x00\x00\x00\x01\x00\x01\x00\x03\x00\x02\x00\x00\x00\x01\x00\x02\x00\x02\x00\x02\x00\x01\x00\x03\x00\x01\x00\x00\x00\x02\x00\x02\x00\x03\x00\x02\x00\x01\x00\x02\x00\x02\x00\x01\x00\x03\x00\x02\x00\x03\x00\x03\x00\x04\x00\x03\x00\x00\x00\x00\x00\x05\x00\x01\x00\x03\x00\x02\x00\x01\x00\x03\x00\x01\x00\x00\x00\x01\x00\x02\x00\x03\x00\x02\x00\x01\x00\x03\x00\x03\x00\x03\x00\x03\x00\x04\x00\x01\x00\x01\x00\x02\x00\x02\x00\x06\x00\x03\x00\x03\x00\x05\x00\x02\x00\x02\x00\x03\x00\x00\x00\x01\x00\x00\x00\x03\x00\x02\x00\x05\x00\x03\x00\x00\x00\x07\x00\x02\x00\x05\x00\x05\x00\x00\x00\x00\x00\x05\x00\x02\x00\x04\x00\x03\x00\x06\x00\x04\x00\x03\x00\x05\x00\x05\x00\x06\x00\x07\x00\x03\x00\x07\x00\x05\x00\x03\x00\x04\x00\x02\x00\x02\x00\x01\x00\x02\x00\x07\x00\x05\x00\x02\x00\x02\x00\x02\x00\x02\x00\x04\x00\x03\x00\x03\x00\x03\x00\x06\x00\x02\x00\x02\x00\x00\x00\x01\x00\x03\x00\x01\x00\x03\x00\x06\x00\x00\x00\x00\x00\x02\x00\x03\x00\x05\x00\x03\x00\x07\x00\x02\x00\x02\x00\x03\x00\x05\x00\x02\x00\x03\x00\x05\x00\x07\x00\n\x00\x03\x00\x02\x00\x02\x00\x01\x00\x03\x00\x04\x00\x04\x00\x04\x00\x04\x00\x06\x00\x06\x00\x05\x00\x05\x00\x05\x00\x02\x00\x03\x00\x03\x00\x05\x00\x05\x00\x01\x00\x05\x00\x03\x00\x01\x00\x02\x00\x02\x00\x04\x00\x04\x00\x05\x00\x03\x00\x04\x00\x02\x00\x07\x00\x03\x00\x01\x00\x05\x00\x05\x00\x05\x00\x02\x00\x05\x00\x03\x00\x03\x00\x07\x00\x02\x00\x02\x00\x07\x00\x02\x00\x03\x00\x01\x00\x02\x00\x00\x00\x01\x00\x01\x00\x01\x00\x01\x00\x07\x00\x01\x00\x03\x00\x00\x00\x01\x00\x01\x00\x02\x00\x03\x00\x01\x00\x01\x00\x01\x00\x01\x00\x04\x00\x06\x00\x02\x00\x02\x00\x01\x00\x00\x00\x04\x00\x02\x00\x06\x00\x06\x00\x06\x00\x03\x00\x00\x00\x02\x00\x01\x00\x02\x00\x01\x00\x04\x00\x03\x00\x06\x00\x07\x00\x03\x00\x01\x00\x03\x00\x04\x00\x05\x00\x03\x00\x01\x00\x01\x00\x03\x00\x01\x00\x00\x00\x00\x00\x02\x00\x01\x00\x01\x00\x00\x00\x01\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x01\x00\x01\x00\x03\x00\x01\x00\x04\x00\x01\x00\x00\x00\x04\x00\x01\x00\x01\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x02\x00\x01\x00\x02\x00\x00\x00\x01\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x03\x00\x03\x00\x00\x00\x00\x00\x03\x00\x03\x00\x00\x00\x02\x00\x00\x00\x02\x00\x03\x00\x02\x00\x02\x00\x02\x00\x02\x00\x01\x00\x01\x00\x02\x00\x01\x00\x01\x00\x02\x00\x02\x00\x01\x00\x03\x00\x02\x00\x00\x00\x01\x00\x02\x00\x03\x00\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00\x01\x00\x02\x00\x01\x00\x01\x00\x01\x00\x03\x00\x01\x00\x04\x00\x00\x00\x01\x00\x05\x00\x00\x00\x03\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00\x01\x00\x01\x00\x01\x00\x05\x00\x00\x00\x03\x00\x05\x00\x02\x00\x00\x00\x00\x00\x01\x00\x02\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01\x00\x02\x00\x01\x00\x02\x00\x00\x00\x02\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x02\x00\x01\x00\x00\x00\x00\x00\x02\x00\x02\x00\x00\x00\x00\x00\x01\x00\x02\x00\x02\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00\x04\x00\x01\x00\x00\x00\x00\x00\x03\x00\x01\x00\x01\x00\x03\x00\x02\x00\x01\x00\x00\x00\x02\x00\x02\x00\x03\x00\x01\x00\x02\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00\x02\x00\x01\x00\x01\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\x00\x01\x00\x01\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01\x00\x01\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x04\x00\x00\x00\x02\x00\x02\x00\x02\x00\x01\x00\x03\x00\x00\x00\x03\x00\x01\x00\x01\x00\x00\x00\x00\x00\x02\x00\x03\x00\x01\x00\x02\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00\x03\x00\x00\x00\x02\x00\x02\x00\x02\x00\x03\x00\x01\x00\x01\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x02\x00\x01\x00\x00\x00\x02\x00\x01\x00\x02\x00\x01\x00\x03\x00\x02\x00\x02\x00\x00\x00\x01\x00\x02\x00\x01\x00\x00\x00\x02\x00\x01\x00\x00\x00\x00\x00\x01\x00\x01\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x01\x00\x02\x00\x01\x00\x01\x00\x04\x00\x01\x00\x03\x00\x02\x00\x02\x00\x04\x00\x01\x00\x00\x00\x02\x00\x00\x00\x00\x00\x01\x00\x02\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\x00\x01\x00\x01\x00\x01\x00\x01\x00\x00\x00\x00\x00\x01\x00\x01\x00\x02\x00\x01\x00\x00\x00\x03\x00\x01\x00\x04\x00\x01\x00\x00\x00\x04\x00\x01\x00\x01\x00\x02\x00\x07\x00\x01\x00\x01\x00\x00\x00\x02\x00\x02\x00\x03\x00\x04\x00\x01\x00\x04\x00\x01\x00\x00\x00\x02\x00\x01\x00\x01\x00\x00\x00\x02\x00\x01\x00\x00\x00\x03\x00\x00\x00\x02\x00\x01\x00\x02\x00\x01\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x01\x00\x01\x00\x00\x00\x02\x00\x02\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x00\x00\x00\x00\x02\x00\x03\x00\x01\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x01\x00\x00\x00\x02\x00\x02\x00\x01\x00\x01\x00\x02\x00\x03\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x04\x00\x00\x00\x02\x00\x01\x00\x03\x00\x04\x00\x01\x00\x03\x00\x01\x00\x00\x00\x02\x00\x00\x00\x00\x00\x01\x00\x02\x00\x03\x00\x00\x00\x00\x00\x01\x00\x03\x00\x00\x00\x00\x00\x02\x00\x02\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00\x00\x00\x00\x00\x01\x00\x02\x00\x02\x00\x02\x00\x00\x00\x02\x00\x01\x00\x00\x00\x00\x00\x06\x00\x08\x00\x07\x00\x03\x00\x00\x00\x01\x00\x05\x00\x01\x00\x01\x00\x03\x00\x08\x00\x06\x00\x05\x00\x04\x00\x02\x00\x01\x00\x02\x00\x04\x00\x00\x00\x01\x00\x01\x00\x02\x00\x01\x00\x02\x00\x00\x00\x03\x00\x00\x00\x02\x00\x01\x00\x01\x00\x01\x00\x00\x00\x02\x00\x02\x00\x02\x00\x04\x00\x04\x00\x03\x00\x02\x00\x01\x00\x01\x00\x03\x00\x01\x00\x03\x00\x01\x00\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x01\x00\x01\x00\x03\x00\x02\x00\x02\x00\x00\x00\x00\x00\x01\x00\x02\x00\x02\x00\x03\x00\x02\x00\x04\x00\x00\x00\x00\x00\x03\x00\x02\x00\x02\x00\x02\x00\x01\x00\x01\x00\x00\x00\x01\x00\x00\x00\x02\x00\x02\x00\x01\x00\x00\x00\x01\x00\x01\x00\x02\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x03\x00\x01\x00\x00\x00\x01\x00\x01\x00\x02\x00\x01\x00\x00\x00\x02\x00\x00\x00\x04\x00\x05\x00\x02\x00\x02\x00\x00\x00\x02\x00\x01\x00\x01\x00\x02\x00\x02\x00\x05\x00\x02\x00\x01\x00\x00\x00\x02\x00\x02\x00\x02\x00\x01\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\x00\x02\x00\x00\x00\x00\x00\x01\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\x00\x01\x00\x00\x00\x01\x00\x02\x00\x01\x00\x01\x00\x03\x00\x05\x00\x01\x00\x01\x00\x01\x00\x02\x00\x01\x00\x04\x00\x02\x00\x01\x00\x00\x00\x01\x00\x01\x00\x01\x00\x02\x00\x01\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x01\x00\x02\x00\x00\x00\x01\x00\x01\x00\x04\x00\x04\x00\x01\x00\x00\x00\x02\x00\x01\x00\x01\x00\x02\x00\x01\x00\x01\x00\x01\x00\x01\x00\x02\x00\x01\x00\x01\x00\x00\x00\x01\x00\x01\x00\x01\x00\x02\x00\x08\x00\x06\x00\x05\x00\x03\x00\x04\x00\x04\x00\x00\x00\x01\x00\x02\x00\x02\x00\x01\x00\x03\x00\x02\x00\x04\x00\x02\x00\x03\x00\x03\x00\x00\x00\x03\x00\x04\x00\x02\x00\x00\x00\x00\x00\x01\x00\x02\x00\x00\x00\x00\x00\x01\x00\x04\x00\x01\x00\x00\x00\x02\x00\x02\x00\x01\x00\x02\x00\x03\x00\x00\x00\x00\x00\x01\x00\x02\x00\x02\x00\x03\x00\x02\x00\x00\x00\x02\x00\x02\x00\x00\x00\x04\x00\x03\x00\x03\x00\x01\x00\x02\x00\x03\x00\x00\x00\x01\x00\x00\x00\x01\x00\x01\x00\x04\x00\x01\x00\x00\x00\x02\x00\x01\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x01\x00\x03\x00\x03\x00\x05\x00\x06\x00\x04\x00\x07\x00\x04\x00\x02\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x01\x00\x05\x00\x03\x00\x01\x00\t\x00\x05\x00\x00\x00\x01\x00\x00\x00\x01\x00\x01\x00\x00\x00\x01\x00\x00\x00\x03\x00\x02\x00\x01\x00\x01\x00\x04\x00\x01\x00\x01\x00\x00\x00\x02\x00\x03\x00\x01\x00\x05\x00\x02\x00\x04\x00\x01\x00\x01\x00\x01\x00\x00\x00\x04\x00\x03\x00\x02\x00\x02\x00\x01\x00\x02\x00\x02\x00\x00\x00\x01\x00\x01\x00\x02\x00\x02\x00\x03\x00\x03\x00\x03\x00\x02\x00\x00\x00\x01\x00\x02\x00\x00\x00\x01\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x03\x00\x02\x00\x01\x00\x01\x00\x00\x00\x02\x00\x01\x00\x02\x00\x01\x00\x01\x00\x02\x00\x01\x00\x01\x00\x05\x00\x06\x00\x03\x00\x02\x00\x02\x00\x02\x00\x02\x00\x01\x00\x03\x00\x03\x00\x01\x00\x02\x00\x01\x00\x01\x00\x01\x00\x02\x00\x06\x00\x01\x00\x04\x00\x00\x00\x01\x00\x02\x00\x01\x00\x00\x00\x01\x00\x00\x00\x04\x00\x02\x00\x04\x00\x02\x00\x01\x00\x01\x00\x06\x00\x05\x00\x00\x00\x02\x00\x01\x00\x01\x00\x04\x00\x00\x00\x04\x00\x02\x00\x04\x00\x07\x00\x01\x00\x01\x00', 0, 0, 0, 0, 302, 2000, 1), {})
Traceback (most recent call last):
  File "/Users/bene/mambaforge/envs/microeye/lib/python3.10/site-packages/omero/gateway/__init__.py", line 4870, in __call__
    return self.f(*args, **kwargs)
  File "/Users/bene/mambaforge/envs/microeye/lib/python3.10/site-packages/omero_api_RawPixelsStore_ice.py", line 1361, in setTile
    return _M_omero.api.RawPixelsStore._op_setTile.invoke(self, ((buf, z, c, t, x, y, w, h), _ctx))
omero.ApiUsageException: exception ::omero::ApiUsageException
{
    serverStackTrace = ome.conditions.ApiUsageException: can't getV3Length() on a null parameter
        at org.postgresql.core.v3.SimpleParameterList.getV3Length(SimpleParameterList.java:459)
        at org.postgresql.core.v3.QueryExecutorImpl.sendBind(QueryExecutorImpl.java:1679)
        at org.postgresql.core.v3.QueryExecutorImpl.sendOneQuery(QueryExecutorImpl.java:1922)
        at org.postgresql.core.v3.QueryExecutorImpl.sendQuery(QueryExecutorImpl.java:1445)
        at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:314)
        at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:481)
        at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:401)
        at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:164)
        at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:114)
        at bitronix.tm.resource.jdbc.proxy.PreparedStatementJavaProxy.executeQuery(PreparedStatementJavaProxy.java:102)
        at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
        at org.hibernate.loader.Loader.getResultSet(Loader.java:1953)
        at org.hibernate.loader.Loader.doQuery(Loader.java:802)
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
        at org.hibernate.loader.Loader.doList(Loader.java:2542)
        at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
        at org.hibernate.loader.Loader.list(Loader.java:2271)
        at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:316)
        at org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1842)
        at org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:165)
        at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:157)
        at ome.security.basic.BasicSecuritySystem$1.doInHibernate(BasicSecuritySystem.java:372)
        at ome.security.basic.BasicSecuritySystem$1.doInHibernate(BasicSecuritySystem.java:363)
        at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:411)
        at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:342)
        at ome.logic.QueryImpl.execute(QueryImpl.java:159)
        at ome.security.basic.BasicSecuritySystem.isGroupContextPermitted(BasicSecuritySystem.java:363)
        at ome.security.basic.BasicSecuritySystem.loadEventContext(BasicSecuritySystem.java:455)
        at ome.security.basic.EventHandler.doLogin(EventHandler.java:210)
        at ome.security.basic.EventHandler.invoke(EventHandler.java:146)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at ome.tools.hibernate.SessionHandler.doStateful(SessionHandler.java:216)
        at ome.tools.hibernate.SessionHandler.invoke(SessionHandler.java:200)
        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.$Proxy113.setTile(Unknown Source)
        at jdk.internal.reflect.GeneratedMethodAccessor895.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 ome.security.basic.BasicSecurityWiring.invoke(BasicSecurityWiring.java:93)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at ome.services.blitz.fire.AopContextInitializer.invoke(AopContextInitializer.java:43)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
        at com.sun.proxy.$Proxy113.setTile(Unknown Source)
        at jdk.internal.reflect.GeneratedMethodAccessor897.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 ome.services.blitz.util.IceMethodInvoker.invoke(IceMethodInvoker.java:172)
        at ome.services.throttling.Callback.run(Callback.java:56)
        at ome.services.throttling.InThreadThrottlingStrategy.callInvokerOnRawArgs(InThreadThrottlingStrategy.java:56)
        at ome.services.blitz.impl.AbstractAmdServant.callInvokerOnRawArgs(AbstractAmdServant.java:140)
        at ome.services.blitz.impl.RawPixelsStoreI.setTile_async(RawPixelsStoreI.java:289)
        at jdk.internal.reflect.GeneratedMethodAccessor896.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.$Proxy114.setTile_async(Unknown Source)
        at omero.api._RawPixelsStoreTie.setTile_async(_RawPixelsStoreTie.java:300)
        at omero.api._RawPixelsStoreDisp.___setTile(_RawPixelsStoreDisp.java:1228)
        at omero.api._RawPixelsStoreDisp.__dispatch(_RawPixelsStoreDisp.java:1788)
        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.ApiUsageException
    message = can't getV3Length() on a null parameter
}
2025-08-30 17:49:49 ERROR Failed to upload complete row 1: exception ::omero::ApiUsageException
{
    serverStackTrace = ome.conditions.ApiUsageException: can't getV3Length() on a null parameter
        at org.postgresql.core.v3.SimpleParameterList.getV3Length(SimpleParameterList.java:459)
        at org.postgresql.core.v3.QueryExecutorImpl.sendBind(QueryExecutorImpl.java:1679)
        at org.postgresql.core.v3.QueryExecutorImpl.sendOneQuery(QueryExecutorImpl.java:1922)
        at org.postgresql.core.v3.QueryExecutorImpl.sendQuery(QueryExecutorImpl.java:1445)
        at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:314)
        at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:481)
        at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:401)
        at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:164)
        at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:114)
        at bitronix.tm.resource.jdbc.proxy.PreparedStatementJavaProxy.executeQuery(PreparedStatementJavaProxy.java:102)
        at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
        at org.hibernate.loader.Loader.getResultSet(Loader.java:1953)
        at org.hibernate.loader.Loader.doQuery(Loader.java:802)
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
        at org.hibernate.loader.Loader.doList(Loader.java:2542)
        at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
        at org.hibernate.loader.Loader.list(Loader.java:2271)
        at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:316)
        at org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1842)
        at org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:165)
        at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:157)
        at ome.security.basic.BasicSecuritySystem$1.doInHibernate(BasicSecuritySystem.java:372)
        at ome.security.basic.BasicSecuritySystem$1.doInHibernate(BasicSecuritySystem.java:363)
        at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:411)
        at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:342)
        at ome.logic.QueryImpl.execute(QueryImpl.java:159)
        at ome.security.basic.BasicSecuritySystem.isGroupContextPermitted(BasicSecuritySystem.java:363)
        at ome.security.basic.BasicSecuritySystem.loadEventContext(BasicSecuritySystem.java:455)
        at ome.security.basic.EventHandler.doLogin(EventHandler.java:210)
        at ome.security.basic.EventHandler.invoke(EventHandler.java:146)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at ome.tools.hibernate.SessionHandler.doStateful(SessionHandler.java:216)
        at ome.tools.hibernate.SessionHandler.invoke(SessionHandler.java:200)
        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.$Proxy113.setTile(Unknown Source)
        at jdk.internal.reflect.GeneratedMethodAccessor895.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 ome.security.basic.BasicSecurityWiring.invoke(BasicSecurityWiring.java:93)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at ome.services.blitz.fire.AopContextInitializer.invoke(AopContextInitializer.java:43)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
        at com.sun.proxy.$Proxy113.setTile(Unknown Source)
        at jdk.internal.reflect.GeneratedMethodAccessor897.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 ome.services.blitz.util.IceMethodInvoker.invoke(IceMethodInvoker.java:172)
        at ome.services.throttling.Callback.run(Callback.java:56)
        at ome.services.throttling.InThreadThrottlingStrategy.callInvokerOnRawArgs(InThreadThrottlingStrategy.java:56)
        at ome.services.blitz.impl.AbstractAmdServant.callInvokerOnRawArgs(AbstractAmdServant.java:140)
        at ome.services.blitz.impl.RawPixelsStoreI.setTile_async(RawPixelsStoreI.java:289)
        at jdk.internal.reflect.GeneratedMethodAccessor896.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.$Proxy114.setTile_async(Unknown Source)
        at omero.api._RawPixelsStoreTie.setTile_async(_RawPixelsStoreTie.java:300)
        at omero.api._RawPixelsStoreDisp.___setTile(_RawPixelsStoreDisp.java:1228)
        at omero.api._RawPixelsStoreDisp.__dispatch(_RawPixelsStoreDisp.java:1788)
        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.ApiUsageException
    message = can't getV3Length() on a null parameter
}
ERROR:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Failed to upload complete row 1: exception ::omero::ApiUsageException
{
    serverStackTrace = ome.conditions.ApiUsageException: can't getV3Length() on a null parameter
        at org.postgresql.core.v3.SimpleParameterList.getV3Length(SimpleParameterList.java:459)
        at org.postgresql.core.v3.QueryExecutorImpl.sendBind(QueryExecutorImpl.java:1679)
        at org.postgresql.core.v3.QueryExecutorImpl.sendOneQuery(QueryExecutorImpl.java:1922)
        at org.postgresql.core.v3.QueryExecutorImpl.sendQuery(QueryExecutorImpl.java:1445)
        at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:314)
        at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:481)
        at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:401)
        at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:164)
        at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:114)
        at bitronix.tm.resource.jdbc.proxy.PreparedStatementJavaProxy.executeQuery(PreparedStatementJavaProxy.java:102)
        at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
        at org.hibernate.loader.Loader.getResultSet(Loader.java:1953)
        at org.hibernate.loader.Loader.doQuery(Loader.java:802)
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
        at org.hibernate.loader.Loader.doList(Loader.java:2542)
        at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
        at org.hibernate.loader.Loader.list(Loader.java:2271)
        at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:316)
        at org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1842)
        at org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:165)
        at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:157)
        at ome.security.basic.BasicSecuritySystem$1.doInHibernate(BasicSecuritySystem.java:372)
        at ome.security.basic.BasicSecuritySystem$1.doInHibernate(BasicSecuritySystem.java:363)
        at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:411)
        at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:342)
        at ome.logic.QueryImpl.execute(QueryImpl.java:159)
        at ome.security.basic.BasicSecuritySystem.isGroupContextPermitted(BasicSecuritySystem.java:363)
        at ome.security.basic.BasicSecuritySystem.loadEventContext(BasicSecuritySystem.java:455)
        at ome.security.basic.EventHandler.doLogin(EventHandler.java:210)
        at ome.security.basic.EventHandler.invoke(EventHandler.java:146)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at ome.tools.hibernate.SessionHandler.doStateful(SessionHandler.java:216)
        at ome.tools.hibernate.SessionHandler.invoke(SessionHandler.java:200)
        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.$Proxy113.setTile(Unknown Source)
        at jdk.internal.reflect.GeneratedMethodAccessor895.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 ome.security.basic.BasicSecurityWiring.invoke(BasicSecurityWiring.java:93)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at ome.services.blitz.fire.AopContextInitializer.invoke(AopContextInitializer.java:43)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
        at com.sun.proxy.$Proxy113.setTile(Unknown Source)
        at jdk.internal.reflect.GeneratedMethodAccessor897.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 ome.services.blitz.util.IceMethodInvoker.invoke(IceMethodInvoker.java:172)
        at ome.services.throttling.Callback.run(Callback.java:56)
        at ome.services.throttling.InThreadThrottlingStrategy.callInvokerOnRawArgs(InThreadThrottlingStrategy.java:56)
        at ome.services.blitz.impl.AbstractAmdServant.callInvokerOnRawArgs(AbstractAmdServant.java:140)
        at ome.services.blitz.impl.RawPixelsStoreI.setTile_async(RawPixelsStoreI.java:289)
        at jdk.internal.reflect.GeneratedMethodAccessor896.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.$Proxy114.setTile_async(Unknown Source)
        at omero.api._RawPixelsStoreTie.setTile_async(_RawPixelsStoreTie.java:300)
        at omero.api._RawPixelsStoreDisp.___setTile(_RawPixelsStoreDisp.java:1228)
        at omero.api._RawPixelsStoreDisp.__dispatch(_RawPixelsStoreDisp.java:1788)
        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.ApiUsageException
    message = can't getV3Length() on a null parameter
}
2025-08-30 17:49:50 ERROR Failed to buffer tile 0,1 for row upload: exception ::omero::ApiUsageException
{
    serverStackTrace = ome.conditions.ApiUsageException: can't getV3Length() on a null parameter
        at org.postgresql.core.v3.SimpleParameterList.getV3Length(SimpleParameterList.java:459)
        at org.postgresql.core.v3.QueryExecutorImpl.sendBind(QueryExecutorImpl.java:1679)
        at org.postgresql.core.v3.QueryExecutorImpl.sendOneQuery(QueryExecutorImpl.java:1922)
        at org.postgresql.core.v3.QueryExecutorImpl.sendQuery(QueryExecutorImpl.java:1445)
        at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:314)
        at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:481)
        at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:401)
        at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:164)
        at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:114)
        at bitronix.tm.resource.jdbc.proxy.PreparedStatementJavaProxy.executeQuery(PreparedStatementJavaProxy.java:102)
        at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
        at org.hibernate.loader.Loader.getResultSet(Loader.java:1953)
        at org.hibernate.loader.Loader.doQuery(Loader.java:802)
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
        at org.hibernate.loader.Loader.doList(Loader.java:2542)
        at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
        at org.hibernate.loader.Loader.list(Loader.java:2271)
        at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:316)
        at org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1842)
        at org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:165)
        at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:157)
        at ome.security.basic.BasicSecuritySystem$1.doInHibernate(BasicSecuritySystem.java:372)
        at ome.security.basic.BasicSecuritySystem$1.doInHibernate(BasicSecuritySystem.java:363)
        at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:411)
        at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:342)
        at ome.logic.QueryImpl.execute(QueryImpl.java:159)
        at ome.security.basic.BasicSecuritySystem.isGroupContextPermitted(BasicSecuritySystem.java:363)
        at ome.security.basic.BasicSecuritySystem.loadEventContext(BasicSecuritySystem.java:455)
        at ome.security.basic.EventHandler.doLogin(EventHandler.java:210)
        at ome.security.basic.EventHandler.invoke(EventHandler.java:146)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at ome.tools.hibernate.SessionHandler.doStateful(SessionHandler.java:216)
        at ome.tools.hibernate.SessionHandler.invoke(SessionHandler.java:200)
        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.$Proxy113.setTile(Unknown Source)
        at jdk.internal.reflect.GeneratedMethodAccessor895.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 ome.security.basic.BasicSecurityWiring.invoke(BasicSecurityWiring.java:93)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at ome.services.blitz.fire.AopContextInitializer.invoke(AopContextInitializer.java:43)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
        at com.sun.proxy.$Proxy113.setTile(Unknown Source)
        at jdk.internal.reflect.GeneratedMethodAccessor897.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 ome.services.blitz.util.IceMethodInvoker.invoke(IceMethodInvoker.java:172)
        at ome.services.throttling.Callback.run(Callback.java:56)
        at ome.services.throttling.InThreadThrottlingStrategy.callInvokerOnRawArgs(InThreadThrottlingStrategy.java:56)
        at ome.services.blitz.impl.AbstractAmdServant.callInvokerOnRawArgs(AbstractAmdServant.java:140)
        at ome.services.blitz.impl.RawPixelsStoreI.setTile_async(RawPixelsStoreI.java:289)
        at jdk.internal.reflect.GeneratedMethodAccessor896.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.$Proxy114.setTile_async(Unknown Source)
        at omero.api._RawPixelsStoreTie.setTile_async(_RawPixelsStoreTie.java:300)
        at omero.api._RawPixelsStoreDisp.___setTile(_RawPixelsStoreDisp.java:1228)
        at omero.api._RawPixelsStoreDisp.__dispatch(_RawPixelsStoreDisp.java:1788)
        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.ApiUsageException
    message = can't getV3Length() on a null parameter
}
ERROR:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Failed to buffer tile 0,1 for row upload: exception ::omero::ApiUsageException
{
    serverStackTrace = ome.conditions.ApiUsageException: can't getV3Length() on a null parameter
        at org.postgresql.core.v3.SimpleParameterList.getV3Length(SimpleParameterList.java:459)
        at org.postgresql.core.v3.QueryExecutorImpl.sendBind(QueryExecutorImpl.java:1679)
        at org.postgresql.core.v3.QueryExecutorImpl.sendOneQuery(QueryExecutorImpl.java:1922)
        at org.postgresql.core.v3.QueryExecutorImpl.sendQuery(QueryExecutorImpl.java:1445)
        at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:314)
        at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:481)
        at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:401)
        at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:164)
        at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:114)
        at bitronix.tm.resource.jdbc.proxy.PreparedStatementJavaProxy.executeQuery(PreparedStatementJavaProxy.java:102)
        at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
        at org.hibernate.loader.Loader.getResultSet(Loader.java:1953)
        at org.hibernate.loader.Loader.doQuery(Loader.java:802)
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
        at org.hibernate.loader.Loader.doList(Loader.java:2542)
        at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
        at org.hibernate.loader.Loader.list(Loader.java:2271)
        at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:316)
        at org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1842)
        at org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:165)
        at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:157)
        at ome.security.basic.BasicSecuritySystem$1.doInHibernate(BasicSecuritySystem.java:372)
        at ome.security.basic.BasicSecuritySystem$1.doInHibernate(BasicSecuritySystem.java:363)
        at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:411)
        at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:342)
        at ome.logic.QueryImpl.execute(QueryImpl.java:159)
        at ome.security.basic.BasicSecuritySystem.isGroupContextPermitted(BasicSecuritySystem.java:363)
        at ome.security.basic.BasicSecuritySystem.loadEventContext(BasicSecuritySystem.java:455)
        at ome.security.basic.EventHandler.doLogin(EventHandler.java:210)
        at ome.security.basic.EventHandler.invoke(EventHandler.java:146)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at ome.tools.hibernate.SessionHandler.doStateful(SessionHandler.java:216)
        at ome.tools.hibernate.SessionHandler.invoke(SessionHandler.java:200)
        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.$Proxy113.setTile(Unknown Source)
        at jdk.internal.reflect.GeneratedMethodAccessor895.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 ome.security.basic.BasicSecurityWiring.invoke(BasicSecurityWiring.java:93)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at ome.services.blitz.fire.AopContextInitializer.invoke(AopContextInitializer.java:43)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
        at com.sun.proxy.$Proxy113.setTile(Unknown Source)
        at jdk.internal.reflect.GeneratedMethodAccessor897.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 ome.services.blitz.util.IceMethodInvoker.invoke(IceMethodInvoker.java:172)
        at ome.services.throttling.Callback.run(Callback.java:56)
        at ome.services.throttling.InThreadThrottlingStrategy.callInvokerOnRawArgs(InThreadThrottlingStrategy.java:56)
        at ome.services.blitz.impl.AbstractAmdServant.callInvokerOnRawArgs(AbstractAmdServant.java:140)
        at ome.services.blitz.impl.RawPixelsStoreI.setTile_async(RawPixelsStoreI.java:289)
        at jdk.internal.reflect.GeneratedMethodAccessor896.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.$Proxy114.setTile_async(Unknown Source)
        at omero.api._RawPixelsStoreTie.setTile_async(_RawPixelsStoreTie.java:300)
        at omero.api._RawPixelsStoreDisp.___setTile(_RawPixelsStoreDisp.java:1228)
        at omero.api._RawPixelsStoreDisp.__dispatch(_RawPixelsStoreDisp.java:1788)
        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.ApiUsageException
    message = can't getV3Length() on a null parameter
}
2025-08-30 17:49:52 ERROR Failed to upload tile (0, 1): exception ::omero::ApiUsageException
{
    serverStackTrace = ome.conditions.ApiUsageException: can't getV3Length() on a null parameter
        at org.postgresql.core.v3.SimpleParameterList.getV3Length(SimpleParameterList.java:459)
        at org.postgresql.core.v3.QueryExecutorImpl.sendBind(QueryExecutorImpl.java:1679)
        at org.postgresql.core.v3.QueryExecutorImpl.sendOneQuery(QueryExecutorImpl.java:1922)
        at org.postgresql.core.v3.QueryExecutorImpl.sendQuery(QueryExecutorImpl.java:1445)
        at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:314)
        at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:481)
        at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:401)
        at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:164)
        at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:114)
        at bitronix.tm.resource.jdbc.proxy.PreparedStatementJavaProxy.executeQuery(PreparedStatementJavaProxy.java:102)
        at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
        at org.hibernate.loader.Loader.getResultSet(Loader.java:1953)
        at org.hibernate.loader.Loader.doQuery(Loader.java:802)
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
        at org.hibernate.loader.Loader.doList(Loader.java:2542)
        at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
        at org.hibernate.loader.Loader.list(Loader.java:2271)
        at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:316)
        at org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1842)
        at org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:165)
        at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:157)
        at ome.security.basic.BasicSecuritySystem$1.doInHibernate(BasicSecuritySystem.java:372)
        at ome.security.basic.BasicSecuritySystem$1.doInHibernate(BasicSecuritySystem.java:363)
        at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:411)
        at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:342)
        at ome.logic.QueryImpl.execute(QueryImpl.java:159)
        at ome.security.basic.BasicSecuritySystem.isGroupContextPermitted(BasicSecuritySystem.java:363)
        at ome.security.basic.BasicSecuritySystem.loadEventContext(BasicSecuritySystem.java:455)
        at ome.security.basic.EventHandler.doLogin(EventHandler.java:210)
        at ome.security.basic.EventHandler.invoke(EventHandler.java:146)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at ome.tools.hibernate.SessionHandler.doStateful(SessionHandler.java:216)
        at ome.tools.hibernate.SessionHandler.invoke(SessionHandler.java:200)
        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.$Proxy113.setTile(Unknown Source)
        at jdk.internal.reflect.GeneratedMethodAccessor895.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 ome.security.basic.BasicSecurityWiring.invoke(BasicSecurityWiring.java:93)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at ome.services.blitz.fire.AopContextInitializer.invoke(AopContextInitializer.java:43)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
        at com.sun.proxy.$Proxy113.setTile(Unknown Source)
        at jdk.internal.reflect.GeneratedMethodAccessor897.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 ome.services.blitz.util.IceMethodInvoker.invoke(IceMethodInvoker.java:172)
        at ome.services.throttling.Callback.run(Callback.java:56)
        at ome.services.throttling.InThreadThrottlingStrategy.callInvokerOnRawArgs(InThreadThrottlingStrategy.java:56)
        at ome.services.blitz.impl.AbstractAmdServant.callInvokerOnRawArgs(AbstractAmdServant.java:140)
        at ome.services.blitz.impl.RawPixelsStoreI.setTile_async(RawPixelsStoreI.java:289)
        at jdk.internal.reflect.GeneratedMethodAccessor896.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.$Proxy114.setTile_async(Unknown Source)
        at omero.api._RawPixelsStoreTie.setTile_async(_RawPixelsStoreTie.java:300)
        at omero.api._RawPixelsStoreDisp.___setTile(_RawPixelsStoreDisp.java:1228)
        at omero.api._RawPixelsStoreDisp.__dispatch(_RawPixelsStoreDisp.java:1788)
        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.ApiUsageException
    message = can't getV3Length() on a null parameter
}
ERROR:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Failed to upload tile (0, 1): exception ::omero::ApiUsageException
{
    serverStackTrace = ome.conditions.ApiUsageException: can't getV3Length() on a null parameter
        at org.postgresql.core.v3.SimpleParameterList.getV3Length(SimpleParameterList.java:459)
        at org.postgresql.core.v3.QueryExecutorImpl.sendBind(QueryExecutorImpl.java:1679)
        at org.postgresql.core.v3.QueryExecutorImpl.sendOneQuery(QueryExecutorImpl.java:1922)
        at org.postgresql.core.v3.QueryExecutorImpl.sendQuery(QueryExecutorImpl.java:1445)
        at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:314)
        at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:481)
        at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:401)
        at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:164)
        at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:114)
        at bitronix.tm.resource.jdbc.proxy.PreparedStatementJavaProxy.executeQuery(PreparedStatementJavaProxy.java:102)
        at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
        at org.hibernate.loader.Loader.getResultSet(Loader.java:1953)
        at org.hibernate.loader.Loader.doQuery(Loader.java:802)
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
        at org.hibernate.loader.Loader.doList(Loader.java:2542)
        at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
        at org.hibernate.loader.Loader.list(Loader.java:2271)
        at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:316)
        at org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1842)
        at org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:165)
        at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:157)
        at ome.security.basic.BasicSecuritySystem$1.doInHibernate(BasicSecuritySystem.java:372)
        at ome.security.basic.BasicSecuritySystem$1.doInHibernate(BasicSecuritySystem.java:363)
        at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:411)
        at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:342)
        at ome.logic.QueryImpl.execute(QueryImpl.java:159)
        at ome.security.basic.BasicSecuritySystem.isGroupContextPermitted(BasicSecuritySystem.java:363)
        at ome.security.basic.BasicSecuritySystem.loadEventContext(BasicSecuritySystem.java:455)
        at ome.security.basic.EventHandler.doLogin(EventHandler.java:210)
        at ome.security.basic.EventHandler.invoke(EventHandler.java:146)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at ome.tools.hibernate.SessionHandler.doStateful(SessionHandler.java:216)
        at ome.tools.hibernate.SessionHandler.invoke(SessionHandler.java:200)
        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.$Proxy113.setTile(Unknown Source)
        at jdk.internal.reflect.GeneratedMethodAccessor895.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 ome.security.basic.BasicSecurityWiring.invoke(BasicSecurityWiring.java:93)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at ome.services.blitz.fire.AopContextInitializer.invoke(AopContextInitializer.java:43)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
        at com.sun.proxy.$Proxy113.setTile(Unknown Source)
        at jdk.internal.reflect.GeneratedMethodAccessor897.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 ome.services.blitz.util.IceMethodInvoker.invoke(IceMethodInvoker.java:172)
        at ome.services.throttling.Callback.run(Callback.java:56)
        at ome.services.throttling.InThreadThrottlingStrategy.callInvokerOnRawArgs(InThreadThrottlingStrategy.java:56)
        at ome.services.blitz.impl.AbstractAmdServant.callInvokerOnRawArgs(AbstractAmdServant.java:140)
        at ome.services.blitz.impl.RawPixelsStoreI.setTile_async(RawPixelsStoreI.java:289)
        at jdk.internal.reflect.GeneratedMethodAccessor896.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.$Proxy114.setTile_async(Unknown Source)
        at omero.api._RawPixelsStoreTie.setTile_async(_RawPixelsStoreTie.java:300)
        at omero.api._RawPixelsStoreDisp.___setTile(_RawPixelsStoreDisp.java:1228)
        at omero.api._RawPixelsStoreDisp.__dispatch(_RawPixelsStoreDisp.java:1788)
        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.ApiUsageException
    message = can't getV3Length() on a null parameter
}
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Processing tile (0, 2) for row buffer, key: (2, 0, 0, 0)
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Created new row buffer for row 2
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Added tile 0 to row 2, now has 1/5 tiles
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Row 2 still incomplete (1/5 tiles), waiting for more tiles...
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Processing tile (1, 2) for row buffer, key: (2, 0, 0, 0)
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Added tile 1 to row 2, now has 2/5 tiles
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Row 2 still incomplete (2/5 tiles), waiting for more tiles...
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Processing tile (2, 2) for row buffer, key: (2, 0, 0, 0)
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Added tile 2 to row 2, now has 3/5 tiles
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Row 2 still incomplete (3/5 tiles), waiting for more tiles...
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Processing tile (3, 2) for row buffer, key: (2, 0, 0, 0)
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Added tile 3 to row 2, now has 4/5 tiles
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Row 2 still incomplete (4/5 tiles), waiting for more tiles...
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Processing tile (4, 2) for row buffer, key: (2, 0, 0, 0)
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Added tile 4 to row 2, now has 5/5 tiles
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Uploading complete row 2 at y=600, size=2000x300
INFO:     127.0.0.1:61910 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
INFO:     127.0.0.1:61910 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
INFO:     127.0.0.1:61918 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
INFO:     127.0.0.1:61924 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
INFO:     127.0.0.1:61924 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
INFO:     127.0.0.1:61929 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Cleaned up completed row buffer for row 2
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Processing tile (4, 3) for row buffer, key: (3, 0, 0, 0)
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Created new row buffer for row 3
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Added tile 4 to row 3, now has 1/5 tiles
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Row 3 still incomplete (1/5 tiles), waiting for more tiles...
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Processing tile (3, 3) for row buffer, key: (3, 0, 0, 0)
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Added tile 3 to row 3, now has 2/5 tiles
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Row 3 still incomplete (2/5 tiles), waiting for more tiles...
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Processing tile (2, 3) for row buffer, key: (3, 0, 0, 0)
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Added tile 2 to row 3, now has 3/5 tiles
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Row 3 still incomplete (3/5 tiles), waiting for more tiles...
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Processing tile (1, 3) for row buffer, key: (3, 0, 0, 0)
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Added tile 1 to row 3, now has 4/5 tiles
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Row 3 still incomplete (4/5 tiles), waiting for more tiles...
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Processing tile (0, 3) for row buffer, key: (3, 0, 0, 0)
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Added tile 0 to row 3, now has 5/5 tiles
DEBUG:imswitch.imcontrol.controller.controllers.experiment_controller.omero_uploader:Uploading complete row 3 at y=900, size=2000x300
INFO:     127.0.0.1:61929 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
INFO:     127.0.0.1:61937 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
INFO:     127.0.0.1:61944 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
INFO:     127.0.0.1:61944 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK
INFO:     127.0.0.1:61957 - "GET /ExperimentController/getExperimentStatus HTTP/1.1" 200 OK

Co-authored-by: openuc2-gmbh <218447657+openuc2-gmbh@users.noreply.github.com>
Copy link
Author

Copilot AI commented Aug 30, 2025

@copilot I think currently, the image scanning can finish faster than uploading the images. Especially if we first have to collect the rows and then upload these. This takes time. The way the locks ar...

Fixed the threading race condition and incomplete upload issues. The problem was that the worker thread would stop processing when self.running = False even if there were still tiles in the queue or incomplete rows in buffers.

Key fixes implemented:

  • Queue drainage: Worker thread now continues processing until both stop is requested AND queue is empty
  • Thread coordination: Added proper signaling with _worker_finished event
  • Lock safety: Added timeout-based lock acquisition in _upload_remaining_rows() to prevent deadlocks
  • Completion signaling: OMEWriter now calls signal_completion() when acquisition finishes
  • Incomplete row handling: Added padding for incomplete rows during finalization

The worker now uses get(timeout=0.1) to periodically check the stop condition while continuing to process remaining tiles. This ensures all captured tiles are uploaded before the thread stops.

Commit: ca0bef4

@Copilot Copilot AI changed the title Implement parallelized OMERO upload for all experiment types with ROMIO backend support Implement parallelized OMERO upload with robust threading and complete queue drainage Aug 30, 2025
Copilot finished work on behalf of openuc2-gmbh August 30, 2025 15:57
Refactored the row upload logic to upload the entire row at once instead of iterating and uploading each stripe individually. This improves efficiency and simplifies the code.
@openuc2-gmbh
Copy link

@copilot this in large parts works already, now we need to ensure that this is also working for

  • timelapse imaging
  • z-stack imaging

It seems like the dataset is created (I see it in the omero webtool), but not uploaded, maybe since the old dataset wasn't closed properly or so. The first dataset / timepoint is uploaded and created succesfully. Also, it would be idea, if we detect that we take a timelapse dataset to store these in the same dataset but along the t channel.

error I get so far when saving two timepoints:
error.txt

Co-authored-by: openuc2-gmbh <218447657+openuc2-gmbh@users.noreply.github.com>
Copy link
Author

Copilot AI commented Sep 1, 2025

@copilot this in large parts works already, now we need to ensure that this is also working for

  • timelapse imaging
  • z-stack imaging
    ...

I've implemented comprehensive OMERO support for timelapse and z-stack imaging. The key changes address the issue where each timepoint was creating separate datasets instead of using a single dataset with proper time/z indexing.

Key fixes implemented:

  1. Shared OMERO Uploaders: Created a registry system where timelapse/z-stack experiments reuse the same OMERO uploader, dataset, and image across all timepoints
  2. Proper Dataset Reuse: Added reuse_dataset_id and reuse_image_id parameters to coordinate upload to the same OMERO objects
  3. Correct Dimensions: Updated mosaic configuration to use full timepoint (n_times) and z-plane (len(z_positions)) ranges
  4. Single Dataset Strategy: All timepoints/z-planes now upload to one dataset with data properly indexed along the t and z channels

Changes made:

  • Enhanced OMEROConnectionParams with reuse parameters for dataset/image coordination
  • Modified OMEWriter to support shared OMERO uploaders via class-level registry
  • Updated experiment controller to create shared writers once per experiment (not per timepoint)
  • Added proper cleanup of shared uploaders when experiments complete

This ensures timelapse datasets are stored in the same dataset along the t-channel as requested, and z-stack data is properly indexed along the z-channel. The first timepoint creates the dataset/image, and subsequent timepoints reuse the same OMERO objects.

Commit: 2ca05b3

@Copilot Copilot AI changed the title Implement parallelized OMERO upload with robust threading and complete queue drainage Implement comprehensive OMERO upload with timelapse/z-stack support and robust threading Sep 1, 2025
Copilot finished work on behalf of openuc2-gmbh September 1, 2025 04:49
Introduces CSV logging functionality to FocusLockController, recording focus measurements, lock state, positions, and PID output. Also adds saving of crop parameters to the config file for improved reproducibility.
Introduces internal tracking of the Z stage position in FocusLockController to avoid repeated hardware polling, updates all relevant methods to use the cached position, and renames the PID controller variable for clarity. Also removes the obsolete PixelCalibrationController_OLD.py file.
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.

Parallelized OMERO Upload via ExperimentController Queue

3 participants