Interfacing with Dicom sistems

User avatar
xProgrammer
Posts: 464
Joined: Tue May 16, 2006 7:47 am
Location: Australia

Re: Interfacing with Dicom sistems

Post by xProgrammer »

Hi all (and especially Massimo)

Whilst I don't have access to a DICOM based camera just at the moment (but will have soon), I have started writing some code with a view to making a start on this project.

I have written a base class (TDicomVR) for a DICOM value representation (VR). I would intend deriving classes for the various types (27 ?) of value representations from this base class.

To date I have written three such derived classes: TDicomVRUI (unique identifier), TDicomVRUL (unsigned long) and TDicomVRUS (unsigned short). These were picked to enable me to build a C-Echo Request class (TEchoReqBody).

I have not yet written any code to actually send this request out on the LAN/WAN nor to capture and decode the expected response.

The following code includes the above classes and uses them to build a C-Echo Request as per the book referenced in above posts and the string it builds matches that given in a table in the book with the exception of 1 byte which I think represents an error in the book.

Code: Select all

// dicom.prg

// initial experimental code aiming for DICOM capabilities from software written in [x]Harbour.

#include "hbclass.ch"

FUNCTION Main()

  obj_ThisBody := TCEchoReqBody():New( "0020" )
  ShowByteStream( obj_ThisBody:ByteStream() )
  InKey( 0 )
  QUIT

/**************************************************************\
*                                                              *
*    CLASS TCEchoReqBody - DICOM C-Echo Request (DICOM-ping)   *
*                                                              *
*  Used to verify one DICOM AE is connected to another         *
*                                                              *
\**************************************************************/

CLASS TCEchoReqBody

  DATA obj_GroupLength
  DATA obj_AffServClassUID 
  DATA obj_CommandField    
  DATA obj_MessageID       
  DATA obj_DataSetType     

  METHOD New( var_ID )
  METHOD ByteStream()

ENDCLASS

METHOD New( var_ID ) CLASS TCEchoReqBody

  LOCAL int_GroupLength

  ::obj_AffServClassUID := TDicomVRUI():New( "0000", "0002", "1.2.840.10008.1.1" )
  ::obj_CommandField    := TDicomVRUS():New( "0000", "0100", "0030" )
  ::obj_MessageID       := TDicomVRUS():New( "0000", "0110", var_ID )
  ::obj_DataSetType     := TDicomVRUS():New( "0000", "0800", "0101" )
  int_GroupLength := ::obj_AffServClassUID:Length() + ::obj_CommandField:Length() + ::obj_MessageID:Length() + ::obj_DataSetType:Length()
  ::obj_GroupLength     := TDicomVRUL():New( "0000", "0000", int_GroupLength )

  RETURN self

METHOD ByteStream() CLASS TCEchoReqBody

  RETURN ::obj_GroupLength:ByteStream() + ::obj_AffServClassUID:ByteStream() + ::obj_CommandField:ByteStream() + ;
    ::obj_MessageID:ByteStream() + ::obj_DataSetType:ByteStream()

/**************************************************************\
*                                                              *
*         CLASS TDicomVR - DICOM Value Representation          *
*                                                              *
*  This is the base class from which the various DICOM value   *
*  representations (there are currently 27 defined) are        *
*  derived.                                                    *
*                                                              *
\**************************************************************/

CLASS TDicomVR

  DATA str_Group
  DATA str_Element
  DATA str_DataLength
  DATA str_Data

  METHOD New() CONSTRUCTOR
  METHOD SetGroupHex( str_HexGroup )
  METHOD SetElementHex( str_HexElement ) 
  METHOD SetLength( int_Length )
  METHOD ByteStream()
  METHOD Length() 

ENDCLASS

METHOD New() CLASS TDicomVR

  RETURN self

METHOD SetGroupHex( str_HexGroup ) CLASS TDicomVR

  LOCAL int_Group

  int_Group := HexToNum( str_HexGroup )
  ::str_Group := Chr( int_Group % 256 ) + Chr( Int( int_Group / 256 ) )

  RETURN nil

