Why can PACS return 0000,0092 values through c-move-rsp - dicom

I use dcmtk3.6.3 send c-move command to pacs.
And dcmtk receives the c-move-rsp which get an error with "(0000, 0902)".
I know the reason for the error,but I don't know Why can PACS return 0000,0092 values through c-move-rsp?
As far as I know,C-move-rsp only has status 0000,0090 in dicom, and has no tag of "(0000, 0902)"
Is the error message of "(0000, 0902)" passed through c-move-rsp?

Well, I am not sure that the status is not correctly communicated in (0000,0900) since the most interesting part of the dcmtk output is omitted. Try to use -ll TRACE option for the movescu and look for "DIMSE Command Received:". Then you can see the original dataset sent by the C-MOVE SCP. It should read somehow like this:
T: DIMSE Command Received:
T:
T: # Dicom-Data-Set
T: # Used TransferSyntax: Little Endian Implicit
T: (0000,0002) UI =MOVEPatientRootQueryRetrieveInformationModel # 28, 1 AffectedSOPClassUID
T: (0000,0100) US 32801 # 2, 1 CommandField
T: (0000,0120) US 1 # 2, 1 MessageIDBeingRespondedTo
T: (0000,0800) US 0 # 2, 1 CommandDataSetType
T: (0000,0900) US 43009 # 2, 1 Status
T: (0000,1021) US 0 # 2, 1 NumberOfCompletedSuboperations
T: (0000,1022) US 3 # 2, 1 NumberOfFailedSuboperations
But since the valid status 0xa702 is correctly reported in the screenshot you posted, I strongly suspect it is present in the MOVE-SCP's response.
However, you are correct that the attribte (0000,0902) is not allowed for that particular status code. See PS3.4, Table C.4-2. The status must always be present. Depending on the status code, additional attributes may be used to convey additional information about the status (e.g. why the operation failed or which objects were affected). The table referenced above lists which additional attributes are allowed for which status.

I find the answer from dicom3.0.

Related

Issue with Setting the Command Set in N_CREATE Response, pydicom

I'm working on a MPPS SCP as described here: MPPS SCP as a basic framework.
I've been able to test it a bit with DVTk, with some tools that are available here: DVTk
Most of it seems to be working correctly, but the issue I seem to be having is that the response is suppose to have tags with group 0000 returned in the "Command Set" and not in the returned DataSet itself: I actually did set them in the DataSet just to verify that I am getting the correct values, e.g.:
python_mpps_1 | (0000, 0000) Command Group Length ????
python_mpps_1 | (0000, 0002) Affected SOP Class UID UI: Modality Performed Procedure Step SOP Class
python_mpps_1 | (0000, 0100) Command Field US: 33088
python_mpps_1 | (0000, 0120) Message ID Being Responded To US: 2
python_mpps_1 | (0000, 0800) Command Data Set Type US: 0
python_mpps_1 | (0000, 0900) Status US: 0
python_mpps_1 | (0008, 0016) SOP Class UID UI: Modality Performed Procedure Step SOP Class
I'm not exactly sure what Command Group Length, Command Field and Command Data Set Type should be, but more importantly, I do not know how to set them appropriately. I do not think they should be set in the Dataset, but part of the Command Set object for the N_CREATE response:
# 'N-CREATE-RSP': (
# 'CommandGroupLength', 'AffectedSOPClassUID', 'CommandField',
# 'MessageIDBeingRespondedTo', 'CommandDataSetType', 'Status',
# 'AffectedSOPInstanceUID',
# 'ErrorID', 'ErrorComment'
# ),
Using DVTk as a testing tool, the MPPS.SCU script in their example scripts, everything seems to work except for the Command Set values not being sent in the response. After a little digging, I think those have to be set in another way, but I am not sure how.
The pynetdicom documentation might have some further info about that (first link), but I've been unable to find it.
The Command Group Length (0000,0000) is the total number of bytes of your binary encoded message. This should usually be set by the toolkit that you are using (see comment from Scaramillion).
Your command type is an N-CREATE Response, and usually this comes without any dataset. Not knowing the DVT script, I assume that your script does not expect a dataset being attached to the command set.
I.e. SOP Class UID (0008, 0016) should not be present (it is already part of the Command Set as Affected SOP Class UID (0000,0002)), and Command Data Set Type (0000, 0800) should be set to 0x0101 to indicate that no data set is following the command set.
At least this counts for a successful N-CREATE operation.

Eva plugin of Frama-C reports "invalid user input" after finishing analysis

