A new year is the perfect time for a new product version.
2011 is the year for the new release of RDCX DICOM Toolkit version 2.0 with structured reporting.
The major feature of this release is the all new DCXSR interface for creating DICOM Structured Reports using the dynamic SR dictionary.
If you had the chance to play around with DICOM SR's, you'll probably agree with me about one thing: so many attributes for so little information, ha? Just look at all these nested sequences, oh my god!
Sunday, January 16, 2011
Wednesday, September 1, 2010
HL7 Mapper may not save configuration due to missing access to INFORMATION_SCHEMA
Symptom: When trying to save configuration, an error message is shown with the following text:
The view may be accessible on one catalog and not accessible on another even if they are on the same table.
If this
Solution: We are working on a fix to this problem.
Ticket 224: HL7 Mapper may not save configuration due to missing system tables
"Object Reference not set to an instance of an object"Reason: The HL7 Mapping application relies on SQL Server INFORMATION_SCHEMA to generate the database view dynamically. Apparently there has been some compatibility issues with this feature since SQL Server 2005 and sometimes there's no access to this view.
The view may be accessible on one catalog and not accessible on another even if they are on the same table.
If this
Solution: We are working on a fix to this problem.
Ticket 224: HL7 Mapper may not save configuration due to missing system tables
Sunday, August 29, 2010
Healthcare Software Integration Engines are grossly over priced
"Healthcare Software Integration Engines are grossly over priced"These are not my words. This is an exact quote of a very well recognized healthcare IT professional.And I fully agree. After all, what's the big deal, Aha? It's just moving fields and attributes from one place to another, change some formats maybe, some XML tricks, database. Really, no big deal, right?
You maybe think to yourself that I'm joking but I'm not. After all, I have developed an HL7 Integration Engine of my own that I'm very proud of, HL7Kit Pro. This little devil is not a show off. It's a tool designed to do one thing - build a two way road, a bridge, between your SQL Server database and HL7.
In modern design, less is more. When going over the features list of some of these products, I can't avoid the comparison with a 'do it all 149 peaces hardware tool kit' perfect package on TV Shop America.
When shopping for an integration engine it's important to remember that there's always the other road. The one of developing custom interfaces. Good programmers nowadays are not that expensive to hire and the software tools we have today are efficient and easy to use. So when you are facing an integration challenge, you should compare the options and don't get tempted to purchase a multi K$ package bundled with a big unknown figure of expert consultation, maintenance and support fees to feed the monster.
Instead, take the right HL7 tool in your hands and finish the work in no time.
The new 1.3 release of HL7Kit Pro adds hot folders integration. The runtime service can be configured to digest HL7 messages from an inbox folder and write outgoing messages to an Out-box directory.
There's also better support for running multiple HL7 runtime services on a single computer, each using it's own queue.
... And there's many bug fixes and little improvements like the ability to read and write directly from views ...
All in all, the new release is a direct continuation of the old one and that's simply because there's no need for major changes when a tool is doing the work. Simple work, but still work.
Ask every professional: working with quality tools designed for the task is great fun.
To get you started, there are two example projects on the HL7 support page. One for incoming messages and one for outgoing messages that you can download and try with the evaluation copy.
Monday, August 23, 2010
Registry free COM using Side By Side Assemblies
![]() |
Registry Free COM |
Did you know that you don't have to register a COM object in order to use it?
Well, I didn't. Until recently, when I was searching for something in the internet and bumped into this article in the MSDN library.
What this means, to me at least, is that there's no need to register RZDCX and thus it can be used in many applications that require no installation, because, as you know, to register a COM object in the registry you need administrative rights but to run an application from a CD you don't have to.
So, this post is all about using RZDCX.DLL with no installation.
For this purpose, we'll use one of the sample applications, for example the C# example EchoSCUExample.
All the examples with their source code can be downloaded from the DICOM download page.
Download the complete package with RZDCX.DLL, The manifest files, C++ Example and C# example.
In order to eliminate the use of registry, we'll create a manifest file for EchoSCUExample.exe and name it EchoSCUExample.exe.manifest
Next, we need to create a manifest file for RZDCX.DLL as well, name it rzdcx.X.manifest and save it in the same folder. Note that this is the manifest of the comming version 2.0.0.0 of RZDCX so some of the interfaces in it are not yet available in version 1.0.1.7 that is currently available on the web site.
Copy all four files (rzdcx.dll, rzdcx.X.manifest, EchoSCUExample.exe and EchoSCUExample.exe.manifest) to a single directory, unregister RZDCX.DLL (using regsvr32.exe -u rzdcx.dll) so that you are absolutely sure that no registry is involved and double click EchoSCUExample.exe.
Enjoy!
Tuesday, June 29, 2010
Fixed bugs and new features in release 1.0.1.7
Fixed bugs and new features in release 1.0.1.7 address all kind of issues that were found lately.
The most important feature that was added this build is the ability to receive N-EVENT-REPORT commands in the Requester class DCXREQ that represents the SCU.
The methods new methods CommitFilesAndWaitForResult and CommitInstancesAndWaitForResult in the requester class enable us to wait for the commit result on the same association that sent the request.
The following code shows how to build a Storage Commitment SCU with the new methods.
[Test]
public void CommitFilesAndWaitForResultOnSameAssoc()
{
bool status;
bool gotIt;
String fullpath = "SCMTEST";
Directory.CreateDirectory(fullpath);
CommonTestUtilities.CreateDummyImages(fullpath, 1, 1);
string succeededInstances;
string failedInstances;
string MyAETitle = System.Environment.GetEnvironmentVariable("COMPUTERNAME");
DCXREQ r = new DCXREQ();
//r.OnCommitResult += new IDCXREQEvents_OnCommitResultEventHandler(a1.accepter_OnCommitResult);
r.OnFileSent += new IDCXREQEvents_OnFileSentEventHandler(OnFileSent);
r.Send(MyAETitle, IS_AE, IS_Host, IS_port, fullpath + "\\SER1\\IMG1", out succeededInstances, out failedInstances);
DCXOBJ obj = new DCXOBJ();
obj.openFile(fullpath + "\\SER1\\IMG1");
string sop_class_uid = obj.getElementByTag((int)DICOM_TAGS_ENUM.sopClassUid).Value.ToString();
string instance_uid = obj.getElementByTag((int)DICOM_TAGS_ENUM.sopInstanceUID).Value.ToString();
string transactionUID = r.CommitFilesAndWaitForResult(MyAETitle, IS_AE, IS_Host, IS_port, fullpath + "\\SER1\\IMG1",
5, out gotIt, out status, out succeededInstances, out failedInstances);
Directory.Delete(fullpath, true);
Assert.True(status, "Commit result is not success");
Assert.That(failedInstances.Length == 0);
Assert.AreEqual(succeededInstances, sop_class_uid + ";" + instance_uid + ";");
}
It's important to remember that the SCP may send the result on a separate association so unless you're absolutely sure about the way the SCP will behave, you should be prepared to receive the result with your accepter that can either run in a separate thread or you can set it up just for this purpose.
Here's a little code snippet that does exactly this. It prepares an accepter, then send the request and then wait for the result either to be send instantly in the same association or on a separate one. Note that this is a NUnit test function with a lot of verification code. To simply send the commit and wait for the result you should call the send and wait methods and if didn't get the result, wait on the accepter.
class SyncAccepter
{
public bool _gotIt = false;
public bool _status = false;
public string _transaction_uid;
public string _succeeded_instances;
public string _failed_instances;
public DCXACC accepter;
public string MyAETitle;
public void accepter_OnCommitResult(
bool status,
string transaction_uid,
string succeeded_instances,
string failed_instances)
{
_gotIt = true;
_status = status;
_transaction_uid = transaction_uid;
_succeeded_instances = succeeded_instances;
_failed_instances = failed_instances;
}
public SyncAccepter()
{
accepter = new DCXACC();
accepter.OnCommitResult += new IDCXACCEvents_OnCommitResultEventHandler(accepter_OnCommitResult);
MyAETitle = System.Environment.GetEnvironmentVariable("COMPUTERNAME");
accepter.WaitForConnection(MyAETitle, 104, 0);
}
public bool WaitForIt(int timeout)
{
if (accepter.WaitForConnection(MyAETitle, 104, timeout))
return accepter.WaitForCommand(timeout);
else
return false;
}
}
[Test]
public void CommitFilesSameThread()
{
// Create test files
String fullpath = "SCMTEST";
Directory.CreateDirectory(fullpath);
CommonTestUtilities.CreateDummyImages(fullpath, 1, 1);
// Send test files
string MyAETitle = System.Environment.GetEnvironmentVariable("COMPUTERNAME");
DCXREQ r = new DCXREQ();
string succeededInstances;
string failedInstances;
r.Send(MyAETitle, IS_AE, IS_Host, IS_port, fullpath + "\\SER1\\IMG1", out succeededInstances, out failedInstances);
Assert.That(failedInstances.Length == 0);
Assert.That(succeededInstances.Length > 0);
// Commit files and wait for result on separate association for 30 seconds
SyncAccepter a1 = new SyncAccepter();
r.CommitFiles(MyAETitle, IS_AE, IS_Host, IS_port, fullpath + "\\SER1\\IMG1");
a1.WaitForIt(30);
if (a1._gotIt)
{
// Check the result
Assert.True(a1._status, "Commit result is not success");
Assert.That(a1._failed_instances.Length == 0);
DCXOBJ obj = new DCXOBJ();
obj.openFile(fullpath + "\\SER1\\IMG1");
string sop_class_uid = obj.getElementByTag((int)DICOM_TAGS_ENUM.sopClassUid).Value.ToString();
string instance_uid = obj.getElementByTag((int)DICOM_TAGS_ENUM.sopInstanceUID).Value.ToString();
Assert.AreEqual(a1._succeeded_instances, sop_class_uid + ";" + instance_uid + ";");
}
else
Assert.Fail("Didn't get commit result");
/// Cleanup
Directory.Delete(fullpath, true);
}
}
The most important feature that was added this build is the ability to receive N-EVENT-REPORT commands in the Requester class DCXREQ that represents the SCU.
The methods new methods CommitFilesAndWaitForResult and CommitInstancesAndWaitForResult in the requester class enable us to wait for the commit result on the same association that sent the request.
The following code shows how to build a Storage Commitment SCU with the new methods.
[Test]
public void CommitFilesAndWaitForResultOnSameAssoc()
{
bool status;
bool gotIt;
String fullpath = "SCMTEST";
Directory.CreateDirectory(fullpath);
CommonTestUtilities.CreateDummyImages(fullpath, 1, 1);
string succeededInstances;
string failedInstances;
string MyAETitle = System.Environment.GetEnvironmentVariable("COMPUTERNAME");
DCXREQ r = new DCXREQ();
//r.OnCommitResult += new IDCXREQEvents_OnCommitResultEventHandler(a1.accepter_OnCommitResult);
r.OnFileSent += new IDCXREQEvents_OnFileSentEventHandler(OnFileSent);
r.Send(MyAETitle, IS_AE, IS_Host, IS_port, fullpath + "\\SER1\\IMG1", out succeededInstances, out failedInstances);
DCXOBJ obj = new DCXOBJ();
obj.openFile(fullpath + "\\SER1\\IMG1");
string sop_class_uid = obj.getElementByTag((int)DICOM_TAGS_ENUM.sopClassUid).Value.ToString();
string instance_uid = obj.getElementByTag((int)DICOM_TAGS_ENUM.sopInstanceUID).Value.ToString();
string transactionUID = r.CommitFilesAndWaitForResult(MyAETitle, IS_AE, IS_Host, IS_port, fullpath + "\\SER1\\IMG1",
5, out gotIt, out status, out succeededInstances, out failedInstances);
Directory.Delete(fullpath, true);
Assert.True(status, "Commit result is not success");
Assert.That(failedInstances.Length == 0);
Assert.AreEqual(succeededInstances, sop_class_uid + ";" + instance_uid + ";");
}
It's important to remember that the SCP may send the result on a separate association so unless you're absolutely sure about the way the SCP will behave, you should be prepared to receive the result with your accepter that can either run in a separate thread or you can set it up just for this purpose.
Here's a little code snippet that does exactly this. It prepares an accepter, then send the request and then wait for the result either to be send instantly in the same association or on a separate one. Note that this is a NUnit test function with a lot of verification code. To simply send the commit and wait for the result you should call the send and wait methods and if didn't get the result, wait on the accepter.
class SyncAccepter
{
public bool _gotIt = false;
public bool _status = false;
public string _transaction_uid;
public string _succeeded_instances;
public string _failed_instances;
public DCXACC accepter;
public string MyAETitle;
public void accepter_OnCommitResult(
bool status,
string transaction_uid,
string succeeded_instances,
string failed_instances)
{
_gotIt = true;
_status = status;
_transaction_uid = transaction_uid;
_succeeded_instances = succeeded_instances;
_failed_instances = failed_instances;
}
public SyncAccepter()
{
accepter = new DCXACC();
accepter.OnCommitResult += new IDCXACCEvents_OnCommitResultEventHandler(accepter_OnCommitResult);
MyAETitle = System.Environment.GetEnvironmentVariable("COMPUTERNAME");
accepter.WaitForConnection(MyAETitle, 104, 0);
}
public bool WaitForIt(int timeout)
{
if (accepter.WaitForConnection(MyAETitle, 104, timeout))
return accepter.WaitForCommand(timeout);
else
return false;
}
}
[Test]
public void CommitFilesSameThread()
{
// Create test files
String fullpath = "SCMTEST";
Directory.CreateDirectory(fullpath);
CommonTestUtilities.CreateDummyImages(fullpath, 1, 1);
// Send test files
string MyAETitle = System.Environment.GetEnvironmentVariable("COMPUTERNAME");
DCXREQ r = new DCXREQ();
string succeededInstances;
string failedInstances;
r.Send(MyAETitle, IS_AE, IS_Host, IS_port, fullpath + "\\SER1\\IMG1", out succeededInstances, out failedInstances);
Assert.That(failedInstances.Length == 0);
Assert.That(succeededInstances.Length > 0);
// Commit files and wait for result on separate association for 30 seconds
SyncAccepter a1 = new SyncAccepter();
r.CommitFiles(MyAETitle, IS_AE, IS_Host, IS_port, fullpath + "\\SER1\\IMG1");
a1.WaitForIt(30);
if (a1._gotIt)
{
// Check the result
Assert.True(a1._status, "Commit result is not success");
Assert.That(a1._failed_instances.Length == 0);
DCXOBJ obj = new DCXOBJ();
obj.openFile(fullpath + "\\SER1\\IMG1");
string sop_class_uid = obj.getElementByTag((int)DICOM_TAGS_ENUM.sopClassUid).Value.ToString();
string instance_uid = obj.getElementByTag((int)DICOM_TAGS_ENUM.sopInstanceUID).Value.ToString();
Assert.AreEqual(a1._succeeded_instances, sop_class_uid + ";" + instance_uid + ";");
}
else
Assert.Fail("Didn't get commit result");
/// Cleanup
Directory.Delete(fullpath, true);
}
}
195 | code | fixed | 1.0.1.6 | N-EVENT-REPORT Response for Storage Commit always return error to SCP | edit |
Returns status 0x00fe always. | |||||
196 | code | fixed | 1.0.1.6 | DCXOBJ TransferSyntax (set) method is reverted after saveFile | edit |
Do the following: 1) Change Transfer Syntax 2) Save file 3) Load the file 4) Check the meta header transfer syntax -> Same as before (1) Reason, xfer member of DCXOBJ doesn't change at (1) even that the object is changed. | |||||
197 | code | fixed | 1.0.1.6 | Can't get printer info if printer is only color | edit |
Reported by L&T (6.2) If printer negotiates only basic color print management, then GetPrinterInfo will not work. | |||||
198 | new | fixed | 1.0.1.6 | Get Storage Commit result N-EVENT-REPORT on requester association | edit |
SCM SCP may send N-EVENT-REPORT with SCM Result on same association that the SCM SCU initiated and sent the request N-ACTION. It may also send it on a new association that the SCP initiates. SCM SCU may disconnect association immediatly after recieving the N-ACTION Response from the SCP. This change allows both ways to be implemented in RZDCX by adding the CommitInstancesAndWaitForResult andCommitFilesAndWaitForResult. These methods send the request and then wait for the N-EVENT-REPORT | |||||
199 | code | fixed | 1.0.1.6 | get property SamplesPrePixel in DCXPrintImageBox may return wrong valu | edit |
Casting between int, enum and ushort may cause wrong interpratation of get value. Resolve by explicit cast in method. | |||||
200 | code | fixed | 1.0.1.6 | Get TM (Time) data element is not identical to set | edit |
Get time of 13:04:59.123 doesn't get expected result. See unit test.change control: return value is up to millisecond i.e. formated as hh:mm:dd.ttt |
Monday, June 21, 2010
RZDCX DICOM Toolkit 1.0.1.6 Released
The new build of RZDCX addresses two bugs found in the Print module and a fix to the C# MWL test application.
# | Type | Status | Created | By | Subsys | Changed | Assigned | Svr | Pri | Title | |
---|---|---|---|---|---|---|---|---|---|---|---|
194 | code | fixed | Jun 20 | zroni | RZDCX | Jun 20 | zroni | 1 | 1 | SPS sequence is not added to query object in C# MWL Test application | edit |
193 | code | fixed | Jun 20 | zroni | RZDCX | Jun 20 | zroni | 1 | 1 | Pixel data size in color print is wrong | edit |
192 | code | fixed | Jun 20 | zroni | RZDCX | Jun 20 | zroni | 1 | 1 | LANDSACPE instead of LANDSCAPE in Print API | edit |
Thursday, June 17, 2010
FIX Problem: RZDCX not showing in the Add reference tab in Visual Studio 2008
Unfortunately, a problem was found in the registration of the win32 build 1.0.1.4.
The problem seams to be related to win32/x64 registry entry mix-up in the type library registry entry leading to the component not showing when trying to add a reference in C# projects.
This problem is showing in build 1.0.1.4 and 1.0.1.3.
The problem is now fixed in build 1.0.1.5
Note that for using the win32 component on x64 machines you should use the SysWOW32o64 version of regsvr32.exe
The problem seams to be related to win32/x64 registry entry mix-up in the type library registry entry leading to the component not showing when trying to add a reference in C# projects.
This problem is showing in build 1.0.1.4 and 1.0.1.3.
The problem is now fixed in build 1.0.1.5
Note that for using the win32 component on x64 machines you should use the SysWOW32o64 version of regsvr32.exe
Subscribe to:
Posts (Atom)