METHOD SetElementHex( str_HexElement ) CLASS TDicomVR

  LOCAL int_Element

  int_Element := HexToNum( str_HexElement )
  ::str_Element := Chr( int_Element % 256 ) + Chr( Int( int_Element / 256 ) )

  RETURN nil

METHOD SetLength( int_Length ) CLASS TDicomVR

  LOCAL int_ThisByte 

  int_ThisByte := int_Length % 256
  ::str_DataLength := Chr( int_ThisByte )
  int_Length := ( int_length - int_ThisByte ) / 256
  int_ThisByte := int_Length % 256
  ::str_DataLength += Chr( int_ThisByte )
  int_Length := ( int_length - int_ThisByte ) / 256
  int_ThisByte := int_Length % 256
  ::str_DataLength += Chr( int_ThisByte )
  int_Length := ( int_length - int_ThisByte ) / 256
  int_ThisByte := int_Length % 256
  ::str_DataLength += Chr( int_ThisByte )

  RETURN nil

METHOD ByteStream() CLASS TDicomVR

  RETURN ::str_Group + ::str_Element + ::str_DataLength + ::str_Data

METHOD Length() CLASS TDicomVR

  RETURN 8 + Len( ::str_Data )

/******************************************************************\
*                                                                 *
* CLASS TDicomVRUI - DICOM Value Representation Unique Identifier *
*                                                                 *
* A character string containing a UID that is used to uniquely    *
* identify a wide variety of items.                               *
*                                                                 *
\******************************************************************/

CLASS TDicomVRUI FROM TDicomVR

  METHOD New( str_Data )

ENDCLASS

METHOD New( str_Group, str_Element, str_Data ) CLASS TDicomVRUI

  LOCAL int_Length 

  ::SetGroupHex( str_Group )
  ::SetElementHex( str_Element )

  // maximum acceptable length for data in a UI is 64 characters
  int_Length := Len( str_Data )
  IF int_Length > 64
    str_Data := SubStr( str_Data, 1, 64 )
    int_Length := 64
  ENDIF

  // data must be an even number of bytes - if odd pad with 0x00
  IF int_Length % 2 == 1
    str_Data += Chr( 0 )
    int_Length += 1
  ENDIF

  // set data and length
  ::str_Data := str_Data
  ::SetLength( int_Length )

  RETURN self

/**************************************************************\
*                                                              *
*  CLASS TDicomVRUL - DICOM Value Representation Unsigned Long *
*                                                              *
*  Unsigned binary integer 32 bits (4 bytes) in length         *
*                                                              *
\**************************************************************/

CLASS TDicomVRUL FROM TDicomVR

  METHOD New( str_Group, str_Element, var_Data ) CONSTRUCTOR
  METHOD Length()

ENDCLASS

METHOD New( str_Group, str_Element, var_Data ) CLASS TDicomVRUL

  LOCAL int_Data

  ::SetGroupHex( str_Group )
  ::SetElementHex( str_Element )
  ::SetLength( 4 )  
  IF ValType( var_Data ) == "C"
    int_Data := HexToNum( var_Data )
   ELSE
    int_Data := var_Data
  ENDIF
  int_ThisByte := int_Data % 256
  ::str_Data := Chr( int_ThisByte )
  int_Data := ( int_Data - int_ThisByte ) / 256
  int_ThisByte := int_Data % 256
  ::str_Data += Chr( int_ThisByte )
  int_Data := ( int_Data - int_ThisByte ) / 256
  int_ThisByte := int_Data % 256
  ::str_Data += Chr( int_ThisByte )
  int_Data := ( int_Data - int_ThisByte ) / 256
  int_ThisByte := int_Data % 256
  ::str_Data += Chr( int_ThisByte )

  RETURN self

METHOD Length() CLASS TDicomVRUL

  RETURN 12

