routing images to another modality

Is it possible to route(in one command, without storing the dicom file in Orthanc) to another modality?
I know I can store dicoms into Orthanc, then get store it to another modality. But I need this without storing the dicom in Orthanc.
Is this possible?

You probably don’t need a full DICOM server to this end. Have a look at the “storescu” command-line tools from dcm4che and DCMTK, or at “gdcmscu” from GDCM.

Thanks Sébastien, this is exactly what I am doing now using DCMTK:
dcmsend $ip $port --aetitle $eacall --call $ae --recurse --scan-directories $source
Just wondering if I can get rid of dcmtk and do the same with Orthanc. Less tools, the better.
Thanks.

Hello,

Got it. I have just added a new route “/modalities/…/store-straight” in the REST API:
https://bitbucket.org/sjodogne/orthanc/commits/7f083dfae62b7031fd964681e7ab01e576e49d54

The usage is straightforward:

$ curl -H ‘Expect:’ http://localhost:8042/modalities/remote/store-straight --data-binary @/tmp/sample.dcm

HTH,
Sébastien-

I am speechless.
Thank you

any idea for a time estimate when this new version will be released and compiled for windows?
I am using Orthanc on a Windows server.
Thank you

Sorry, the date of release of Orthanc 1.6.1 has not been decided yet.

Hi Sébastien,
I tried this feature. It works but it is a little slow. I am calling it from a Powershell script to loop for a folder that have ~371 MB, 1,280 Files, 15 subfolders.
In the dcmtk approach, I will just do dcmsend.exe $ip $port --aetitle $aetitle --call $ae --recurse --scan-directories $results. This takes about ~1 min and 30 seconds
Via Orthanc, it is calling store-straight links for each image with a POST file in, in a loop for all these 1,280 files. Time wise, it seems to take double time than dcmtk. Orthanc is printing UUID for each POST.
Is there a way to improve this?
Emil

Dear Emil,

I am personally not using Microsoft Windows, neither Powershell, as those are not fee and open-source technologies:

https://book.orthanc-server.com/faq/proprietary.html

However, you should first read the section “Orthanc Explorer is slow under Windows on the localhost” in the Orthanc Book:
https://book.orthanc-server.com/faq/troubleshooting.html#performance-issues

You should also try and set the “Expect” HTTP header to the empty string:
https://book.orthanc-server.com/users/rest.html#sending-dicom-images

I let other people using Microsoft Windows extend my answer if need be.

Regards,
Sébastien-

PS: Orthanc 1.6.1 is now released.

Hello Emil

Are you using pwsh Invoke-RestMethod or Invoke-WebRequest to upload your files?

Although this group isn’t dedicated to discuss tooling, if you paste your Powershell script, maybe some of us might suggest improvements.

A big low-hanging fruit to catch when using these methods is to disable the (ridiculously slow) pwsh progress bar, as mentioned in the Orthanc Book. Please see this section that contains a Dicom upload pwsh script example: https://book.orthanc-server.com/users/rest.html#id6

Another potentially huge gain is to try to make these call async. Something along those lines:

$filePaths |% { Invoke-Command -ScriptBlock {Invoke-RestMethod http://localhost:8042/instances -Method POST -InFile $_.Fullname} -AsJob }

(disclaimer: untested)

(On a side note, Powershell is now open-source and available in Linux/Windows/macOS)

(disclaimer: untested)

More specifically, I am not sure the pipe variable $_ can be marshaled inside the script block (for it may run on other computers).

In case you experience this problem, you might try the following (found in https://blog.ipswitch.com/understanding-powershell-scriptblocks)

Using Invoke-RestMethod:
$uri=“http://localhost:8042/modalities/“+$modalityae+”/store-straight
#command to send back results to modality
Get-ChildItem -Path $source -Recurse | where { ! $.PSIsContainer } | Foreach-Object {
Invoke-RestMethod -Uri $uri -Method Post -InFile $
.FullName -UseDefaultCredentials
}

Great ! My advice can be applied and might help :slight_smile: If you are the script maintainer, you should definitely try to remove the progress bar and, if this is not enough, use the invoke async method I described above. tTell us how it goes !

HTH

yep, better time.
$ProgressPreference = ‘SilentlyContinue’

$uri=“http://localhost:8042/modalities/”+$modalityae+“/store-straight”
#command to send back results to modality
Get-ChildItem -Path $source -Recurse | where { ! $.PSIsContainer } | Foreach-Object {
$reply = Invoke-RestMethod -Uri $uri -Method Post -InFile $
.FullName

}

Thank you all for your help.
Emil

It’s been awhile…while this is nice, I am starting to have patients with thousands of dicoms that I need to send to a remote modality. That will overflow the remote with http requests and sometime will errored out:

E0309 11:11:33.897143 OrthancException.cpp:57] Error in the network protocol: DicomAssociation - connecting to AET “myAEtitle”: Failed to establish association (0006:0317 Peer aborted Association (or never connected); 0006:031c TCP Initialization Error: The operation completed successfully. (Timeout))
I saw Osimis developed some Transfers accelerator plugin, but not sure if this can be used with dicom files stored on drive and seems to work only with peers.
Ideal will be to feed only the main folder and Orthanc to handle the storage commitment.
I also did some reading on the autorouting python script and while this command will do it all under one connection, it still relies on POST http:
RestToolbox.DoPost(‘%s/modalities/sample/store’ % URL, instances)
I could very well load the dicoms that I want to send to the remote modality into Orthanc, but because I execute a LUA script on OnStableStudy, it will create additional problems for this data that I only want to send to a remote modality.
So here I am trying to figure it out how to transfer more efficiently without overwhelming the remote modality with tons of POSTs.
Any input is very appreciated, anything to guide me in the right direction.
Thank you,
Emil

Your last post mixes a lot of subquestions (Lua, storage commitment, Powershell, transfer accelerator, “/modalities/…/store-straight”, REST API…), so please make it simpler so that we can provide a sound answer.

Here are some elements of answer:

  • The “Transfers accelerator” plugin is for Orthanc-to-Orthanc transfers (over HTTP), not for Orthanc-to-DICOM transfers. However, this probably is the fastest way of transmitting images.

  • If you face DICOM timeouts, you can tune the “DicomScuTimeout” global option.

  • If you use curl to send images using “/modalities/…/store-straight”, make sure to add the “Expect:” HTTP header, otherwise there will be a delay:
    https://book.orthanc-server.com/users/rest.html#sending-dicom-images

  • It looks like your setup is the following: “localhost => Orthanc server => DICOM modality”. The first “=>” transfer is done using “/modalities/…/store-straight”. The second “=>” transfer is done using the DICOM protocol. This means 2 network transfers, whereas the “dcmsend” command only needs one network transfer. If “localhost” and “Orthanc” are not the same computer, this doubles the global transfer time, which is what you observe. A typical solution consists in avoiding such a synchronous wait induced by “/modalities/…/store-straight” by implementing server-side auto-routing, with Orthanc acting as a transient buffer:
    https://book.orthanc-server.com/users/lua.html#lua-auto-routing

all right.
let me ask this question: I have a case on local drive that needs to be sent to a remote modality(not Orthanc).
Should I use store-straight (Powershell) like:
$uri=“http://localhost:8042/modalities/$modalityae/store-straight

$ProgressPreference = ‘SilentlyContinue’

Get-ChildItem -Path $source -Recurse -Exclude “DICOMDIR” | where { ! $.PSIsContainer } | Foreach-Object {
$reply = Invoke-RestMethod -Uri $uri -Method Post -InFile $
.FullName
}

OR store locally first, send study as a whole and delete:

#upload dicoms to local Orthanc
$ProgressPreference = ‘SilentlyContinue’
Get-ChildItem -Path (join-path $process “STAGE”) -Recurse -Exclude “DICOMDIR” | where { ! $.PSIsContainer } | Foreach-Object {
$reply = Invoke-RestMethod -Uri http://localhost:8042/instances -Method Post -InFile $
.FullName
}
$studyid=$reply.ParentStudy
#send SEND results to modality
$body = @{
Level = @(‘Study’)
Resources = @($studyid)
Synchronous = $false
StorageCommitment = $false
} | ConvertTo-Json -Depth 3
#send studyid to remote modality
$Uri=“http://localhost:8042/modalities/$remotemodality/store

try{
$id = Invoke-RestMethod -Uri $Uri -Method Post -Body $body -ContentType ‘application/json’
}

catch{
Write-Host “Something went wrong sending study”
}
#monitor job every 5 seconds
if ($id.ID -ne $null) {

$Uri=“http://localhost:8042/jobs/$($id.ID)
do {
$check = Invoke-RestMethod -Uri $Uri -Method Get
Start-Sleep -s 5

}
while($check.State -ne “Success”)
}
Write-Host “Case sent to remote modality - COMPLETE”
#delete SEND results from Orthanc

try{
$id = Invoke-RestMethod -Uri “http://localhost:8042/studies/$studyid” -Method Delete
}

catch{
Write-Host “Something went wrong deleting local study”
}

Does it make any difference for the remote modality? (other than taking longer with the second approach) Will the remote modality see that data is coming from the same AE title?
Thank you

seems like there is a difference in the remote modality response…using Onis as a remote modality and reading the logs
here it is using straight from STAGEORTH to ONIS26:
straight.png
here is sending whole study as one Invoke-RestMethod from STAGEORTH to ONIS26:
wholestudy.png
So some remote may not behave properly with so many socket open/close operations.
Also there is something that times out with the second approach(send whole study). I have my KeepAlive set to true. I will follow on this if I can figure it out the reason

here is a little schematic of my design. So I was playing with the green block. This approach is storing results as temporary into ORTH instead of store-straight, but it freezes at about 4-6% while I monitor the job(or about 15 seconds in). I know if could be because of the OnStableStudy kicks in, but that should be skipped with conditional origin==“DicomProtocol”. Uploads from powershell are recorded as RestApi. Not sure why Orthanc service freezes(have to kill ps1 processes and restart service)…any ideas? Trying to avoid store-straight because of the socket open/close for each dicom.
scheme.png
Thank you,
Emil