I get the following log when I am trying to apply Eva plugin to a C project.
[eva:summary] ====== ANALYSIS SUMMARY ======
----------------------------------------------------------------------------
53 functions analyzed (out of 9107): 0% coverage.
In these functions, 5300 statements reached (out of 14354): 36% coverage.
----------------------------------------------------------------------------
Some errors and warnings have been raised during the analysis:
by the Eva analyzer: 0 errors 15 warnings
by the Frama-C kernel: 0 errors 2 warnings
----------------------------------------------------------------------------
45 alarms generated by the analysis:
29 invalid memory accesses
4 accesses out of bounds index
6 invalid shifts
1 access to uninitialized left-values
5 others
----------------------------------------------------------------------------
Evaluation of the logical properties reached by the analysis:
Assertions 1113 valid 18 unknown 1 invalid 1132 total
Preconditions 0 valid 0 unknown 0 invalid 0 total
98% of the logical properties reached have been proven.
----------------------------------------------------------------------------
[kernel] Warning: warning CERT:MSC:38 treated as deferred error. See above messages for more information.
[kernel] Frama-C aborted: invalid user input.
Frama-C aborted the analysis after providing the analysis summary. However, it does not point out which file and which line of code that has a problem.
Could you please let me know which are possible problems in this case? And is the analysis finished?
As the header of the line indicates, the message is not emitted by Eva, but by Frama-C's kernel. This error indicates that your code is violating CERT C Coding Standard, and more specifically its rule MSC-38 which basically states that it is a bad idea to declare identifiers that belong to the standard library, where they are specified as being potentially implemented as a macro. This notably includes assert and errno.
As this rule indicates that the code is not strictly ISO-C compliant, it has been decided to treat it by default as an error, but given the fact that the issue by itself is unlikely to make the analyzers crash, Frama-C does not abort as soon as it is triggered. This is why you can still launch Eva, which runs flawlessly, before being reminded by the kernel that there is an issue in your code (a first message, with Warning status, was likely output at the beginning of the log).
You can modify the severity status of CERT:MSC:38 using -kernel-warn-key CERT:MSC:38=<status>, where <status> can range from inactive (completely ignored) to abort (emit an error and abort immediately). The complete list of statuses can be found on section 6.2 of the user manual.

[DICOM][MergeCOM] MC3 E: Total attribute length (4) not a multiple of size

I have an older version of mergecom library( V4.4.0 ). And now I received the latest version(V5.4.0 ). When I tried to integrate the latest MergeCom library I am getting following error on C-ECHO( logged in merge.log ).
DICOM;(20936) 06-21 17:59:01.28 MC3 E: Total attribute length (4) not a multiple of size
DICOM;(20936) 06-21 17:59:01.28 MC3 E: for VR (UN): 8, tag '0x0'
DICOM;(20936) 06-21 17:59:01.28 MC3(ReadMessageToTag) E: Message received encoded improperly Invalid VR length in stream data .
Please find the attached wireshark logs snapshots
Wireshark
1. ASSOCIATION-RQ
2.ASSOCIATION-RSP
3.ECHO-RQ
4.ECHO-RSP
5.ABORT
The error log from MergeCOM-3 is implying a parsing error when reading the C-ECHO-RSP. The log message is implying MergeCOM-3 did not identify the group 0 element's value representation, and instead interpreted it as UN.
From the appearance of the C-ECHO-RSP in the WireShark capture, it appears to be encoded properly and WireShark was able to decode the C-ECHO-RSP.
Were there any other errors in the logs? Is your data dictionary being loaded properly, such that the library would know the VR of the group 0 length tag (0000,0000)?

Why can't I use hPutStr after printing the result of hGetContents?