/**************************************************************\
*                                                              *
* CLASS TDicomVRUS - DICOM Value Representation Unsigned Short *
*                                                              *
*  Unsigned binary integer 16 bits (2 bytes) in length         *
*                                                              *
\**************************************************************/

CLASS TDicomVRUS FROM TDicomVR

  METHOD New( str_Group, str_Element, var_Data ) CONSTRUCTOR
  METHOD Length()

ENDCLASS

METHOD New( str_Group, str_Element, var_Data ) CLASS TDicomVRUS

  LOCAL int_Data 

  ::SetGroupHex( str_Group )
  ::SetElementHex( str_Element )
  ::SetLength( 2 )  
  IF ValType( var_Data ) == "C"
    int_Data := HexToNum( var_Data )
   ELSE
    int_Data := var_Data
  ENDIF
  ::str_Data := Chr( int_Data % 256 ) + Chr( Int( int_Data / 256 ) )

  RETURN self

METHOD Length() CLASS TDicomVRUS

  RETURN 10
  
FUNCTION ShowByteStream( str_Stream ) 

  LOCAL int_StreamLength

  int_StreamLength := Len( str_Stream )
  FOR ii = 1 TO int_StreamLength
    ? "Byte", Str( ii, 3, 0 ), "=>", Str( Asc( str_Stream[ii] ), 3, 0), "Decimal or", NumToHex( Asc( str_Stream[ii] ), 2 ), "hex"
  NEXT
 
Any comments / suggestions happily received.
User avatar
Massimo Linossi
Posts: 474
Joined: Mon Oct 17, 2005 10:38 am
Location: Italy

Re: Interfacing with Dicom sistems

Post by Massimo Linossi »

Wow !!! You're really fast. Now i must ask if there is a way to go in that
clinic where there is a Dicom system and to go near the machine.
Maybe I can make some tests in a Pc connected in the net and assign it as a
fake server, not the main one.
I'll keep you informed if there are some possibilities to make this experiment.
Thanks a lot.
Massimo.
User avatar
xProgrammer
Posts: 464
Joined: Tue May 16, 2006 7:47 am
Location: Australia

Re: Interfacing with Dicom sistems

Post by xProgrammer »

Hi Massimo

I have some classes from my applications that access my [x]Harbour based client-server data base server that should adapt fairly easily to sending such a request and waiting for a reply, I think. But I need to know a bit more about the DICOM setup of the camera that I will have access to such as IP address (should be easy enough), port number(s). There may well be other setup details needed as well - I have to do more research in that area.

That code (as used to access data base server - that is not yet adapted to our prupose) is as follows:

Code: Select all

// Socket.prg

#include "hbclass.ch"

CLASS TSocket

  CLASSDATA log_Initialised INIT .F.
  DATA str_IPAddress
  DATA int_PortNumber
  DATA pSocket
  DATA log_Connected
  DATA str_Data

  METHOD New() CONSTRUCTOR
  METHOD SetIP( str_IPAddress )
  METHOD SetPort( int_PortNumber )
  METHOD CreateQueryObject()
  METHOD Connect()
  METHOD Send( cMessage )
  METHOD Receive()
  METHOD Close()
  METHOD SendReceive( cMessage )
  METHOD CleanUp()

ENDCLASS

METHOD New() CLASS TSocket

  ::str_IPAddress := "127.0.0.1"
  ::int_PortNumber := 1800
  IF !::log_Initialised
     INetInit()
     ::log_Initialised := .T.
  ENDIF

  RETURN self

METHOD SetIP( str_IPAddress ) CLASS TSocket

  ::str_IPAddress := AllTrim( str_IPAddress )

  RETURN nil


METHOD SetPort( int_PortNumber ) CLASS TSocket

  ::int_PortNumber := int_PortNumber

  RETURN nil


METHOD CreateQueryObject()

  RETURN( TQuery():New( self ) )


