Wednesday, February 1, 2023

Hello Dubai! A visit to ArabHealth 2023

The Moon over Burj Khalifa tower in Dubai

The Abraham Accords opened the UAE to Israelis and here I am in Dubai for the ArabHealth 2023 convention. I'm not a big fan of trade shows but when the opportunity came up I just couldn't say no. Add to that the 10% discount on Emirates flights a week before and after the show and the connection flight to Colombo, Sri Lanka, one of my favorite surf destinations, and there you go, business and pleasure comes together. 

Business first, how can you make business in a trade show? 

  1. Set up a booth, you may say? Well, for a small company like HRZ, when looking at the huge pavilions of GE and Siemens, I don't think so. Actually I tried this once at MEDICA and wasn't happy at all with the results.

Sunday, August 1, 2021

MODALIZER+ V6

Well, I guess it's time to celebrate. MODALIZER+ V6 is being released today. Seriously, it's been a long journey. We started working on this version more than two years ago. This been a team work of many people. Evgenia that was in charge of the DICOMIZER-MODALIZER product line since its beginning, Bezalel that designed the new UI, Bar that finished the work and added the latest features, and also David and Rotem that helped allong the way. Additionally, this release completes the work on all HRZ V6 products: MODAIZER-SDK DICOM Library, ZiKiT PACS Server and now MODALIZER+.

So, what's new in MODALIZER+ V6? The first thing you will notice is of course the new graphic design.

MODALIZER+ V6 Home Screen

The new MODALIZER+ is colorful. You will also notice the colors are following into the different workflows, allowing the user to distinguish between them, as we realized that some of the screens look very similar to one another. Also, there's usability, you will notice larger fonts and wider spaces.

Monday, January 18, 2021

Move all studies of patients with ID in CSV file from PACS-A to PACS-B

OK, so here's another PowerShell DICOM script that came handy recently. So my friend, lets call him Benny, got a request from his manager to export all the studies of patients in a list provided as excel sheet and deliver them to a research group (after de-identification and everything of course) but when he called me he just needed to get them out quickly from the PACS. The list was long and there was no chance to do this one by one. So we wrote together this little PowerShell script that reads the patient id's from the excel (after saving it as csv) and use MODALIZER-SDK to do the DICOM work. here it is. I think it explains itself pretty well. We've set the destination PACS-B to be our lightweight PACS server with no plugin so the DICOM files were saved on the disk and from there he picked them up.

$my_ae_title="MY-AE-TITLE"


$pacs_a_ae_title="PACS-A"

$pacs_a_ip_address="10.0.0.10"

$pacs_a_dicom_port=104


$pacs_b_ae_title="PACS-B"


function MoveStudyByPatientID { 

param($pat)

$r = New-Object -ComObject rzdcx.DCXREQ

    

    # Lets echo to be sure

$r.Echo($my_ae_title, $pacs_a_ae_title, $pacs_a_ip_address, $pacs_a_dicom_port)

$o = New-Object -ComObject rzdcx.DCXOBJ

$e = New-Object -ComObject rzdcx.DCXELM

# Query Level - STUDY

$e.Init(0x00080052)

$e.Value = "STUDY"

$o.insertElement($e)

# Patient ID

$e.Init(0x00100020)

$e.Value = $pat

$o.insertElement($e)

# Study Instance UID

$e.Init(0x0020000d)

    $e.Value = ""

$o.insertElement($e)

$i = $r.Query($my_ae_title, $pacs_a_ae_title, $pacs_a_ip_address, $pacs_a_dicom_port, "1.2.840.10008.5.1.4.1.2.1.1", $o)

    if ($i.AtEnd()) {

        "No Studies for patient id: " + $pat

    }

    else

    {

        while ($i.AtEnd() -ne $true)

        {

            $res = $i.Get()

    "LOG: Study Instance UID: " + $res.GetElement(0x0020000d).Value

    $o.insertElement($res.GetElement(0x0020000d))

    $r.Move($my_ae_title, $pacs_a_ae_title, $pacs_a_ip_address, $pacs_a_dicom_port, 104, $pacs_b_ae_title, $o)

            $i.Next();

    } 

    }

}


# A log never hurts

$a = New-Object -ComObject rzdcx.DCXAPP

$a.StartLogging("log.log")

$a.LogLevel = 5


$patients = Import-Csv -Path .\patients.csv

foreach ($pat in $patients.patient_id) 

{

    "LOG: Patient ID: " + $pat

MoveStudyByPatientID $pat

}


$a.StopLogging()


# That's it for now 




Thursday, August 27, 2020

Sending DICOM files indexed in a DICOMDIR on a DICOM CD to PACS using PowerShell and MODALIZER-SDK

 I'm posting this PowerShell script in response to a question I got about sending DICOM files on a CD to PACS. 

This functionality is available in MODALIZER+ from the View menu simply by right clicking the Study item at the top study panel and selecting "Send to". The PACS AE title has to be configured first in the settings.

But, for the automation enthusiasts, here's a PowerShell script that do the same. Recalling on DICOMDIR, a DICOM CD or DVD has a file called DICOMDIR in the root path that references all DICOM files on the media. This script iterates through the DICOMDIR records to collect all referenced files, then it send them using DCXREQ.Send command to the PACS.

Here it is. Enjoy!

 # Send DICOMDIR Patients to PACS


param($rootFolder);

Wednesday, May 8, 2019

More PowerShell DICOM

# PowerShell DICOM