I'm new to stackoverflow so forgive me if I do something wrong. I trying to understand how a simple server would work in Haskell. I think I'm missing something very simple or fundamental about how hGetContents works.
import Network
import System.IO
main = withSocketsDo $ do
socket <- listenOn $ PortNumber 5002
(h, _, _) <- accept socket
c <- hGetContents h
-- putStrLn c -- doesn't work
-- putStrLn $ head $ lines c -- works!
-- putStrLn $ unlines $ take 2 $ lines c -- works!
-- putStrLn $ unlines $ take 3 $ lines c -- works!
-- putStrLn $ unlines $ take 6 $ lines c -- works!
putStrLn $ unlines $ take 10 $ lines c -- doesn't work
hPutStr h $ "HTTP/1.0 200 OK\r\nContent-Length: 5\r\n\r\nHello!\r\n"
hClose h
After running the program, I navigate via web browser to http://localhost:5002. The problem seems to be that, depending on how much I've parsed the handle contents, I eventually am unable to send a response. I'd like to be able to parse the request before I send a response. I've commented in the code the cases that work and the cases that don't. Hoogle says that for hGetContents (lazy) the handle is "semi-closed" as it is being read. Am I misunderstanding the laziness or should I consider the handle closed once I begin parsing its contents?
The error I get is "hPutChar: resource vanished (Broken pipe)." Thanks for any help.
I tried to reproduce your problem. For that I executed your code and send it a request using nc:
printf "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11" | nc localhost 5002
As expected the server (code from your question) printed out first 10 lines and exited without any error. The client (nc) printed:
HTTP/1.0 200 OK
Content-Length: 5
Hello!
and also exited without an error.
So, at first I couldn't understand what's your problem, but then I tried to send a smaller request:
printf "1\n2\n3\n4\n5\n6\n" | nc localhost 5002
The server printed first 6 lines and didn't exit. The client also didn't exit, so I interrupted it with Ctrl-C and after that the server exited with "resource vanished" error.
I took some thinking and it started making sense to me. I don't understand lazy IO too good, so if my explanation isn't clear or correct it would be helpful if someone with better understanding would improve it.
Let's follow your code. First:
(h, _, _) <- accept socket
c <- hGetContents h
You open a handle and read it's content. Note that the handle is lazy and the content that you get is also lazy. When we say that something is lazy we mean that it can be passed around without being evaluated (it's often referred as 'call by name' vs 'call by value').
Now:
putStrLn $ unlines $ take 10 $ lines c
Here it is, you pass your lazy, unevaluated content to another function take 10. take 10 will try to evaluate first 10 elements of a list and return them, if there are less than 10 elements in the list it would simply return all of them. After take 10 we have putStrLn and unlines which both perfectly compatible with laziness.
Now let's say that client sends an input that is only 6 lines long and then starts waiting for the respond. Our server lazily receives the content and tries to print first 10 lines. First, take 10 function happily consumes the first 6 lines and passes them over to putStrLn . unlines, what happens then? take 10 can't just finish it's output because there is absolutely no indication that it is the end. The handle is still open, bytes still can be floating from client to server, so it just waits for more input.
This behaviour can be observed by running:
nc localhost 5002
and manually typing there 10 lines. The input would appear on server line-by-line as you type. After you will type the 10th line the server will respond with "Hello" message.
P.S: I guess that the behaviour that you described happens because you web browser sends 6 to 9 lines of something with the request.
To test, debug and analyze this kind of low level servers you should use simple tools like nc and curl instead of your web browser :)
When you initiate a lazy read on a handle, you give up the right to do anything much else with the handle until the contents string is fully forced, or you close the handle manually (at which point attempting to force any more of the contents string will lead to bad behavior or an error).
TL;DR
This is not a situation where lazy I/O is appropriate. The situations where a lazy read on a socket is appropriate can probably be counted on zero fingers. You can use regular strict I/O if you like, or conduit, or pipes, or some Haskell web framework like Yesod or Scotty or various other competitors.
Calling hGetContents puts the handle into a "semi-closed" state. You should not perform any operations on the handle after that point. You should only use the string returned from hGetContents.
Put simply, don't use lazy I/O here. You need to manually read and write individual strings one at a time, since the timing matters.
In general, lazy I/O is kind of neat, but it doesn't work well for anything much beyond toy examples.

How to download historical data with twsInstrument using getContract?

