Mercurial > hg > orthanc
comparison OrthancServer/ServerIndex.cpp @ 80:6212bf978584
status of series
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 20 Sep 2012 15:18:12 +0200 |
parents | b8dfde8d64e8 |
children | 9eb40cad7935 |
comparison
equal
deleted
inserted
replaced
79:297bad4e1019 | 80:6212bf978584 |
---|---|
229 const std::string& jsonUuid, | 229 const std::string& jsonUuid, |
230 const std::string& distantAet) | 230 const std::string& distantAet) |
231 { | 231 { |
232 std::string instanceUuid = Toolbox::GenerateUuid(); | 232 std::string instanceUuid = Toolbox::GenerateUuid(); |
233 | 233 |
234 SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Instances VALUES(?, ?, ?, ?, ?, ?, ?)"); | 234 SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Instances VALUES(?, ?, ?, ?, ?, ?, ?, ?)"); |
235 s.BindString(0, instanceUuid); | 235 s.BindString(0, instanceUuid); |
236 s.BindString(1, parentSeriesUuid); | 236 s.BindString(1, parentSeriesUuid); |
237 s.BindString(2, dicomInstance); | 237 s.BindString(2, dicomInstance); |
238 s.BindString(3, fileUuid); | 238 s.BindString(3, fileUuid); |
239 s.BindInt64(4, fileSize); | 239 s.BindInt64(4, fileSize); |
240 s.BindString(5, jsonUuid); | 240 s.BindString(5, jsonUuid); |
241 s.BindString(6, distantAet); | 241 s.BindString(6, distantAet); |
242 | |
243 const DicomValue* indexInSeries; | |
244 if ((indexInSeries = dicomSummary.TestAndGetValue(DICOM_TAG_INSTANCE_NUMBER)) != NULL || | |
245 (indexInSeries = dicomSummary.TestAndGetValue(DICOM_TAG_IMAGE_INDEX)) != NULL) | |
246 { | |
247 s.BindInt(7, boost::lexical_cast<unsigned int>(indexInSeries->AsString())); | |
248 } | |
249 else | |
250 { | |
251 s.BindNull(7); | |
252 } | |
253 | |
242 s.Run(); | 254 s.Run(); |
243 | 255 |
244 RecordChange("instances", instanceUuid); | 256 RecordChange("instances", instanceUuid); |
245 | 257 |
246 DicomMap dicom; | 258 DicomMap dicom; |
281 | 293 |
282 SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Series VALUES(?, ?, ?, ?)"); | 294 SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Series VALUES(?, ?, ?, ?)"); |
283 s.BindString(0, seriesUuid); | 295 s.BindString(0, seriesUuid); |
284 s.BindString(1, parentStudyUuid); | 296 s.BindString(1, parentStudyUuid); |
285 s.BindString(2, dicomSeries); | 297 s.BindString(2, dicomSeries); |
286 s.BindNull(3); | 298 |
299 const DicomValue* expectedNumberOfInstances; | |
300 if ((expectedNumberOfInstances = dicomSummary.TestAndGetValue(DICOM_TAG_NUMBER_OF_FRAMES)) != NULL || | |
301 (expectedNumberOfInstances = dicomSummary.TestAndGetValue(DICOM_TAG_NUMBER_OF_SLICES)) != NULL || | |
302 (expectedNumberOfInstances = dicomSummary.TestAndGetValue(DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES)) != NULL || | |
303 (expectedNumberOfInstances = dicomSummary.TestAndGetValue(DICOM_TAG_IMAGES_IN_ACQUISITION)) != NULL) | |
304 { | |
305 s.BindInt(3, boost::lexical_cast<unsigned int>(expectedNumberOfInstances->AsString())); | |
306 } | |
307 else | |
308 { | |
309 s.BindNull(3); | |
310 } | |
311 | |
287 s.Run(); | 312 s.Run(); |
288 | 313 |
289 RecordChange("series", seriesUuid); | 314 RecordChange("series", seriesUuid); |
290 | 315 |
291 DicomMap dicom; | 316 DicomMap dicom; |
352 | 377 |
353 std::string ServerIndex::CreatePatient(const std::string& patientId, | 378 std::string ServerIndex::CreatePatient(const std::string& patientId, |
354 const DicomMap& dicomSummary) | 379 const DicomMap& dicomSummary) |
355 { | 380 { |
356 std::string patientUuid = Toolbox::GenerateUuid(); | 381 std::string patientUuid = Toolbox::GenerateUuid(); |
357 std::string dicomPatientId = dicomSummary.GetValue(DicomTag::PATIENT_ID).AsString(); | 382 std::string dicomPatientId = dicomSummary.GetValue(DICOM_TAG_PATIENT_ID).AsString(); |
358 | 383 |
359 SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Patients VALUES(?, ?)"); | 384 SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Patients VALUES(?, ?)"); |
360 s.BindString(0, patientUuid); | 385 s.BindString(0, patientUuid); |
361 s.BindString(1, dicomPatientId); | 386 s.BindString(1, dicomPatientId); |
362 s.Run(); | 387 s.Run(); |
472 const std::string& jsonUuid, | 497 const std::string& jsonUuid, |
473 const std::string& distantAet) | 498 const std::string& distantAet) |
474 { | 499 { |
475 boost::mutex::scoped_lock scoped_lock(mutex_); | 500 boost::mutex::scoped_lock scoped_lock(mutex_); |
476 | 501 |
477 std::string dicomPatientId = dicomSummary.GetValue(DicomTag::PATIENT_ID).AsString(); | 502 std::string dicomPatientId = dicomSummary.GetValue(DICOM_TAG_PATIENT_ID).AsString(); |
478 std::string dicomInstance = dicomSummary.GetValue(DicomTag::SOP_INSTANCE_UID).AsString(); | 503 std::string dicomInstance = dicomSummary.GetValue(DICOM_TAG_SOP_INSTANCE_UID).AsString(); |
479 std::string dicomSeries = dicomSummary.GetValue(DicomTag::SERIES_INSTANCE_UID).AsString(); | 504 std::string dicomSeries = dicomSummary.GetValue(DICOM_TAG_SERIES_INSTANCE_UID).AsString(); |
480 std::string dicomStudy = dicomSummary.GetValue(DicomTag::STUDY_INSTANCE_UID).AsString(); | 505 std::string dicomStudy = dicomSummary.GetValue(DICOM_TAG_STUDY_INSTANCE_UID).AsString(); |
481 | 506 |
482 try | 507 try |
483 { | 508 { |
484 SQLite::Transaction t(db_); | 509 SQLite::Transaction t(db_); |
485 t.Begin(); | 510 t.Begin(); |
582 } | 607 } |
583 | 608 |
584 | 609 |
585 SeriesStatus ServerIndex::GetSeriesStatus(const std::string& seriesUuid) | 610 SeriesStatus ServerIndex::GetSeriesStatus(const std::string& seriesUuid) |
586 { | 611 { |
587 int numberOfSlices; | 612 SQLite::Statement s1(db_, SQLITE_FROM_HERE, "SELECT expectedNumberOfInstances FROM Series WHERE uuid=?"); |
588 if (!GetMainDicomIntTag(numberOfSlices, seriesUuid, DicomTag::NUMBER_OF_SLICES) || | 613 s1.BindString(0, seriesUuid); |
589 numberOfSlices < 0) | 614 if (!s1.Step()) |
590 { | 615 { |
591 return SeriesStatus_Unknown; | 616 return SeriesStatus_Unknown; |
592 } | 617 } |
593 | 618 |
594 // Loop over the instances of the series | 619 int numberOfInstances = s1.ColumnInt(0); |
595 //std::set< | 620 if (numberOfInstances < 0) |
596 | 621 { |
597 // TODO | 622 return SeriesStatus_Unknown; |
598 return SeriesStatus_Unknown; | 623 } |
599 } | 624 |
600 | 625 std::set<int> instances; |
601 | 626 SQLite::Statement s2(db_, SQLITE_FROM_HERE, "SELECT indexInSeries FROM Instances WHERE parentSeries=?"); |
627 s2.BindString(0, seriesUuid); | |
628 while (s2.Step()) | |
629 { | |
630 int index = s2.ColumnInt(0); | |
631 if (index <= 0 || index > numberOfInstances) | |
632 { | |
633 // Out-of-range instance index | |
634 return SeriesStatus_Inconsistent; | |
635 } | |
636 | |
637 if (instances.find(index) != instances.end()) | |
638 { | |
639 // Twice the same instance index | |
640 return SeriesStatus_Inconsistent; | |
641 } | |
642 | |
643 instances.insert(index); | |
644 } | |
645 | |
646 for (int i = 1; i <= numberOfInstances; i++) | |
647 { | |
648 if (instances.find(i) == instances.end()) | |
649 { | |
650 return SeriesStatus_Missing; | |
651 } | |
652 } | |
653 | |
654 return SeriesStatus_Complete; | |
655 } | |
602 | 656 |
603 | 657 |
604 | 658 |
605 bool ServerIndex::GetInstance(Json::Value& result, | 659 bool ServerIndex::GetInstance(Json::Value& result, |
606 const std::string& instanceUuid) | 660 const std::string& instanceUuid) |
607 { | 661 { |
608 assert(result.type() == Json::objectValue); | 662 assert(result.type() == Json::objectValue); |
609 boost::mutex::scoped_lock scoped_lock(mutex_); | 663 boost::mutex::scoped_lock scoped_lock(mutex_); |
610 | 664 |
611 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT parentSeries, dicomInstance, fileSize, fileUuid FROM Instances WHERE uuid=?"); | 665 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT parentSeries, dicomInstance, fileSize, fileUuid, indexInSeries FROM Instances WHERE uuid=?"); |
612 s.BindString(0, instanceUuid); | 666 s.BindString(0, instanceUuid); |
613 if (!s.Step()) | 667 if (!s.Step()) |
614 { | 668 { |
615 return false; | 669 return false; |
616 } | 670 } |
619 result["ID"] = instanceUuid; | 673 result["ID"] = instanceUuid; |
620 result["ParentSeries"] = s.ColumnString(0); | 674 result["ParentSeries"] = s.ColumnString(0); |
621 result["FileSize"] = s.ColumnInt(2); // TODO switch to 64bit with JsonCpp 0.6? | 675 result["FileSize"] = s.ColumnInt(2); // TODO switch to 64bit with JsonCpp 0.6? |
622 result["FileUuid"] = s.ColumnString(3); | 676 result["FileUuid"] = s.ColumnString(3); |
623 MainDicomTagsToJson(result, instanceUuid); | 677 MainDicomTagsToJson(result, instanceUuid); |
678 | |
679 if (s.ColumnIsNull(4)) | |
680 { | |
681 result["IndexInSeries"] = -1; | |
682 } | |
683 else | |
684 { | |
685 result["IndexInSeries"] = s.ColumnInt(4); | |
686 } | |
687 | |
624 return true; | 688 return true; |
625 } | 689 } |
626 } | 690 } |
627 | 691 |
628 | 692 |
630 const std::string& seriesUuid) | 694 const std::string& seriesUuid) |
631 { | 695 { |
632 assert(result.type() == Json::objectValue); | 696 assert(result.type() == Json::objectValue); |
633 boost::mutex::scoped_lock scoped_lock(mutex_); | 697 boost::mutex::scoped_lock scoped_lock(mutex_); |
634 | 698 |
635 SQLite::Statement s1(db_, SQLITE_FROM_HERE, "SELECT parentStudy, dicomSeries FROM Series WHERE uuid=?"); | 699 SQLite::Statement s1(db_, SQLITE_FROM_HERE, "SELECT parentStudy, dicomSeries, expectedNumberOfInstances FROM Series WHERE uuid=?"); |
636 s1.BindString(0, seriesUuid); | 700 s1.BindString(0, seriesUuid); |
637 if (!s1.Step()) | 701 if (!s1.Step()) |
638 { | 702 { |
639 return false; | 703 return false; |
640 } | 704 } |
650 { | 714 { |
651 instances.append(s2.ColumnString(0)); | 715 instances.append(s2.ColumnString(0)); |
652 } | 716 } |
653 | 717 |
654 result["Instances"] = instances; | 718 result["Instances"] = instances; |
719 | |
720 if (s1.ColumnIsNull(2)) | |
721 { | |
722 result["ExpectedNumberOfInstances"] = -1; | |
723 } | |
724 else | |
725 { | |
726 result["ExpectedNumberOfInstances"] = s1.ColumnInt(2); | |
727 } | |
728 | |
729 SeriesStatus status = GetSeriesStatus(seriesUuid); | |
730 | |
731 switch (status) | |
732 { | |
733 case SeriesStatus_Complete: | |
734 result["Status"] = "Complete"; | |
735 break; | |
736 | |
737 case SeriesStatus_Missing: | |
738 result["Status"] = "Missing"; | |
739 break; | |
740 | |
741 case SeriesStatus_Inconsistent: | |
742 result["Status"] = "Inconsistent"; | |
743 break; | |
744 | |
745 default: | |
746 case SeriesStatus_Unknown: | |
747 result["Status"] = "Unknown"; | |
748 break; | |
749 } | |
655 | 750 |
656 return true; | 751 return true; |
657 } | 752 } |
658 | 753 |
659 | 754 |