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)