send($this) ->through([ Pipes\ScanStudies::class, Pipes\FilterStudies::class, Pipes\InsertStudies::class, Pipes\UpdateStudies::class, Pipes\ArchiveStudies::class, ]) ->thenReturn(); } public function __construct(?OrthancRestClient $client = null) { $this->study_ids = collect(); $this->client = $client ?? new OrthancRestClient; $this->resetQueues(); } public function getClient(): OrthancRestClient { return $this->client; } public function getStudyIds(): Collection { return $this->study_ids; } public function setStudyIds(array $study_ids): void { $this->study_ids = collect($study_ids); } public function resetQueues() { $this->insert_queue = collect(); $this->update_queue = collect(); $this->archive_queue = collect(); } public function getInsertQueue(): Collection { return $this->insert_queue; } public function getUpdateQueue(): Collection { return $this->update_queue; } public function getArchiveQueue(): Collection { return $this->archive_queue; } public function fetchStudyDetails(string $orthanc_uuid): ?array { $study = $this->client->getStudyDetails($orthanc_uuid); if ($study == null) { return null; } $stats = $this->client->getStudyStatistics($orthanc_uuid); $study['Statistics'] = $stats; $series = $this->client->getStudySeries($orthanc_uuid); $study['Series'] = $series; return $study; } public function transformData(mixed $orthanc_src): array { $inst_name = data_get($orthanc_src, 'MainDicomTags.InstitutionName'); $inst_id = InstituteMapper::map($inst_name); $study = [ 'orthanc_uuid' => strtolower($orthanc_src['ID']), 'institution_name' => $inst_name, 'institute_id' => $inst_id, 'patient_uuid' => strtolower($orthanc_src['ParentPatient']), 'patient_id' => data_get($orthanc_src, 'PatientMainDicomTags.PatientID'), 'patient_name' => data_get($orthanc_src, 'PatientMainDicomTags.PatientName'), 'patient_sex' => data_get($orthanc_src, 'PatientMainDicomTags.PatientSex'), 'accession_number' => data_get($orthanc_src, 'MainDicomTags.AccessionNumber'), 'referring_physician_name' => data_get($orthanc_src, 'MainDicomTags.ReferringPhysicianName'), 'study_id' => data_get($orthanc_src, 'MainDicomTags.StudyID'), 'study_instance_uid' => data_get($orthanc_src, 'MainDicomTags.StudyInstanceUID'), 'modality' => data_get($orthanc_src, 'RequestedTags.Modality'), 'body_part_examined' => data_get($orthanc_src, 'RequestedTags.BodyPartExamined'), 'study_date' => DicomUtils::dateTimeToCarbon($orthanc_src['MainDicomTags']['StudyDate'], $orthanc_src['MainDicomTags']['StudyTime']) ?? Carbon::createFromTimestamp(0), 'received_at' => Carbon::parse($orthanc_src['LastUpdate'], 'UTC'), 'image_count' => data_get($orthanc_src, 'Statistics.CountInstances'), 'series_count' => data_get($orthanc_src, 'Statistics.CountSeries'), 'disk_size' => data_get($orthanc_src, 'Statistics.DiskSize'), ]; if ((bool) data_get($orthanc_src, 'IsStable', false)) { $study['study_status'] = StudyLevelStatus::StudyArrived->value; } else { $study['study_status'] = StudyLevelStatus::Pending->value; } $dob = data_get($orthanc_src, 'PatientMainDicomTags.PatientBirthDate'); if (filled($dob)) { try { $study['patient_birthdate'] = Carbon::parse($dob); } catch (\Exception) { Log::error('Failed to parse PatientMainDicomTags.PatientBirthDate: {dob}', ['dob' => $dob]); } } $descr = data_get($orthanc_src, 'MainDicomTags.StudyDescription'); if (blank($descr)) { $descr = data_get($orthanc_src, 'RequestedTags.AcquisitionDeviceProcessingDescription'); } if (blank($descr)) { $descr = data_get($orthanc_src, 'MainDicomTags.AcquisitionDeviceProcessingDescription'); } $this->setValue($study, 'study_description', trim($descr)); $properties = [ 'other_patient_names' => data_get($orthanc_src, 'RequestedTags.OtherPatientNames'), 'other_patient_ids' => data_get($orthanc_src, 'RequestedTags.OtherPatientIDs'), 'software_versions' => data_get($orthanc_src, 'RequestedTags.SoftwareVersions'), 'station_name' => data_get($orthanc_src, 'RequestedTags.StationName'), 'operators_name' => data_get($orthanc_src, 'RequestedTags.OperatorsName'), 'manufacturer' => data_get($orthanc_src, 'RequestedTags.Manufacturer'), 'manufacturer_model_name' => data_get($orthanc_src, 'RequestedTags.ManufacturerModelName'), 'acquisition_date' => DicomUtils::dateTimeToCarbon(data_get($orthanc_src, 'RequestedTags.AcquisitionDate'), data_get($orthanc_src, 'RequestedTags.AcquisitionTime')), ]; $properties = array_purge($properties); if (empty($properties)) { $properties = [ 'other_patient_names' => data_get($orthanc_src, 'MainDicomTags.OtherPatientNames'), 'other_patient_ids' => data_get($orthanc_src, 'MainDicomTags.OtherPatientIDs'), 'software_versions' => data_get($orthanc_src, 'MainDicomTags.SoftwareVersions'), 'station_name' => data_get($orthanc_src, 'MainDicomTags.StationName'), 'operators_name' => data_get($orthanc_src, 'MainDicomTags.OperatorsName'), 'manufacturer' => data_get($orthanc_src, 'MainDicomTags.Manufacturer'), 'manufacturer_model_name' => data_get($orthanc_src, 'MainDicomTags.ManufacturerModelName'), 'acquisition_date' => DicomUtils::dateTimeToCarbon(data_get($orthanc_src, 'MainDicomTags.AcquisitionDate'), data_get($orthanc_src, 'MainDicomTags.AcquisitionTime')), ]; $properties = array_purge($properties); } $series = []; foreach (data_get($orthanc_src, 'Series', []) as $ser) { $params = [ 'orthanc_uuid' => strtolower($ser['ID']), 'series_instance_uid' => data_get($ser, 'MainDicomTags.SeriesInstanceUID'), 'series_date' => DicomUtils::dateTimeToCarbon(data_get($ser, 'MainDicomTags.SeriesDate'), data_get($ser, 'MainDicomTags.SeriesTime')), 'series_number' => data_get($ser, 'MainDicomTags.SeriesNumber'), 'series_description' => data_get($ser, 'MainDicomTags.SeriesDescription'), 'protocol_name' => data_get($ser, 'MainDicomTags.ProtocolName'), 'modality' => data_get($ser, 'MainDicomTags.Modality'), 'body_part_examined' => data_get($ser, 'MainDicomTags.BodyPartExamined'), 'performed_procedure_step_description' => data_get($ser, 'MainDicomTags.PerformedProcedureStepDescription'), 'sequence_name' => data_get($ser, 'MainDicomTags.SequenceName'), ]; $params['num_instances'] = count(data_get($ser, 'Instances', [])); $params = array_purge($params); if (! empty($params)) { $series[] = $params; } } if (empty($series)) { $series = null; } else { // $series = array_multisort(array_column($series, 'series_number'), SORT_ASC, $series); usort($series, fn ($a, $b): int => (int) $a['series_number'] <=> (int) $b['series_number']); } if (empty($properties)) { $properties = null; } $details = compact('properties', 'series'); $details = array_purge($details); $study = array_purge($study); return compact('study', 'details'); } private function setValue(array &$array, string $key, mixed $value): void { if (filled($value)) { $array[$key] = $value; } } }