Skip to content

Import mit omero-py bricht ohne Fehlermeldung ab

Unser Ziel ist es, Bilddaten in einer Verzeichnisstruktur im (lokalen) Dateisystem zusammen mit Metadaten in OMERO mit omero-py zu importieren. Die Verzeichnisnamen, in denen sich die Bilddaten befinden sollen dabei in OMERO als Projekte und Datensätze abgebildet werden. Metadaten sind in CSV-Dateien hinterlegt und sollen als Schlüssel-Wert-Paare hinterlegt werden. Die Zuordnung erfolgt über den Dateinamen.

Das Script friert während der Ausführung in unregelmäßigen Abständen ein. Das passiert teilweise innerhalb der ersten Minuten nach Ausführung oder nach mehreren Tausend importierten Bildern. Weder auf Clientseite wo das Script ausgeführt wird noch auf Serverseite sind offensichtliche Fehler in den Logs ersichtlich.

Für das Script benötigt man die Bilddaten und CSVs.

Im Script müssen die Pfade DIR_CSV (CSV-Verzeichnis) und DIR_EXTRACTED (Bild-Verzeichnis) angepasst werden:

import omero
from getpass import getpass
from omero.gateway import BlitzGateway, DatasetWrapper
from omero.model import ProjectI,DatasetI
import glob
import numpy as np
from PIL import Image
import json
from omero.rtypes import rstring, rint
import csv
import os
import pandas
from pathlib import Path
import tifffile

DIR_CSV = '/csv'
PREFIX_CSV = 'elena-classifications-21-11-22-'
DIR_EXTRACTED='/extracted'

DEFAULT_GROUP = 'default'
DEFAULT_HOST = 'omero.intranet.ufz.de'
DEFAULT_PORT = 4064

USERNAME = input('Username: ')
PASSWORD = getpass('Password: ')
GROUP = input(f'Group ({DEFAULT_GROUP}): ') or DEFAULT_GROUP
HOST = input(f'Host ({DEFAULT_HOST}): ') or DEFAULT_HOST
PORT = input(f'Port ({DEFAULT_PORT}): ') or DEFAULT_PORT

print(f'USERNAME:{USERNAME} PASSWORD:[redacted] GROUP:{GROUP} HOST:{HOST} PORT:{PORT}')

def get_or_create_project(project):
    projects = list(conn.getObjects("Project", attributes={"name": project}))
    if len(projects) == 0:
        project_obj = ProjectI()
        project_obj.setName(omero.rtypes.rstring(project))
        
        project_obj = conn.getUpdateService().saveAndReturnObject(project_obj, conn.SERVICE_OPTS)

    else:
        project_obj = projects[0]
    return project_obj

def get_or_create_dataset(project_obj, dataset_name):
    datasets = list(conn.getObjects("Dataset", attributes={"name": dataset_name}))
    if len(datasets) == 0:
        dataset_obj = DatasetI()
        dataset_obj.setName(omero.rtypes.rstring(dataset_name))
        
        dataset_obj = conn.getUpdateService().saveAndReturnObject(dataset_obj, conn.SERVICE_OPTS)

        link = omero.model.ProjectDatasetLinkI()
        link.setChild(omero.model.DatasetI(dataset_obj.id.val, False))
        link.setParent(omero.model.ProjectI(project_obj.id, False))
        conn.getUpdateService().saveObject(link)

    else:
        dataset_obj = datasets[0]

    return dataset_obj

def plane_gen(image):
    for c in range(image.shape[-1]):
        yield image[:,:,c]

def import_image(tif_file, dataset_obj, dataset_name):        
    filename = os.path.basename(tif_file)
    image = tifffile.imread(tif_file)
    image_obj = conn.createImageFromNumpySeq(
        plane_gen(image), filename, sizeZ=1, sizeC=image.shape[-1], sizeT=1, dataset=dataset_obj)

    key_value_data = df.loc[df['dir2'] == dataset_name].loc[df['filename'] == filename][['pred1 name','pred1 probability','pred2 name','pred2 probability','pred3 name','pred3 probability']].T.reset_index().astype(str).values.tolist()
    map_ann = omero.gateway.MapAnnotationWrapper(conn)

    namespace = omero.constants.metadata.NSCLIENTMAPANNOTATION
    map_ann.setNs(namespace)
    map_ann.setValue(key_value_data)
    map_ann.save()
    image_obj.linkAnnotation(map_ann)


conn = BlitzGateway(USERNAME, PASSWORD, host=HOST, port=PORT, group=GROUP, secure=True)
conn.connect()

for project_name in next(os.walk(DIR_EXTRACTED))[1]:
    print(f'Project: {project_name}')
    file = f'{DIR_CSV}/{PREFIX_CSV}{project_name}.csv'
    df = pandas.read_csv(file)

    project_obj = get_or_create_project(project_name)
    SUBDIR = f'{DIR_EXTRACTED}/{project_name}'

    for dataset_name in next(os.walk(SUBDIR))[1]:

        dataset_obj = get_or_create_dataset(project_obj, dataset_name)

        tif_files = list(Path(f'{SUBDIR}/{dataset_name}').rglob('*.tif'))

        i = 0
        for tif_file in tif_files:
            import_image(tif_file, dataset_obj, dataset_name)
            i += 1
            print(f'\r-> Dataset: {dataset_name} - {i} images imported...', end='', flush=True)
            
conn.close()

Dockerfile mit Jupyter Notebook und allen Dependencies für obiges Script:

FROM alpine:3.9

RUN apk add --no-cache sudo bash libffi-dev build-base zlib-dev jpeg-dev python3-dev openssl-dev bzip2-dev openjdk8

ENV PYTHONUNBUFFERED=1
RUN apk add --update --no-cache python3 && ln -sf python3 /usr/bin/python

RUN python3 -m ensurepip
RUN pip3 install --no-cache-dir --upgrade pip setuptools wheel
RUN pip3 install --no-cache-dir --global-option=build_ext --global-option="-D__USE_UNIX98" omero-py
RUN pip3 install --no-cache-dir jupyter omero-cli-duplicate pandas xlrd pillow tifffile

RUN mkdir /src
WORKDIR /src

CMD ["jupyter", "notebook", "--port=8888", "--no-browser", "--ip=0.0.0.0", "--allow-root"]
docker build -t omero-py .
docker run -p 8888:8888 -v $HOME/path/to/extracted:/extracted -v $HOME/path/to/csv:/csv omero-py

Ich habe das Blitz.log mit dem Zeitpunkt des Abbruchs hochgeladen. Es ist kein Fehler erkennbar, ggf. stimmt aber etwas mit dem Session-Management nicht.

omero-log.txt

Edited by Daniel Lahr