METHOD Connect() CLASS TSocket

  LOCAL log_OK
  LOCAL log_Retry

  log_Retry := .T.
  DO WHILE log_Retry
    log_OK := .T.
    TRY
      ::pSocket := INetConnect( ::str_IPAddress, ::int_PortNumber )
    CATCH
      MsgInfo( "Unable to connect to data server" )
      log_OK := .F.
    END
    IF log_OK
      IF INetErrorCode( ::pSocket ) == 0
        ::log_Connected := .T.
        RETURN .T.
       ELSE
        ? "Socket error:", INetErrorDesc( ::pSocket )
      ENDIF
    ENDIF
    log_OK := .F.
    ::log_Connected := .F.
    // ? "Press [Esc] to exit, [Enter] to retry"
    // IF InKey( 0 ) == 27
    IF !MsgYesNo( "Emphasis can't communicate with the data server. Do you want to retry?", "Communication Error" ) 
      INetCleanUp()
      log_OK := .F.
      ProgExit()
    ENDIF
  ENDDO


METHOD Send( var_Message ) CLASS TSocket

  INetSend( ::pSocket, var_Message )

  RETURN nil


METHOD Receive() CLASS TSocket

  LOCAL str_Buffer
  LOCAL int_Bytes

  INetSetTimeOut( ::pSocket, 1000 )
  ::str_Data := ""
  int_Bytes := 1
  DO WHILE int_Bytes > 0
    ? "in loop"
    str_Buffer := Space( 1024 )
    int_Bytes := INetRecv( ::pSocket, @str_Buffer )
    ? int_Bytes
    ::str_Data += Left( str_Buffer, int_Bytes )
  ENDDO

  RETURN nil


METHOD Close() CLASS TSocket

  INetClose( ::pSocket )

  RETURN nil


METHOD SendReceive( cMessage ) CLASS TSocket

  ::Send( cMessage )
  ::Receive()
  ::Close()

  RETURN ::cData


METHOD CleanUp() CLASS TSocket

  RETURN InetCleanUp()
and

Code: Select all

// Query.prg

/*
added property oSocket to this class to support an application passing
queries to multiple servers
*/

#include "hbclass.ch"
#include "rapids.ch"

CLASS TQuery

DATA arr_Request
DATA arr_Translated
DATA int_ErrorLevel
DATA log_Remote
DATA obj_Socket

METHOD New() CONSTRUCTOR
METHOD Execute()
METHOD ErrorText( int_ErrorNumber )
METHOD ErrorList()

ENDCLASS

METHOD New( obj_Socket ) CLASS TQuery

::obj_Socket := obj_Socket
::arr_Request := Array( 2 )
::arr_Request[1] := Array( 2 )
::arr_Request[1][2] := obj_User:str_Key
::log_Remote := .T.

RETURN self

METHOD Execute( int_Query, arr_Parameters) CLASS TQuery

  LOCAL log_Retry
  // LOCAL tStart
  // LOCAL tEnd

  // tStart := Seconds()
  ::int_ErrorLevel := 1
  ::arr_Request[1][1] := int_Query
  // ? "Query", iQuery
  ::arr_Request[2] := arr_Parameters
  DO WHILE ::int_ErrorLevel = dberrorclass_RETRY_OK
    IF ::log_Remote
      ::obj_Socket:Connect()
      ? "about to send"
      ::obj_Socket:Send( HB_Serialize( ::arr_Request) ) 
      ? "waiting to receive"  
      ::obj_Socket:Receive()
      ? "closing socket"
      ::obj_Socket:Close()
      ::arr_Translated := HB_Deserialize( ::obj_Socket:str_Data )
     ELSE
      // ::arr_Translated := MakeLocalQuery( ::arr_Request )
    ENDIF
    ::int_ErrorLevel := ::arr_Translated[1][1]
    // ? "Return value", ::int_ErrorLevel
    DO CASE
      CASE ::int_ErrorLevel = dberrorclass_RETRY_OK
        log_Retry := MsgYesNo( "Unable to write to database.  Do you want to retry?" )
        IF log_Retry 
          ::int_ErrorLevel := dberrorclass_GAVE_UP
        ENDIF
      CASE ::int_ErrorLevel = dberrorclass_NO_RETRY
         MsgInfo( "The database server has reported the following error(s):" + CRLF + ::ErrorList() )
    ENDCASE
  ENDDO
  // time_End := Seconds()
  // ? "start at", time_Start, "end at", time_End

  RETURN ::int_ErrorLevel

