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