comparison OrthancStone/Sources/Toolbox/DicomStructuredReport.cpp @ 2094:7c3d65166c26

partial integration dicom-sr->mainline
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 08 Nov 2023 14:54:15 +0100
parents 51c8b21b81e4
children 79e984a89a38 67db5afb305d
comparison
equal deleted inserted replaced
2087:51c8b21b81e4 2094:7c3d65166c26
116 } 116 }
117 117
118 118
119 namespace OrthancStone 119 namespace OrthancStone
120 { 120 {
121 void DicomStructuredReport::ReferencedInstance::AddFrame(unsigned int frame)
122 {
123 if (frame == 0)
124 {
125 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
126 }
127 else
128 {
129 frames_.insert(frame - 1);
130 }
131 }
132
133
121 class DicomStructuredReport::Structure : public boost::noncopyable 134 class DicomStructuredReport::Structure : public boost::noncopyable
122 { 135 {
123 private: 136 private:
124 std::string sopInstanceUid_; 137 std::string sopInstanceUid_;
125 bool hasFrameNumber_; 138 bool hasFrameNumber_;
146 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); 159 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
147 } 160 }
148 else 161 else
149 { 162 {
150 hasFrameNumber_ = true; 163 hasFrameNumber_ = true;
151 frameNumber_ = frame; 164 frameNumber_ = frame - 1;
152 } 165 }
153 } 166 }
154 167
155 void SetProbabilityOfCancer(float probability) 168 void SetProbabilityOfCancer(float probability)
156 { 169 {
324 337
325 DicomStructuredReport::DicomStructuredReport(Orthanc::ParsedDicomFile& dicom) 338 DicomStructuredReport::DicomStructuredReport(Orthanc::ParsedDicomFile& dicom)
326 { 339 {
327 DcmDataset& dataset = *dicom.GetDcmtkObject().getDataset(); 340 DcmDataset& dataset = *dicom.GetDcmtkObject().getDataset();
328 341
342 studyInstanceUid_ = GetStringValue(dataset, DCM_StudyInstanceUID);
343 seriesInstanceUid_ = GetStringValue(dataset, DCM_SeriesInstanceUID);
344 sopInstanceUid_ = GetStringValue(dataset, DCM_SOPInstanceUID);
345
329 CheckStringValue(dataset, DCM_Modality, "SR"); 346 CheckStringValue(dataset, DCM_Modality, "SR");
330 CheckStringValue(dataset, DCM_SOPClassUID, "1.2.840.10008.5.1.4.1.1.88.33"); // Comprehensive SR IOD 347 CheckStringValue(dataset, DCM_SOPClassUID, "1.2.840.10008.5.1.4.1.1.88.33"); // Comprehensive SR IOD
331 CheckStringValue(dataset, DCM_ValueType, "CONTAINER"); 348 CheckStringValue(dataset, DCM_ValueType, "CONTAINER");
332 349
333 if (!IsDicomConcept(dataset, "126000") /* Imaging measurement report */ || 350 if (!IsDicomConcept(dataset, "126000") /* Imaging measurement report */ ||
367 std::string sopClassUid = GetStringValue(*referencedInstances->getItem(k), DCM_ReferencedSOPClassUID); 384 std::string sopClassUid = GetStringValue(*referencedInstances->getItem(k), DCM_ReferencedSOPClassUID);
368 std::string sopInstanceUid = GetStringValue(*referencedInstances->getItem(k), DCM_ReferencedSOPInstanceUID); 385 std::string sopInstanceUid = GetStringValue(*referencedInstances->getItem(k), DCM_ReferencedSOPInstanceUID);
369 386
370 if (instancesInformation_.find(sopInstanceUid) == instancesInformation_.end()) 387 if (instancesInformation_.find(sopInstanceUid) == instancesInformation_.end())
371 { 388 {
372 instancesInformation_[sopInstanceUid] = ReferencedInstance(studyInstanceUid, seriesInstanceUid, sopClassUid); 389 instancesInformation_[sopInstanceUid] = new ReferencedInstance(studyInstanceUid, seriesInstanceUid, sopClassUid);
373 } 390 }
374 else 391 else
375 { 392 {
376 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, 393 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat,
377 "Multiple occurrences of the same instance in DICOM-SR: " + sopInstanceUid); 394 "Multiple occurrences of the same instance in DICOM-SR: " + sopInstanceUid);
466 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, 483 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat,
467 "Region cannot reference multiple instances in DICOM-SR"); 484 "Region cannot reference multiple instances in DICOM-SR");
468 } 485 }
469 486
470 std::string sopInstanceUid = GetStringValue(*instances.getItem(0), DCM_ReferencedSOPInstanceUID); 487 std::string sopInstanceUid = GetStringValue(*instances.getItem(0), DCM_ReferencedSOPInstanceUID);
471 if (instancesInformation_.find(sopInstanceUid) == instancesInformation_.end()) 488 std::map<std::string, ReferencedInstance*>::iterator instanceInformation = instancesInformation_.find(sopInstanceUid);
489
490 if (instanceInformation == instancesInformation_.end())
472 { 491 {
473 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, 492 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat,
474 "Referencing unknown instance in DICOM-SR: " + sopInstanceUid); 493 "Referencing unknown instance in DICOM-SR: " + sopInstanceUid);
475 } 494 }
495
496 assert(instanceInformation->second != NULL);
476 497
477 if (instances.getItem(0)->tagExists(DCM_ReferencedFrameNumber)) 498 if (instances.getItem(0)->tagExists(DCM_ReferencedFrameNumber))
478 { 499 {
479 std::string frames = GetStringValue(*instances.getItem(0), DCM_ReferencedFrameNumber); 500 std::string frames = GetStringValue(*instances.getItem(0), DCM_ReferencedFrameNumber);
480 std::vector<std::string> tokens; 501 std::vector<std::string> tokens;
488 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); 509 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
489 } 510 }
490 else 511 else
491 { 512 {
492 AddStructure(sopInstanceUid, group, true, frame, hasProbabilityOfCancer, probabilityOfCancer); 513 AddStructure(sopInstanceUid, group, true, frame, hasProbabilityOfCancer, probabilityOfCancer);
514 instanceInformation->second->AddFrame(frame);
493 } 515 }
494 } 516 }
495 } 517 }
496 else 518 else
497 { 519 {
498 AddStructure(sopInstanceUid, group, false, 0, hasProbabilityOfCancer, probabilityOfCancer); 520 AddStructure(sopInstanceUid, group, false, 0, hasProbabilityOfCancer, probabilityOfCancer);
521 instanceInformation->second->AddFrame(1);
499 } 522 }
500 } 523 }
501 } 524 }
502 } 525 }
503 } 526 }
513 for (std::list<Structure*>::iterator it = structures_.begin(); it != structures_.end(); ++it) 536 for (std::list<Structure*>::iterator it = structures_.begin(); it != structures_.end(); ++it)
514 { 537 {
515 assert(*it != NULL); 538 assert(*it != NULL);
516 delete *it; 539 delete *it;
517 } 540 }
518 } 541
519 } 542 for (std::map<std::string, ReferencedInstance*>::iterator
543 it = instancesInformation_.begin(); it != instancesInformation_.end(); ++it)
544 {
545 assert(it->second != NULL);
546 delete it->second;
547 }
548 }
549
550
551 void DicomStructuredReport::GetReferencedInstance(std::string& studyInstanceUid,
552 std::string& seriesInstanceUid,
553 std::string& sopInstanceUid,
554 std::string& sopClassUid,
555 size_t i) const
556 {
557 if (i >= orderedInstances_.size())
558 {
559 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
560 }
561
562 sopInstanceUid = orderedInstances_[i];
563
564 std::map<std::string, ReferencedInstance*>::const_iterator found = instancesInformation_.find(sopInstanceUid);
565 if (found == instancesInformation_.end())
566 {
567 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
568 }
569
570 assert(found->second != NULL);
571 studyInstanceUid = found->second->GetStudyInstanceUid();
572 seriesInstanceUid = found->second->GetSeriesInstanceUid();
573 sopClassUid = found->second->GetSopClassUid();
574 }
575
576
577 void DicomStructuredReport::ExportReferencedFrames(std::list<ReferencedFrame>& frames) const
578 {
579 frames.clear();
580
581 for (size_t i = 0; i < orderedInstances_.size(); i++)
582 {
583 std::map<std::string, ReferencedInstance*>::const_iterator found = instancesInformation_.find(orderedInstances_[i]);
584 if (found == instancesInformation_.end())
585 {
586 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
587 }
588
589 assert(found->second != NULL);
590
591 for (std::set<unsigned int>::const_iterator frame = found->second->GetFrames().begin();
592 frame != found->second->GetFrames().end(); ++frame)
593 {
594 frames.push_back(ReferencedFrame(found->second->GetStudyInstanceUid(),
595 found->second->GetSeriesInstanceUid(),
596 orderedInstances_[i],
597 found->second->GetSopClassUid(), *frame));
598 }
599 }
600 }
601 }