METHOD ErrorText( int_ErrorNumber ) CLASS TQuery

  DO CASE
    CASE int_ErrorNumber = dberror_NO_ERROR
      RETURN "No error has occurred"
    CASE int_ErrorNumber = dberror_CANNOT_LOCK_RECORD        
      RETURN "Unable to obtain a record lock"
    CASE int_ErrorNumber = dberror_CANNOT_APPEND_RECORD  
      RETURN "Unable to append to table"     
    CASE int_ErrorNumber = dberror_CANNOT_LOCK_FILE  
      RETURN "Unable to obtain a table lock"       
    CASE int_ErrorNumber = dberror_INVALID_KEY_ALLOCATOR      
      RETURN "Invalid key allocator specified"
    CASE int_ErrorNumber = dberror_CANNOT_LOCK_LASTKEY_FILE   
      RETURN "Cannot obtain a lock on the key allocation table"
    CASE int_ErrorNumber = dberror_NO_SUCH_KEY_VALUE          
      RETURN "No such key value"
    CASE int_ErrorNumber = dberror_KEY_NOT_A_STRING          
      RETURN "The search value was not a string"
    CASE int_ErrorNumber = dberror_NO_SUCH_QUERY_DEFINED     
      RETURN "No such query defined on this server"
    CASE int_ErrorNumber = dberror_QUERY_IS_NOT_AN_ARRAY     
      RETURN "The query was received in an invalid (non-array) format"
    CASE int_ErrorNumber = dberror_RECORD_HAS_CHANGED        
      RETURN "The record has been altered by another user"
    CASE int_ErrorNumber = dberror_NO_ASSIGNED_KEY_ALLOCATOR 
      RETURN "No assigned key allocator"
    OTHERWISE
      RETURN "Unknown error"
  ENDCASE

METHOD ErrorList() CLASS TQuery

LOCAL arr_Messages
LOCAL int_NumMessages
LOCAL str_Text
LOCAL int_MsgNum

arr_Messages := ::arr_Translated[1][2]
int_NumMessages := LEN( arr_Messages )
str_Text := ""
FOR int_MsgNum = 1 TO int_NumMessages
   str_Text += "ERROR " + Str( arr_Messages[int_MsgNum] ) + ": " + ::ErrorText( arr_Messages[int_MsgNum] ) + CRLF 
NEXT

RETURN str_Text
Obviously this code needs reworking for our current purposes, but it gives a rough idea of where we may be headed to get C-Echo Requests (and later DICOM requests) working.

I also remember that when I ran this code in a Windows environment (I use Linux almost exclusively) I had to make a small change to the way the software looped when receiving a reply.

Regards
xProgrammer
User avatar
xProgrammer
Posts: 464
Joined: Tue May 16, 2006 7:47 am
Location: Australia

Re: Interfacing with Dicom sistems

Post by xProgrammer »

Hi all

At this stage, presumably, the emphasis is on "proof of concept" - that is showing that we can interact successfully with other devices that implement DICOM from software written in [x]Harbour - rather than the elegance, efficiency and flexibility of our code. Nonetheless, perhaps we should start thinking about some of our goals in these regards. Some of my thoughts follow.

Some of the DICOM Value Representations have specific rules about what they should contain. To what extent should we check this and what should we do if the data passed in is non-conformant? Take the DA (Date) VR, a class for which might look like the following code (which was written quickly for this discussion and has not been tested) :

Code: Select all

/**************************************************************\
*                                                              *
*    CLASS TDicomVRDA - DICOM Value Representation Date        *
*                                                              *
*  A date in the format YYYYMMDD                               *
*                                                              *
\**************************************************************/

