Skip to content

Commit

Permalink
Allow SeriesNumber to be Empty or invalid
Browse files Browse the repository at this point in the history
  • Loading branch information
jennydaman committed Aug 13, 2023
1 parent 05e5bc2 commit 65fa3e8
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 31 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "rx-repack"
description = "Rust re-write of px-repack"
version = "1.0.0"
version = "1.0.1"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
67 changes: 45 additions & 22 deletions src/dicom_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,43 @@ pub(crate) struct CommonElements<'a> {
pub PatientName: Option<&'a str>,
pub PatientBirthDate: Option<&'a str>,
pub StudyDescription: Option<&'a str>,
pub AccessionNumnber: Option<&'a str>,
pub AccessionNumber: Option<&'a str>,
pub StudyDate: Option<&'a str>,
pub SeriesNumber: i32, // SeriesNumber is of the "Integer String" (IS) type

pub SeriesNumber: Option<MaybeU32<'a>>,
pub SeriesDescription: Option<&'a str>,

// these are not part of the path name, but used in the log path names.
pub StudyInstanceUID: String,
pub SeriesInstanceUID: String,
}

/// Something that is maybe a [u32], but in case it's not valid, is a [str].
#[derive(Copy, Clone, Debug, PartialEq, serde::Serialize)]
#[serde(untagged)]
pub(crate) enum MaybeU32<'a> {
U32(u32),
Str(&'a str),
}

impl<'a> From<&'a str> for MaybeU32<'a> {
fn from(value: &'a str) -> Self {
value
.parse()
.map(Self::U32)
.unwrap_or_else(|_| MaybeU32::Str(value))
}
}

impl<'a> ToString for MaybeU32<'a> {
fn to_string(&self) -> String {
match self {
MaybeU32::U32(num) => num.to_string(),
MaybeU32::Str(s) => s.to_string(),
}
}
}

