removed old
This commit is contained in:
parent
17af167505
commit
cdd776b7ec
@ -3,16 +3,13 @@
|
|||||||
namespace App\Http\Controllers\System;
|
namespace App\Http\Controllers\System;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Services\Pacs\StudyImporter;
|
use App\Services\Pacs\Sync\StudiesSync;
|
||||||
|
|
||||||
class SyncOrthancController extends Controller
|
class SyncOrthancController extends Controller
|
||||||
{
|
{
|
||||||
public function __invoke()
|
public function __invoke()
|
||||||
{
|
{
|
||||||
$svc = (new StudyImporter);
|
(new StudiesSync)->execute();
|
||||||
$svc->scanStudies();
|
|
||||||
$svc->filterStudies();
|
|
||||||
$svc->importStudies();
|
|
||||||
|
|
||||||
return redirect()->route('studies.index');
|
return redirect()->route('studies.index');
|
||||||
}
|
}
|
||||||
|
@ -1,237 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Services\Pacs;
|
|
||||||
|
|
||||||
use App\Models\Enums\StudyLevelStatus;
|
|
||||||
use App\Models\Study;
|
|
||||||
use App\Models\StudyDetails;
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
|
|
||||||
final class StudyImporter
|
|
||||||
{
|
|
||||||
private array $study_ids = [];
|
|
||||||
|
|
||||||
private array $insert_queue = [];
|
|
||||||
|
|
||||||
private array $update_queue = [];
|
|
||||||
|
|
||||||
private OrthancRestClient $client;
|
|
||||||
|
|
||||||
public function __construct(?OrthancRestClient $client = null)
|
|
||||||
{
|
|
||||||
$this->client = $client ?? new OrthancRestClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function scanStudies()
|
|
||||||
{
|
|
||||||
$this->study_ids = $this->client->getStudiesIds();
|
|
||||||
}
|
|
||||||
|
|
||||||
private function checkUpdate(string $orthanc_uuid): void
|
|
||||||
{
|
|
||||||
$row = DB::table('studies')->where('orthanc_uuid', $orthanc_uuid)->first(['id', 'study_status']);
|
|
||||||
|
|
||||||
if ($row === null) {
|
|
||||||
$this->insert_queue[] = $orthanc_uuid;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($row->study_status < StudyLevelStatus::StudyArrived->value) {
|
|
||||||
$this->update_queue[$orthanc_uuid] = $row->id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function filterStudies()
|
|
||||||
{
|
|
||||||
$this->insert_queue = [];
|
|
||||||
$this->update_queue = [];
|
|
||||||
foreach ($this->study_ids as $study_id) {
|
|
||||||
$this->checkUpdate($study_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function fetchStudyDetails(string $orthanc_uid): ?array
|
|
||||||
{
|
|
||||||
$study = $this->client->getStudyDetails($orthanc_uid);
|
|
||||||
if ($study == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$stats = $this->client->getStudyStatistics($orthanc_uid);
|
|
||||||
$study['Statistics'] = $stats;
|
|
||||||
|
|
||||||
$series = $this->client->getStudySeries($orthanc_uid);
|
|
||||||
$study['Series'] = $series;
|
|
||||||
|
|
||||||
return $study;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function importStudies()
|
|
||||||
{
|
|
||||||
foreach ($this->update_queue as $orthanc_uuid => $row_id) {
|
|
||||||
$study = $this->fetchStudyDetails($orthanc_uuid);
|
|
||||||
if ($study == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$this->updateStudy($row_id, $study);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($this->insert_queue as $orthanc_uuid) {
|
|
||||||
$study = $this->fetchStudyDetails($orthanc_uuid);
|
|
||||||
if ($study == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$this->insertStudy($study);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function prepareData(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']),
|
|
||||||
'is_locked' => false,
|
|
||||||
'is_active' => true,
|
|
||||||
|
|
||||||
'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'),
|
|
||||||
'study_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']),
|
|
||||||
'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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function updateStudy(int $row_id, mixed $study): void
|
|
||||||
{
|
|
||||||
$payload = $this->prepareData($study);
|
|
||||||
unset($payload['study']['orthanc_uuid']);
|
|
||||||
$payload['study']['updated_at'] = now();
|
|
||||||
DB::table('studies')->where('id', $row_id)->update($payload['study']);
|
|
||||||
|
|
||||||
if (! empty($payload['details'])) {
|
|
||||||
$payload['details']['updated_at'] = now();
|
|
||||||
DB::table('study_details')->where('study_id', $row_id)->update($payload['details']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function insertStudy(mixed $study): void
|
|
||||||
{
|
|
||||||
$payload = $this->prepareData($study);
|
|
||||||
$row = Study::create($payload['study']);
|
|
||||||
$payload['details']['study_id'] = $row->id;
|
|
||||||
StudyDetails::create($payload['details']);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user