CLASS TDicomVRDA FROM TDicomVR

  METHOD New( str_Group, str_Element, var_Data ) CONSTRUCTOR
  METHOD Length()

ENDCLASS

METHOD New( str_Group, str_Element, var_Data ) CLASS TDicomVRDA

  LOCAL int_Data 

  ::SetGroupHex( str_Group )
  ::SetElementHex( str_Element )
  ::SetLength( 2 )  
  IF ValType( var_Data ) == "D"
    ::str_Data := DToS( var_Data )
   ELSE
    // string must be 8 characters long
    // it should be in the format YYYYMMDD
    ::Str_Data := PadR( var_Data, 8 )
  ENDIF

  RETURN self

METHOD Length() CLASS TDicomVRDA

  RETURN 16
If the date is passed in as an [x]Harbour date we don't have an issue here. But we probably want the flexibiity to pass in dates as character strings in the YYYYMMDD format which can be used directly. Length of the data is critical in DICOM, and we can ensure that is correct with the PadR function. But if the length is not 8 our code setting up the DICOM VR is presumably faulty. Should we rather return an error somehow to the requesting code?

And if we are going to check for errors do we check the string for only containing the characters [0-9]? And for being a valid date?

If a string being passed to one of the text VRs is over length do we just trim it to the maximum length or flag this as an error? Should such behaviour be optional and controlled by some parameter?

Regards
xProgrammer
User avatar
xProgrammer
Posts: 464
Joined: Tue May 16, 2006 7:47 am
Location: Australia

Re: Interfacing with Dicom sistems

Post by xProgrammer »

Hi all

Please note that whilst this project will, if successful, become important to me, I have lots of higher priority tasks to attend to, so I have to fit it into odd times in the evenings or mornings mostly. Also access to DICOM systems, whilst it will be available, will be limited, especially during early testing, as we can't afford to crash cameras or processing stations whilst they are being used for medical purposes. So don't expect too much too soon.

Regards
xProgrammer
User avatar
xProgrammer
Posts: 464
Joined: Tue May 16, 2006 7:47 am
Location: Australia

Re: Interfacing with Dicom sistems

Post by xProgrammer »

Hi all

If and when we manage to get C-Echo-Rq working, the next thing to try is probably C-Find-Rq, partly because of its function, and partly because a detailed, worked example is given in appendix A.3 (page 359 on)

Regards
xProgrammer
LEADTOOLS Support
Posts: 1
Joined: Wed Jan 27, 2010 4:12 pm

Re: Interfacing with Dicom sistems

Post by LEADTOOLS Support »

Massimo Linossi wrote:Thanks Frose.
I'm reading the file you linked. I don't really know how this can be
implemented in a Xharbour program. I'm looking at the Leadtools
forum and there are the 99% of the questions that are about the
imaging process and not the patients study database.
I'll look around in the web this weekend trying to find a solution.
Thanks again.

Massimo,

I am not sure when the last time you have used LEADTOOLS was, but we have a complete toolkit for DICOM and DICOM communication. Some of our latest additions provide high level components that handle all of the DICOM specific communication for you, so you only have to write the integration portion. There are many fully functional demos to help you get started as well.

I urge you to visit us at the below link, and download an evaluation.

http://leadtools.com/sdk/pacs-imaging.htm
http://support.leadtools.com/SupportPor ... Forum.aspx

LEADTOOLS Support
LEAD Technologies Inc.
http://www.leadtools.com/
http://support.leadtools.com/cs/forums/
User avatar
xProgrammer
Posts: 464
Joined: Tue May 16, 2006 7:47 am
Location: Australia

Re: Interfacing with Dicom sistems

Post by xProgrammer »

My understanding is that Leadtools is platform (ie Windows) dependant so that being the case it wouldn't be an option that I would consider (as my application runs on Linux), but it might suit others.

Regards
xProgrammer
User avatar
Massimo Linossi
Posts: 474
Joined: Mon Oct 17, 2005 10:38 am
Location: Italy

