Mercurial > hg > orthanc
comparison OrthancServer/DicomProtocol/DicomUserConnection.cpp @ 1368:b22ba8c5edbe query-retrieve
query retrieve
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 26 May 2015 17:54:34 +0200 |
parents | a3559b66fba7 |
children | f528849ee9f7 |
comparison
equal
deleted
inserted
replaced
1367:fe6e5a9f1ea2 | 1368:b22ba8c5edbe |
---|---|
82 #include "DicomUserConnection.h" | 82 #include "DicomUserConnection.h" |
83 | 83 |
84 #include "../../Core/OrthancException.h" | 84 #include "../../Core/OrthancException.h" |
85 #include "../ToDcmtkBridge.h" | 85 #include "../ToDcmtkBridge.h" |
86 #include "../FromDcmtkBridge.h" | 86 #include "../FromDcmtkBridge.h" |
87 #include "../../Core/DicomFormat/DicomArray.h" | |
87 | 88 |
88 #include <dcmtk/dcmdata/dcistrmb.h> | 89 #include <dcmtk/dcmdata/dcistrmb.h> |
89 #include <dcmtk/dcmdata/dcistrmf.h> | 90 #include <dcmtk/dcmdata/dcistrmf.h> |
90 #include <dcmtk/dcmdata/dcfilefo.h> | 91 #include <dcmtk/dcmdata/dcfilefo.h> |
91 #include <dcmtk/dcmdata/dcmetinf.h> | 92 #include <dcmtk/dcmdata/dcmetinf.h> |
370 | 371 |
371 payload.answers->Add(m); | 372 payload.answers->Add(m); |
372 } | 373 } |
373 } | 374 } |
374 | 375 |
376 | |
377 static void CheckFindQuery(ResourceType level, | |
378 const DicomMap& fields) | |
379 { | |
380 std::set<DicomTag> allowedTags; | |
381 | |
382 // WARNING: Do not add "break" or reorder items in this switch-case! | |
383 switch (level) | |
384 { | |
385 case ResourceType_Instance: | |
386 DicomTag::AddTagsForModule(allowedTags, DicomModule_Instance); | |
387 | |
388 case ResourceType_Series: | |
389 DicomTag::AddTagsForModule(allowedTags, DicomModule_Series); | |
390 | |
391 case ResourceType_Study: | |
392 DicomTag::AddTagsForModule(allowedTags, DicomModule_Study); | |
393 | |
394 case ResourceType_Patient: | |
395 DicomTag::AddTagsForModule(allowedTags, DicomModule_Patient); | |
396 break; | |
397 | |
398 default: | |
399 throw OrthancException(ErrorCode_InternalError); | |
400 } | |
401 | |
402 DicomArray query(fields); | |
403 for (size_t i = 0; i < query.GetSize(); i++) | |
404 { | |
405 const DicomTag& tag = query.GetElement(i).GetTag(); | |
406 if (allowedTags.find(tag) == allowedTags.end()) | |
407 { | |
408 LOG(ERROR) << "Tag not allowed for this C-Find level: " << tag; | |
409 throw OrthancException(ErrorCode_BadRequest); | |
410 } | |
411 } | |
412 } | |
413 | |
414 | |
375 void DicomUserConnection::Find(DicomFindAnswers& result, | 415 void DicomUserConnection::Find(DicomFindAnswers& result, |
376 FindRootModel model, | 416 ResourceType level, |
377 const DicomMap& fields) | 417 const DicomMap& fields) |
378 { | 418 { |
419 CheckFindQuery(level, fields); | |
420 | |
379 CheckIsOpen(); | 421 CheckIsOpen(); |
380 | 422 |
381 FindPayload payload; | 423 FindPayload payload; |
382 payload.answers = &result; | 424 payload.answers = &result; |
383 | 425 |
384 const char* sopClass; | 426 const char* sopClass; |
385 std::auto_ptr<DcmDataset> dataset(ToDcmtkBridge::Convert(fields)); | 427 std::auto_ptr<DcmDataset> dataset(ToDcmtkBridge::Convert(fields)); |
386 switch (model) | 428 switch (level) |
387 { | 429 { |
388 case FindRootModel_Patient: | 430 case ResourceType_Patient: |
389 payload.level = "PATIENT"; | 431 payload.level = "PATIENT"; |
390 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "PATIENT"); | 432 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "PATIENT"); |
391 sopClass = UID_FINDPatientRootQueryRetrieveInformationModel; | 433 sopClass = UID_FINDPatientRootQueryRetrieveInformationModel; |
392 | |
393 // Accession number | |
394 if (!fields.HasTag(0x0008, 0x0050)) | |
395 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0050), ""); | |
396 | |
397 // Patient ID | |
398 if (!fields.HasTag(0x0010, 0x0020)) | |
399 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0010, 0x0020), ""); | |
400 | |
401 break; | 434 break; |
402 | 435 |
403 case FindRootModel_Study: | 436 case ResourceType_Study: |
404 payload.level = "STUDY"; | 437 payload.level = "STUDY"; |
405 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "STUDY"); | 438 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "STUDY"); |
406 sopClass = UID_FINDStudyRootQueryRetrieveInformationModel; | 439 sopClass = UID_FINDStudyRootQueryRetrieveInformationModel; |
407 | |
408 // Accession number | |
409 if (!fields.HasTag(0x0008, 0x0050)) | |
410 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0050), ""); | |
411 | |
412 // Study instance UID | |
413 if (!fields.HasTag(0x0020, 0x000d)) | |
414 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000d), ""); | |
415 | |
416 break; | 440 break; |
417 | 441 |
418 case FindRootModel_Series: | 442 case ResourceType_Series: |
419 payload.level = "SERIES"; | 443 payload.level = "SERIES"; |
420 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "SERIES"); | 444 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "SERIES"); |
421 sopClass = UID_FINDStudyRootQueryRetrieveInformationModel; | 445 sopClass = UID_FINDStudyRootQueryRetrieveInformationModel; |
422 | |
423 // Accession number | |
424 if (!fields.HasTag(0x0008, 0x0050)) | |
425 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0050), ""); | |
426 | |
427 // Study instance UID | |
428 if (!fields.HasTag(0x0020, 0x000d)) | |
429 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000d), ""); | |
430 | |
431 // Series instance UID | |
432 if (!fields.HasTag(0x0020, 0x000e)) | |
433 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000e), ""); | |
434 | |
435 break; | 446 break; |
436 | 447 |
437 case FindRootModel_Instance: | 448 case ResourceType_Instance: |
438 payload.level = "INSTANCE"; | 449 payload.level = "INSTANCE"; |
439 if (manufacturer_ == ModalityManufacturer_ClearCanvas || | 450 if (manufacturer_ == ModalityManufacturer_ClearCanvas || |
440 manufacturer_ == ModalityManufacturer_Dcm4Chee) | 451 manufacturer_ == ModalityManufacturer_Dcm4Chee) |
441 { | 452 { |
442 // This is a particular case for ClearCanvas, thanks to Peter Somlo <peter.somlo@gmail.com>. | 453 // This is a particular case for ClearCanvas, thanks to Peter Somlo <peter.somlo@gmail.com>. |
448 { | 459 { |
449 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "INSTANCE"); | 460 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "INSTANCE"); |
450 } | 461 } |
451 | 462 |
452 sopClass = UID_FINDStudyRootQueryRetrieveInformationModel; | 463 sopClass = UID_FINDStudyRootQueryRetrieveInformationModel; |
453 | 464 break; |
465 | |
466 default: | |
467 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
468 } | |
469 | |
470 // Add the expected tags for this query level. | |
471 // WARNING: Do not reorder or add "break" in this switch-case! | |
472 switch (level) | |
473 { | |
474 case ResourceType_Instance: | |
475 // SOP Instance UID | |
476 if (!fields.HasTag(0x0008, 0x0018)) | |
477 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0018), ""); | |
478 | |
479 case ResourceType_Series: | |
480 // Series instance UID | |
481 if (!fields.HasTag(0x0020, 0x000e)) | |
482 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000e), ""); | |
483 | |
484 case ResourceType_Study: | |
454 // Accession number | 485 // Accession number |
455 if (!fields.HasTag(0x0008, 0x0050)) | 486 if (!fields.HasTag(0x0008, 0x0050)) |
456 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0050), ""); | 487 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0050), ""); |
457 | 488 |
458 // Study instance UID | 489 // Study instance UID |
459 if (!fields.HasTag(0x0020, 0x000d)) | 490 if (!fields.HasTag(0x0020, 0x000d)) |
460 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000d), ""); | 491 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000d), ""); |
461 | 492 |
462 // Series instance UID | 493 case ResourceType_Patient: |
463 if (!fields.HasTag(0x0020, 0x000e)) | 494 // Patient ID |
464 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000e), ""); | 495 if (!fields.HasTag(0x0010, 0x0020)) |
465 | 496 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0010, 0x0020), ""); |
466 // SOP Instance UID | |
467 if (!fields.HasTag(0x0008, 0x0018)) | |
468 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0018), ""); | |
469 | 497 |
470 break; | 498 break; |
471 | 499 |
472 default: | 500 default: |
473 throw OrthancException(ErrorCode_ParameterOutOfRange); | 501 throw OrthancException(ErrorCode_ParameterOutOfRange); |
499 { | 527 { |
500 delete statusDetail; | 528 delete statusDetail; |
501 } | 529 } |
502 | 530 |
503 Check(cond); | 531 Check(cond); |
504 } | |
505 | |
506 | |
507 void DicomUserConnection::FindPatient(DicomFindAnswers& result, | |
508 const DicomMap& fields) | |
509 { | |
510 // Only keep the filters from "fields" that are related to the patient | |
511 DicomMap s; | |
512 fields.ExtractPatientInformation(s); | |
513 Find(result, FindRootModel_Patient, s); | |
514 } | |
515 | |
516 void DicomUserConnection::FindStudy(DicomFindAnswers& result, | |
517 const DicomMap& fields) | |
518 { | |
519 // Only keep the filters from "fields" that are related to the study | |
520 DicomMap s; | |
521 fields.ExtractStudyInformation(s); | |
522 | |
523 s.CopyTagIfExists(fields, DICOM_TAG_PATIENT_ID); | |
524 s.CopyTagIfExists(fields, DICOM_TAG_ACCESSION_NUMBER); | |
525 s.CopyTagIfExists(fields, DICOM_TAG_MODALITIES_IN_STUDY); | |
526 | |
527 Find(result, FindRootModel_Study, s); | |
528 } | |
529 | |
530 void DicomUserConnection::FindSeries(DicomFindAnswers& result, | |
531 const DicomMap& fields) | |
532 { | |
533 // Only keep the filters from "fields" that are related to the series | |
534 DicomMap s; | |
535 fields.ExtractSeriesInformation(s); | |
536 | |
537 s.CopyTagIfExists(fields, DICOM_TAG_PATIENT_ID); | |
538 s.CopyTagIfExists(fields, DICOM_TAG_ACCESSION_NUMBER); | |
539 s.CopyTagIfExists(fields, DICOM_TAG_STUDY_INSTANCE_UID); | |
540 | |
541 Find(result, FindRootModel_Series, s); | |
542 } | |
543 | |
544 void DicomUserConnection::FindInstance(DicomFindAnswers& result, | |
545 const DicomMap& fields) | |
546 { | |
547 // Only keep the filters from "fields" that are related to the instance | |
548 DicomMap s; | |
549 fields.ExtractInstanceInformation(s); | |
550 | |
551 s.CopyTagIfExists(fields, DICOM_TAG_PATIENT_ID); | |
552 s.CopyTagIfExists(fields, DICOM_TAG_ACCESSION_NUMBER); | |
553 s.CopyTagIfExists(fields, DICOM_TAG_STUDY_INSTANCE_UID); | |
554 s.CopyTagIfExists(fields, DICOM_TAG_SERIES_INSTANCE_UID); | |
555 | |
556 Find(result, FindRootModel_Instance, s); | |
557 } | 532 } |
558 | 533 |
559 | 534 |
560 void DicomUserConnection::MoveInternal(const std::string& targetAet, | 535 void DicomUserConnection::MoveInternal(const std::string& targetAet, |
561 const DicomMap& fields) | 536 const DicomMap& fields) |