When downloading data from interactive brokers some future contracts can be downloaded properly others not.
R console command:
icegasoil_feb <- getContract("GOILG2")
Connected with clientId 100.
Error in buildIBcontract(symbol = instrument, tws = tws, addIBslot = addIBslot, :
Could not create valid twsContract.
GOI may not be a valid CASH. Disconnected.
Next error when using getBAT is :
getBAT("ZWH2")
Connected with clientId 120.
waiting for TWS reply on ZW ............failed.
waiting for TWS reply on ZW ....failed.
waiting for TWS reply on ZW ....failed.
Disconnecting ...
NULL
Failure:
1: In errorHandler(con, verbose, OK = c(165, 300, 366, 2104, 2106, :
Historical Market Data Service error message:No data of type DayChart is available for
the exchange 'CBOT' and the security type 'Futures' and '5 d' and '1 min'
able for the exchange 'CBOT' and the security type 'Futures' and '5 d' and '1 min'
The first problem you encountered will not occur if you update
FinancialInstrument.
Prior to revision 888, FinancialInstrument:::parse_id --
which is used internally by twsInstrument -- would have thought a Symbol like
"GOILG2" should have a root_id of "GO" because it would have seen "ILG2" as a
4 character suffix similar to the ones that Interactive Brokers uses for single
stock futures. One way around this is to use an underscore to separate the
root_id from the suffix_id so that parse_id does not have to deal with an
ambiguous id. So, getContract("GOIL_G2") should have worked, and is still
the recommended format for instrument ids. That said, if you update
FinancialInstrument, it will work as is.
> require("twsInstrument")
> getContract("GOILG2")
Connected with clientId 100.
Checking to see if other 'type's have a pre-defined currency.
Request complete: GOIL FUT USD.
Disconnected.
List of 16
$ conId : chr "34134707"
$ symbol : chr "GOIL"
$ sectype : chr "FUT"
$ exch : chr "IPE"
$ primary : chr ""
$ expiry : chr "20120210"
$ strike : chr "0"
$ currency : chr "USD"
$ right : chr ""
$ local : chr "GOILG2"
$ multiplier : chr "100"
$ combo_legs_desc: chr ""
$ comboleg : chr ""
$ include_expired: chr "0"
$ secIdType : chr ""
$ secId : chr ""
The second problem is a little trickier. Basically, more than one contract
was found that corresponds to "ZWH2" and the "wrong" one was used (pit-traded
instead of the electronic). Before getting to the solution, allow me to give
a little background.
The twsInstrument package was built with the intention of using Interactive
Brokers to help me update the metadata of instruments that I had already
defined with the FinancialInstrument package.
It will take what information it has and use that to gather more information.
When you use getContract it will first search locally for the twsContract.
If it cannot find it, then it will see if instrument metadata has been defined
in the FinancialInstrument:::.instrument environment. If so, that information
will be used to create a shell of a twsContract that can be passed to
IBrokers:::reqContractDetails, which will fill in the missing parts. If there
is no instrument definition for this Symbol, then FinancialInstrument:::parse_id
will figure out the information required by IBrokers:::reqContractDetails.
If Interactive Brokers has several contracts that match the info given, it will
return a list of all of them. Unfortunately, I did not realize this when I
wrote twsInstrument. So, only the first element of the list will be used.
FWIW, the IB API does appear to try to be smart about which contract it returns
first, but that can actually cause frustrations when it is giving you a different
contract depending on which contract you looked at last, for example.
In your case, you are asking for data on "ZWH2". The first contract that
reqContractDetails returns will be the future that trades on "CBOT", but as you
can see from the error message you got, that data is not available. That's
because you really want the one that trades on "ECBOT". The following shows how
to see the list of length 2 that IBrokers:::reqContractDetails returns.
require("IBrokers")
fut <- twsContract()
fut$symbol <- 'ZW'
fut$sectype <- 'FUT'
fut$expiry <- '201203'
fut$currency <- 'USD'
tws <- ConnectIB()
reqContractDetails(tws, fut)
twsDisconnect(tws)
The way to ensure that you get the contract you want is to use enough information
that reqContractDetails does not find more than one match.
e.g.
> define_futures("ZW", "ECBOT", "201203")
Connected with clientId 100.
Request complete: ZW FUT USD.
Disconnected.
[1] "ZW_MAR12"
> getBAT("ZW_MAR12")
Connected with clientId 120.
waiting for TWS reply on ZW ....... done.
Pausing 10 seconds between requests ...
waiting for TWS reply on ZW .... done.
Pausing 10 seconds between requests ...
waiting for TWS reply on ZW .... done.
Pausing 10 seconds between requests ...
Disconnecting ...
[1] "ZW_MAR12"
define_futures makes the primary_id of the instrument based off the value of
"local" in the twsContract. In this case, it is "ZW_MAR12". If you want the
id to be "ZWH2", you can change it with FinancialInstrument:::instrument_attr
> instrument_attr("ZW_MAR12", "primary_id", "ZWH2")
> # Now your original code will work
> getBAT("ZWH2")
Connected with clientId 120.
waiting for TWS reply on ZW ....... done.
Pausing 10 seconds between requests ...
waiting for TWS reply on ZW .... done.
Pausing 10 seconds between requests ...
waiting for TWS reply on ZW .... done.
Pausing 10 seconds between requests ...
Disconnecting ...
[1] "ZWH2"
Alternatively, you could define the instrument using only the FinancialInstrument
package making sure to provide the exchange:
future("ZW", currency("USD"), 5000, exchange='ECBOT')
future_series("ZWH2")
getBAT("ZWH2")
Finally, if you have revision 233 or later of twsInstrument, the following
will also work to define the instrument:
twsInstrument(twsFUT("ZW", "ECBOT", "201203"))
I would have responded sooner, but I don't visit SO all that often. You'll get a
quicker response about twsInstrument if you send your question to either the
r-sig-finance list, or directly to me (my e-mail address is in the DESCRIPTION
file of the package). Please note that twsInstrument is still under development.

Resources