Re: Interfacing with Dicom sistems

Post by Massimo Linossi »

I looked into the forum, and I didn't found a solution for answering a Dicom
request for the patients list. There are a lot of examples about the imaging and
other problems. Xprogrammer, I think your approach is much better, for having
something that can work in different OS. And easy to change too, if the customer
ask you to add some different features. If I can help you in some way I'm here.
Thanks a lot.
Massimo.
User avatar
xProgrammer
Posts: 464
Joined: Tue May 16, 2006 7:47 am
Location: Australia

Re: Interfacing with Dicom sistems

Post by xProgrammer »

Hi Massimo

Last night I started on code to send the DICOM messages and receive replies. Maybe 2 weeks before I have an opportunity to test. Will also start on code to decipher replies (which I should be able to test using a dummy reply).

Regards
xProgrammer
User avatar
Massimo Linossi
Posts: 474
Joined: Mon Oct 17, 2005 10:38 am
Location: Italy

Re: Interfacing with Dicom sistems

Post by Massimo Linossi »

It's a pity that you are so far, otherwise we can go to work in my customer's clinic.
If you can make a little test program for receiving the request for the patients
worklist and then send it back to the Dicom machine, I can make some debug
and eventually rearrange the code for that specific procedure.
Thanks again.
Massimo.
User avatar
xProgrammer
Posts: 464
Joined: Tue May 16, 2006 7:47 am
Location: Australia

Re: Interfacing with Dicom sistems

Post by xProgrammer »

Hi Massimo

I've planned out some changes to my DICOM classes to allow the one object to handle both received and transmitted data, as the originator or the respondent. But this week coming up is very busy for me with high priority jobs so don't expect much progress for a week.

Regards
xProgrammer
User avatar
xProgrammer
Posts: 464
Joined: Tue May 16, 2006 7:47 am
Location: Australia

Re: Interfacing with Dicom sistems

Post by xProgrammer »

Hi Massimo

Installation of new DICOM workstation was delayed - expected within the next two weeks - will keep you informed of any progress.

Regards
xProgrammer
IVAN TRACHTA
Posts: 44
Joined: Fri Feb 03, 2006 6:42 pm
Location: FORMOSA - ARGENTINA

Re: Interfacing with Dicom sistems

Post by IVAN TRACHTA »

Hi
Are there any developments regarding this topic?

I need to develop an interface between my patient administration software and equipment based on DICOM.
The mechanism appears to be using HL7 but do not know how to deploy.
The idea is to export the data from patients directly to DICOM equipment.
Appreciate to know what's new. Thanks in advance

Iván
User avatar
xProgrammer
Posts: 464
Joined: Tue May 16, 2006 7:47 am
Location: Australia

Re: Interfacing with Dicom sistems

Post by xProgrammer »

Hi Ivan

I haven't touched my DICOM code for some time now as other projects took priority. When I last used it I had it correctly requesting a session, processing the reply, requesting a session close and getting the acknowledgment.

I wasn't getting a response to a request for a list of scans so there must have been some little problem there somewhere.

Happy to share what I have. And I will get back to it some time in the not too distant future.

As it so happens I now need (as a higher priority) to write some code to generate HL7. For this application it just needs to be written as a file and dumped into a designated folder for another application to pick up and process. But note that this has to be HL7 version 2.3.1 with the modifications made by Standards Australia. I have only just started writing this code and it has to be on a very much part time basis but I would be happy to share any code and any experiences.

There are later 2.x versions of the HL7 standard plus version 3 which is XML based.

The particular message I need to deal with (at this stage) is a REF. I have just started coding for the PID segment of that message. Whilst my primary need is to generate HL7 I will be writing code to both generate it and parse it.

I also note that it looks as if this application will have to switch to HL7 version 3 sometime in 2012.

I'm not sure from your message whether you need HL7 code or DICOM code or both.

Regards
xProgrammer
Post Reply