wip
This commit is contained in:
parent
5c03963116
commit
6092d3540e
36
app/Models/DicomRoutingRule.php
Normal file
36
app/Models/DicomRoutingRule.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Domain\Rule\MatchCondition;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
|
||||||
|
class DicomRoutingRule extends BaseModel
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
public function conditions(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(DicomRuleCondition::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function institute(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Institute::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function facility(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Facility::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function casts(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'is_active' => 'boolean',
|
||||||
|
'match_condition' => MatchCondition::class,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
25
app/Models/DicomRuleCondition.php
Normal file
25
app/Models/DicomRuleCondition.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Domain\Rule\MatchMode;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
|
||||||
|
class DicomRuleCondition extends BaseModel
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
public function routingRule(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(DicomRoutingRule::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function casts(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'case_sensitive' => 'boolean',
|
||||||
|
'match_mode' => MatchMode::class,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
final class DicomStudyMapper
|
final class DicomStudyMapper
|
||||||
{
|
{
|
||||||
private static array $patterns = [];
|
private static array $rules = [];
|
||||||
|
|
||||||
private static int $catchAll = -1;
|
private static int $catchAll = -1;
|
||||||
|
|
||||||
@ -18,20 +18,24 @@ final class DicomStudyMapper
|
|||||||
*/
|
*/
|
||||||
public static function map(?string $input): array
|
public static function map(?string $input): array
|
||||||
{
|
{
|
||||||
if (empty(self::$patterns)) {
|
if (empty(self::$rules)) {
|
||||||
self::$patterns = Cache::remember('institute_names',
|
self::$rules = Cache::remember('institute_names',
|
||||||
now()->addMinutes(15),
|
now()->addMinutes(15),
|
||||||
fn () => DB::table('dicom_routing_rules')
|
fn () => DB::table('dicom_routing_rules')
|
||||||
->orderByDesc('priority')
|
->orderByDesc('priority')
|
||||||
->get()->toArray()
|
->get()
|
||||||
|
->toArray()
|
||||||
);
|
);
|
||||||
self::$catchAll = DB::table('institutes')->first('id')->id;
|
self::$catchAll = DB::table('institutes')
|
||||||
|
->where('name', 'Catch-all')
|
||||||
|
->first('id')
|
||||||
|
->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! blank($input)) {
|
if (! blank($input)) {
|
||||||
$input = strtolower($input);
|
$input = strtolower($input);
|
||||||
|
|
||||||
foreach (self::$patterns as $pattern) {
|
foreach (self::$rules as $pattern) {
|
||||||
if (StringMatcher::match($input, $pattern->name, MatchMode::from($pattern->match_mode))) {
|
if (StringMatcher::match($input, $pattern->name, MatchMode::from($pattern->match_mode))) {
|
||||||
return [$pattern->institute_id, $pattern->facility_id];
|
return [$pattern->institute_id, $pattern->facility_id];
|
||||||
}
|
}
|
63
app/Services/Pacs/DicomTagIdentifiers.php
Normal file
63
app/Services/Pacs/DicomTagIdentifiers.php
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services\Pacs;
|
||||||
|
|
||||||
|
enum DicomTagIdentifiers: string
|
||||||
|
{
|
||||||
|
case PatientName = '0010,0010'; // Patient's Name
|
||||||
|
case PatientID = '0010,0020'; // Patient ID
|
||||||
|
case PatientBirthDate = '0010,0030'; // Patient's Birth Date
|
||||||
|
case PatientSex = '0010,0040'; // Patient's Sex
|
||||||
|
case StudyInstanceUID = '0020,000D'; // Study Instance UID
|
||||||
|
case SeriesInstanceUID = '0020,000E'; // Series Instance UID
|
||||||
|
case StudyID = '0020,0010'; // Study ID
|
||||||
|
case SeriesNumber = '0020,0011'; // Series Number
|
||||||
|
case InstanceNumber = '0020,0013'; // Instance Number
|
||||||
|
case SOPClassUID = '0008,0016'; // SOP Class UID
|
||||||
|
case SOPInstanceUID = '0008,0018'; // SOP Instance UID
|
||||||
|
case StudyDate = '0008,0020'; // Study Date
|
||||||
|
case StudyTime = '0008,0030'; // Study Time
|
||||||
|
case AccessionNumber = '0008,0050'; // Accession Number
|
||||||
|
case Modality = '0008,0060'; // Modality
|
||||||
|
case Manufacturer = '0008,0070'; // Manufacturer
|
||||||
|
case InstitutionName = '0008,0080'; // Institution Name
|
||||||
|
case ReferringPhysicianName = '0008,0090'; // Referring Physician's Name
|
||||||
|
case StationName = '0008,1010'; // Station Name
|
||||||
|
case SeriesDescription = '0008,103E'; // Series Description
|
||||||
|
case ManufacturerModelName = '0008,1090'; // Manufacturer's Model Name
|
||||||
|
case PatientAge = '0010,1010'; // Patient's Age
|
||||||
|
case PatientWeight = '0010,1030'; // Patient's Weight
|
||||||
|
case BodyPartExamined = '0018,0015'; // Body Part Examined
|
||||||
|
case ProtocolName = '0018,1030'; // Protocol Name
|
||||||
|
case SoftwareVersions = '0018,1020'; // Software Versions
|
||||||
|
case AcquisitionDate = '0008,0022'; // Acquisition Date
|
||||||
|
case AcquisitionTime = '0008,0032'; // Acquisition Time
|
||||||
|
case ContentDate = '0008,0023'; // Content Date
|
||||||
|
case ContentTime = '0008,0033'; // Content Time
|
||||||
|
case AcquisitionDeviceProcessingDescription = '0018,1400'; // Acquisition Device Processing Description
|
||||||
|
case InstitutionAddress = '0008,0081'; // Institution Address
|
||||||
|
case StudyDescription = '0008,1030'; // Study Description
|
||||||
|
case OperatorsName = '0008,1070'; // Operator's Name
|
||||||
|
case Private10 = '0029,0010'; // Private Tag 10
|
||||||
|
case IW_Private = '0009,0010'; // IW Private Tag
|
||||||
|
case ImageType = '0008,0008'; // Image Type
|
||||||
|
case PatientOrientation = '0020,0020'; // Patient Orientation
|
||||||
|
case ImagePositionPatient = '0020,0032'; // Image Position (Patient)
|
||||||
|
case ImageOrientationPatient = '0020,0037'; // Image Orientation (Patient)
|
||||||
|
case FrameOfReferenceUID = '0020,0052'; // Frame of Reference UID
|
||||||
|
case PositionReferenceIndicator = '0020,1040'; // Position Reference Indicator
|
||||||
|
case SliceLocation = '0020,1041'; // Slice Location
|
||||||
|
case SamplesPerPixel = '0028,0002'; // Samples per Pixel
|
||||||
|
case PhotometricInterpretation = '0028,0004'; // Photometric Interpretation
|
||||||
|
case Rows = '0028,0010'; // Rows
|
||||||
|
case Columns = '0028,0011'; // Columns
|
||||||
|
case PixelSpacing = '0028,0030'; // Pixel Spacing
|
||||||
|
case BitsAllocated = '0028,0100'; // Bits Allocated
|
||||||
|
case BitsStored = '0028,0101'; // Bits Stored
|
||||||
|
case HighBit = '0028,0102'; // High Bit
|
||||||
|
case PixelRepresentation = '0028,0103'; // Pixel Representation
|
||||||
|
case WindowCenter = '0028,1050'; // Window Center
|
||||||
|
case WindowWidth = '0028,1051'; // Window Width
|
||||||
|
case RescaleIntercept = '0028,1052'; // Rescale Intercept
|
||||||
|
case RescaleSlope = '0028,1053'; // Rescale Slope
|
||||||
|
}
|
@ -24,4 +24,66 @@ public static function dateTimeToCarbon(?string $datePart, ?string $timePart, st
|
|||||||
|
|
||||||
return Carbon::createFromFormat('YmdHis', $datePart . Str::before($timePart, '.'), $timezone);
|
return Carbon::createFromFormat('YmdHis', $datePart . Str::before($timePart, '.'), $timezone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getDicomTagDescription(DicomTagIdentifiers $tag): string
|
||||||
|
{
|
||||||
|
return match ($tag) {
|
||||||
|
DicomTagIdentifiers::PatientName => "Patient's Name",
|
||||||
|
DicomTagIdentifiers::PatientID => 'Patient ID',
|
||||||
|
DicomTagIdentifiers::PatientBirthDate => "Patient's Birth Date",
|
||||||
|
DicomTagIdentifiers::PatientSex => "Patient's Sex",
|
||||||
|
DicomTagIdentifiers::StudyInstanceUID => 'Study Instance UID',
|
||||||
|
DicomTagIdentifiers::SeriesInstanceUID => 'Series Instance UID',
|
||||||
|
DicomTagIdentifiers::StudyID => 'Study ID',
|
||||||
|
DicomTagIdentifiers::SeriesNumber => 'Series Number',
|
||||||
|
DicomTagIdentifiers::InstanceNumber => 'Instance Number',
|
||||||
|
DicomTagIdentifiers::SOPClassUID => 'SOP Class UID',
|
||||||
|
DicomTagIdentifiers::SOPInstanceUID => 'SOP Instance UID',
|
||||||
|
DicomTagIdentifiers::StudyDate => 'Study Date',
|
||||||
|
DicomTagIdentifiers::StudyTime => 'Study Time',
|
||||||
|
DicomTagIdentifiers::AccessionNumber => 'Accession Number',
|
||||||
|
DicomTagIdentifiers::Modality => 'Modality',
|
||||||
|
DicomTagIdentifiers::Manufacturer => 'Manufacturer',
|
||||||
|
DicomTagIdentifiers::InstitutionName => 'Institution Name',
|
||||||
|
DicomTagIdentifiers::ReferringPhysicianName => "Referring Physician's Name",
|
||||||
|
DicomTagIdentifiers::StationName => 'Station Name',
|
||||||
|
DicomTagIdentifiers::SeriesDescription => 'Series Description',
|
||||||
|
DicomTagIdentifiers::ManufacturerModelName => "Manufacturer's Model Name",
|
||||||
|
DicomTagIdentifiers::PatientAge => "Patient's Age",
|
||||||
|
DicomTagIdentifiers::PatientWeight => "Patient's Weight",
|
||||||
|
DicomTagIdentifiers::BodyPartExamined => 'Body Part Examined',
|
||||||
|
DicomTagIdentifiers::ProtocolName => 'Protocol Name',
|
||||||
|
DicomTagIdentifiers::SoftwareVersions => 'Software Versions',
|
||||||
|
DicomTagIdentifiers::AcquisitionDate => 'Acquisition Date',
|
||||||
|
DicomTagIdentifiers::AcquisitionTime => 'Acquisition Time',
|
||||||
|
DicomTagIdentifiers::ContentDate => 'Content Date',
|
||||||
|
DicomTagIdentifiers::ContentTime => 'Content Time',
|
||||||
|
DicomTagIdentifiers::AcquisitionDeviceProcessingDescription => 'Acquisition Device Processing Description',
|
||||||
|
DicomTagIdentifiers::InstitutionAddress => 'Institution Address',
|
||||||
|
DicomTagIdentifiers::StudyDescription => 'Study Description',
|
||||||
|
DicomTagIdentifiers::OperatorsName => "Operator's Name",
|
||||||
|
DicomTagIdentifiers::Private10 => 'Private Tag 10',
|
||||||
|
DicomTagIdentifiers::IW_Private => 'IW Private Tag',
|
||||||
|
DicomTagIdentifiers::ImageType => 'Image Type',
|
||||||
|
DicomTagIdentifiers::PatientOrientation => 'Patient Orientation',
|
||||||
|
DicomTagIdentifiers::ImagePositionPatient => 'Image Position (Patient)',
|
||||||
|
DicomTagIdentifiers::ImageOrientationPatient => 'Image Orientation (Patient)',
|
||||||
|
DicomTagIdentifiers::FrameOfReferenceUID => 'Frame of Reference UID',
|
||||||
|
DicomTagIdentifiers::PositionReferenceIndicator => 'Position Reference Indicator',
|
||||||
|
DicomTagIdentifiers::SliceLocation => 'Slice Location',
|
||||||
|
DicomTagIdentifiers::SamplesPerPixel => 'Samples per Pixel',
|
||||||
|
DicomTagIdentifiers::PhotometricInterpretation => 'Photometric Interpretation',
|
||||||
|
DicomTagIdentifiers::Rows => 'Rows',
|
||||||
|
DicomTagIdentifiers::Columns => 'Columns',
|
||||||
|
DicomTagIdentifiers::PixelSpacing => 'Pixel Spacing',
|
||||||
|
DicomTagIdentifiers::BitsAllocated => 'Bits Allocated',
|
||||||
|
DicomTagIdentifiers::BitsStored => 'Bits Stored',
|
||||||
|
DicomTagIdentifiers::HighBit => 'High Bit',
|
||||||
|
DicomTagIdentifiers::PixelRepresentation => 'Pixel Representation',
|
||||||
|
DicomTagIdentifiers::WindowCenter => 'Window Center',
|
||||||
|
DicomTagIdentifiers::WindowWidth => 'Window Width',
|
||||||
|
DicomTagIdentifiers::RescaleIntercept => 'Rescale Intercept',
|
||||||
|
DicomTagIdentifiers::RescaleSlope => 'Rescale Slope',
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,6 @@ public static function match(string $input, string $pattern, MatchMode $mode): b
|
|||||||
MatchMode::StartsWith => str_starts_with($input, $pattern),
|
MatchMode::StartsWith => str_starts_with($input, $pattern),
|
||||||
MatchMode::EndsWith => str_ends_with($input, $pattern),
|
MatchMode::EndsWith => str_ends_with($input, $pattern),
|
||||||
MatchMode::Regex => preg_match($pattern, $input) === 1,
|
MatchMode::Regex => preg_match($pattern, $input) === 1,
|
||||||
default => false,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user