Ajuda para Importar Grande Volume de Arquivos DICOM para o Orthanc de Forma Automática

Hello

If you know some Python, you could start with a script such as this one below.

The idea is to :

  • Walk your directory tree to find all .7z files
  • For each .7z file, uncompress it to a temporary folder and process all the files that are extracted
  • For each extracted file, upload it to Orthanc thanks to a POST to the /instances endpoint
  • when all the files in .7z archive have been uploaded, move the .7z file to a “finished” directory tree, by replicating the same relative path, so that the finished directory keeps the exact same layout as the initial source directory (you might want to disable this specific step unless you have validated that the script works correctly!)

In addition, in order to not overload Orthanc, a semaphore is used that will limit the number of concurrent uploads to 30.

I just defined the overall architecture and asked chatGPT to generate the skeleton : i have NOT attempted to run it. The code looks exactly like what I asked, though.

Packages required here: aiohttp aiofiles py7zr

Hopefully , if you have some programming knowledge, this should lead you in the right direction.

Feel free to ask questions.

HTH

Benjamin

import os
import asyncio
import aiohttp
import aiofiles
import py7zr
import tempfile
import shutil
from pathlib import Path

async def main():
    root_dir = '/path/to/input/directory'
    finished_dir = '/path/to/finished/directory'
    upload_url = 'http://orthanc-server/instances'
    max_concurrent_posts = 30
    semaphore = asyncio.Semaphore(max_concurrent_posts)
    
    # Find all .7z files
    seven_z_files = find_7z_files(root_dir)
    
    for seven_z_file in seven_z_files:
        print(f"Processing {seven_z_file}")
        await process_7z_file(seven_z_file, upload_url, semaphore)
        # After processing, move the .7z file to the finished directory
        move_to_finished(seven_z_file, root_dir, finished_dir)

def find_7z_files(root_dir):
    seven_z_files = []
    for dirpath, dirnames, filenames in os.walk(root_dir):
        for filename in filenames:
            if filename.endswith('.7z'):
                seven_z_files.append(os.path.join(dirpath, filename))
    return seven_z_files

async def process_7z_file(seven_z_file, upload_url, semaphore):
    # Extract to a temporary directory
    with tempfile.TemporaryDirectory() as tmpdirname:
        with py7zr.SevenZipFile(seven_z_file, mode='r') as z:
            z.extractall(path=tmpdirname)
        # Now, get all files in the temp directory
        file_paths = []
        for dirpath, dirnames, filenames in os.walk(tmpdirname):
            for filename in filenames:
                file_paths.append(os.path.join(dirpath, filename))
        
        # Create an aiohttp session
        async with aiohttp.ClientSession() as session:
            # Create tasks for uploading files
            tasks = []
            for file_path in file_paths:
                task = asyncio.create_task(upload_file(file_path, upload_url, semaphore, session))
                tasks.append(task)
            # Wait for all uploads to complete
            await asyncio.gather(*tasks)

async def upload_file(file_path, upload_url, semaphore, session):
    async with semaphore:
        # Load file into memory
        async with aiofiles.open(file_path, 'rb') as f:
            data = await f.read()
        # Perform POST request
        try:
            async with session.post(upload_url, data=data) as resp:
                if resp.status == 200 or resp.status == 201:
                    print(f"Uploaded {file_path}")
                else:
                    print(f"Failed to upload {file_path}, status code: {resp.status}")
        except Exception as e:
            print(f"Error uploading {file_path}: {e}")

def move_to_finished(seven_z_file, root_dir, finished_dir):
    # Get the relative path
    relative_path = os.path.relpath(seven_z_file, root_dir)
    # Destination path
    dest_path = os.path.join(finished_dir, relative_path)
    # Ensure the destination directory exists
    dest_dir = os.path.dirname(dest_path)
    os.makedirs(dest_dir, exist_ok=True)
    # Move the file
    shutil.move(seven_z_file, dest_path)

if __name__ == '__main__':
    asyncio.run(main())
2 Likes