impl<'a> TagExtractor<'a> {
pub fn new(dcm: &'a DefaultDicomObject) -> Self {
Self {
Expand All @@ -79,25 +106,24 @@ impl<'a> TagExtractor<'a> {
.unwrap_or_else(|error| {
let e = DicomTagAndError { tag, error };
self.errors.borrow_mut().push(e);

NOT_DEFINED.into()
})
}

/// Get the value of a tag as an integer. In the case of a failure,
/// record the error in `self.errors` and return [i32::MIN].
/// That oughta throw a wrench in the system!
pub fn get_i32(&self, tag: Tag) -> i32 {
self.dcm
.element(tag)
.map_err(DicomTagError::from)
.and_then(|ele| ele.to_int::<i32>().map_err(DicomTagError::from))
.unwrap_or_else(|error| {
let e = DicomTagAndError { tag, error };
self.errors.borrow_mut().push(e);
i32::MIN
})
}
// /// Get the value of a tag as an integer. In the case of a failure,
// /// record the error in `self.errors` and return [i32::MIN].
// /// That oughta throw a wrench in the system!
// pub fn get_i32(&self, tag: Tag) -> i32 {
// self.dcm
// .element(tag)
// .map_err(DicomTagError::from)
// .and_then(|ele| ele.to_int::<i32>().map_err(DicomTagError::from))
// .unwrap_or_else(|error| {
// let e = DicomTagAndError { tag, error };
// self.errors.borrow_mut().push(e);
// i32::MIN
// })
// }
}

impl<'a> TryFrom<&'a DefaultDicomObject> for CommonElements<'a> {
Expand All @@ -113,12 +139,9 @@ impl<'a> TryFrom<&'a DefaultDicomObject> for CommonElements<'a> {
PatientName: tt(dcm, tags::PATIENT_NAME).ok(),
PatientBirthDate: tt(dcm, tags::PATIENT_BIRTH_DATE).ok(),
StudyDescription: tt(dcm, tags::STUDY_DESCRIPTION).ok(),
AccessionNumnber: tt(dcm, tags::ACCESSION_NUMBER).ok(),
AccessionNumber: tt(dcm, tags::ACCESSION_NUMBER).ok(),
StudyDate: tt(dcm, tags::STUDY_DATE).ok(),
SeriesNumber: dcm
.element(tags::SERIES_NUMBER)
.map_err(Self::Error::from)
.and_then(|ele| ele.value().to_int::<i32>().map_err(Self::Error::from))?,
SeriesNumber: tt(dcm, tags::SERIES_NUMBER).map(MaybeU32::from).ok(),
SeriesDescription: tt(dcm, tags::SERIES_DESCRIPTION).ok(),
StudyInstanceUID: tts(dcm, tags::STUDY_INSTANCE_UID)?,
SeriesInstanceUID: tts(dcm, tags::SERIES_INSTANCE_UID)?,
Expand Down
10 changes: 5 additions & 5 deletions src/log_models.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Models of what gets written to `/home/dicom/log`.
#![allow(non_snake_case)]
use crate::dicom_data::{CommonElements, TagExtractor, NOT_DEFINED};
use crate::dicom_data::{CommonElements, MaybeU32, TagExtractor, NOT_DEFINED};
use dicom::dictionary_std::tags;
use hashbrown::{HashMap, HashSet};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -59,7 +59,7 @@ pub(crate) struct SeriesDataMeta<'a> {
StudyInstanceUID: &'a str,
SeriesInstanceUID: &'a str,
SeriesDescription: &'a str,
SeriesNumber: i32,
SeriesNumber: MaybeU32<'a>,
SeriesDate: &'a str,
Modality: Cow<'a, str>,
}
Expand All @@ -71,7 +71,7 @@ impl<'a> SeriesDataMeta<'a> {
StudyInstanceUID: &e.StudyInstanceUID,
SeriesInstanceUID: &e.SeriesInstanceUID,
SeriesDescription: e.SeriesDescription.unwrap_or(NOT_DEFINED),
SeriesNumber: e.SeriesNumber,
SeriesNumber: e.SeriesNumber.unwrap_or(MaybeU32::Str(NOT_DEFINED)),
SeriesDate: e.StudyDate.unwrap_or(NOT_DEFINED),
Modality: d.get(tags::MODALITY),
}
Expand All @@ -84,7 +84,7 @@ pub(crate) struct InstanceData<'a> {
StudyInstanceUID: &'a str,
SeriesInstanceUID: &'a str,
SeriesDescription: Cow<'a, str>,
SeriesNumber: i32,
SeriesNumber: MaybeU32<'a>,
SeriesDate: Cow<'a, str>,
Modality: Cow<'a, str>,
outputFile: &'a str,
Expand All @@ -108,7 +108,7 @@ impl<'a> InstanceData<'a> {
StudyInstanceUID: &e.StudyInstanceUID,
SeriesInstanceUID: &e.SeriesInstanceUID,
SeriesDescription: d.get(tags::SERIES_DESCRIPTION),
SeriesNumber: d.get_i32(tags::SERIES_NUMBER),
SeriesNumber: e.SeriesNumber.unwrap_or(MaybeU32::Str(NOT_DEFINED)),
SeriesDate: d.get(tags::SERIES_DATE),
Modality: d.get(tags::MODALITY),
outputFile,
Expand Down
7 changes: 5 additions & 2 deletions src/pack_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,15 @@ impl PypxPath {
let study_dir = sanitize(format!(
"{}-{}-{}",
dcm.StudyDescription.unwrap_or("StudyDescription"),
dcm.AccessionNumnber.unwrap_or("AccessionNumber"),
dcm.AccessionNumber.unwrap_or("AccessionNumber"),
dcm.StudyDate.unwrap_or("StudyDate")
));
let series_dir = sanitize(format!(
"{:0>5}-{}-{}",
dcm.SeriesNumber,
dcm.SeriesNumber
.map(|s| s.to_string())
.as_deref()
.unwrap_or("SeriesNumber"),
dcm.SeriesDescription.unwrap_or("SeriesDescription"),
&hash(&dcm.SeriesInstanceUID)[..7]
));
Expand Down

0 comments on commit 65fa3e8

Please sign in to comment.