# This little script becomes handy for example for a daily test of your PACS
# It generates a 1000x1000 image with date and key attributes (Study, Series and Instance UID) burned in
# This script uses HRZ's RZDCX.DLL.

# Create DICOM Object
$DCM = New-Object -com rzdcx.DCXOBJ

# UID Generator
$UID = New-Object -com rzdcx.DCXUID

# Create new Key UID's
$studyInstanceUID = $UID.CreateUID(1)
$seriesInstanceUID = $UID.CreateUID(2)
$sopInstanceUID = $UID.CreateUID(3)

# Add minimal elements to the dataset
$tagValues = @(
0x00080016, "1.2.840.10008.5.1.4.1.1.7", 
0x00080018, $sopInstanceUID,
0x00080020, ($studyDate = Get-Date -UFormat "%Y%m%d"),
0x00080030, "",
0x00080050, "ACCNUMHRZTEST",
0x00080060, "SC",
0x00080064, "WSD",
0x00080090, "HRZ",
0x00100010, "HRZ^TEST",
0x00100020, "HRZTEST",
0x00100030, "20100101",
0x00100040, "O",
0x0020000d, $studyInstanceUID,
0x0020000e, $seriesInstanceUID,
0x00200010, "123",
0x00200011, "1",
0x00200013, "1")

$E = New-Object -com rzdcx.DCXELM
for (($i=0); ($i -lt $tagValues.Count); ($i+=2))
{
    $E.Init($tagValues[$i])
    $E.Value = $tagValues[$i+1]
    $DCM.insertElement($E)
}

# Create 1000x1000 Image with text printed on it
$rows = 1000
$cols = 1000

# jpeg image
Add-Type -AssemblyName System.Drawing
$imageFormat = "System.Drawing.Imaging.ImageFormat" -as [type]
$format = $imageFormat::jpeg


$uidType = "rzdcx.UID_TYPE" -as [type]

$createDate = Get-Date
$bmp = new-object System.Drawing.Bitmap $cols,$rows
$font = new-object System.Drawing.Font Consolas,24 
$brushBg = [System.Drawing.Brushes]::Yellow 
$brushFg = [System.Drawing.Brushes]::Black 
$graphics = [System.Drawing.Graphics]::FromImage($bmp) 
$graphics.FillRectangle($brushBg,0,0,$bmp.Width,$bmp.Height) 
$graphics.DrawString($createDate, $font,$brushFg,10,10) 
$font = new-object System.Drawing.Font Consolas,8 
$graphics.DrawString("StudyInstance UID: " + $studyInstanceUID, $font,$brushFg, 10,110)  
$graphics.DrawString("Series Instance UID: " + $studyInstanceUID, $font,$brushFg,10,210)  
$graphics.DrawString("SOP Instance UID: " + $studyInstanceUID, $font,$brushFg,10,310)  
$graphics.DrawString("TARGET AET: " + "PACS-A", $font, $brushFg, 10, 410)  

$graphics.Dispose() 

# Save the JPEG image
$filename = "$home\HRZTEST.jpg"
$bmp.Save($filename, $format) 

# Insert it to the DICOM object
$DCM.SetJpegFrames($filename);

# Save the DICOM file
$dcmfile = $filename + ".dcm"
$DCM.saveFile($dcmfile)

# Send it to the PACS
$REQ = New-Object -com rzdcx.DCXREQ

$succeeded = ""
$failed = ""

# Start logging for network comunication and save to log file

$APP = New-Object -com rzdcx.DCXAPP
$APP.LogLevel = 5 # Debug

$logFile = "$home\SendTestImage.log"

$APP.StartLogging($logFile)

$REQ.Echo("HRZ-TEST", "PACS-A", "localhost", 104)
$REQ.Send("HRZ-TEST", "PACS-A", "localhost", 104, $dcmfile, [ref] $succeeded, [ref] $failed)

# Print results
$filename
$dcmfile
"Succeeded: " + $succeeded
"Failed: " + $failed

# Stop logging
$App.StopLogging()

"Done!"






Tuesday, January 15, 2019

PowerShell DICOM Scripting

Disclosure: This post is purely technical!
Assumption: you know your way around PowerShell or how to get there and a bit of DICOM and our RZDCX API.

If your system is x64 (probably) than make sure to regsvr32 radix.dll the x64 version.

Let's PowerShell!!!

# download rzdcx
Invoke-WebRequest -Uri http://downloads.roniza.com/rzdcx/2.0.8.7/RZDCX_2087.zip -OutFile ./rzdcx.zip

# unzip it
Expand-Archive ./rzdcx.zip -DestinationPath ./rzdcx

# regsvr32 win32 version
$rzdcx32 = Resolve-Path .\rzdcx\win32\rzdcx.dll
Start-Process regsvr32 -verb runAs -argumentlist $rzdcx32

$rzdcx64 = Resolve-Path .\rzdcx\x64\rzdcx.dll
Start-Process regsvr32 -verb runAs -argumentlist $rzdcx64

# Create DICOM Object
$DCM = New-Object -com rzdcx.DCXOBJ

# I assume you have a directory called DICOM with DICOM files in it
$files = @(Get-ChildItem ".\DICOM\*")

# Write headers
"filename, Patient Name, Patient ID"

# For each file extract and print patient name and patient id
foreach ($file in $files) {
  $DCM.openFile($file)
  $patname = $DCM.GetElement([int32]::Parse(00100010,'HexNumber')).Value
  $patid   = $DCM.GetElement([int32]::Parse(00100020,'HexNumber')).Value
  Write-Host $file "," $patname "," $patid
}

Try it!