python基於影像Dicom標籤,計算患者年齡

本文由Markdown語法編輯器編輯完成。

1. 需求背景

產品要進行體系認證,而體系中對影像過濾進行了一些限制。其中一條規則是,需要篩選出所有影像中年齡大於等於16歲的影像。
要注意,這裏的年齡,是患者在當時拍攝影像時的年齡,而不是患者當前的年齡。
在dicom標籤中,有一個標籤是表明患者拍攝時的年齡的,(0x0010, 0x1010) PatientAge.
但是由於這個標籤不是一類標籤,不一定存在。因此,可以根據另外兩個標籤,來計算出患者當時拍攝時的年齡。這兩個標籤是:(0x0008, 0x0020) StudyDate, (0x0010, 0x0030) PatientBirthDate. 然後根據這兩個標籤,計算出年份的差異,也就知道了患者當時拍攝時的年齡。

明確了以上的方案,就可以寫代碼來實現了。

2. 需求實現

def check_age_restriction():
	patient_age_str = get_tag_values(ds, (0x0010, 0x1010), None)
          if patient_age_str:
              if patient_age_str.__contains__('D') or \
                      patient_age_str.__contains__('W') or \
                      patient_age_str.__contains__('M') or \
                      (patient_age_str.__contains__('Y') and
                       int(patient_age_str.split('Y')[0]) < 16):
                  return False
              return True
          patient_birthdate_str = get_tag_values(ds, (0x0010, 0x0030), None)
          study_date = get_tag_values(ds, (0x0008, 0x0020), None)
          series_date = get_tag_values(ds, (0x0008, 0x0021), None)
          acquisition_date = get_tag_values(ds, (0x0008, 0x0022), None)
          content_date = get_tag_values(ds, (0x0008, 0x0023), None)
          if not patient_birthdate_str:
              return True
          else:
              patient_birthdate = \
                  datetime.strptime(patient_birthdate_str, '%Y%m%d').date()
              actual_study_date = datetime.strptime(
                  study_date or series_date or acquisition_date or
                  content_date, '%Y%m%d').date()
              patient_age = cal_age_by_study_and_birth_date(
                  actual_study_date, patient_birthdate)
              if patient_age < DR_CE_AGE_LOWER_LIMIT:
                  return False
              return True

def get_tag_values(ds, tag, default=None):
    """
    獲取dataset
    :param ds: Dataset 待獲取對象dataset
    :param tag: tuple tag十六進制數
    :param default: object 缺省返回
    :return: object
    """
    if tag[0] == 0x0002:
        val = ds.file_meta.get(tag)
    else:
        val = ds.get(tag, default=default)
    if hasattr(val, 'value'):
        val = val.value
    return normalize_tag(val)


def normalize_tag(tag):
    """
    把tag的值轉化爲python的內置類型
    :param tag: Tag
    :return: object
    """
    type_map = [
        ('DSfloat', float),
        ('DSdecimal', float),
        ('IS', int),
        ('MultiString', lambda x: [normalize_tag(i) for i in x]),
        ('MultiValue', lambda x: [normalize_tag(i) for i in x]),
        ('PersonName3', str),
        ('PersonNameBase', str),
        ('PersonName', str),
        ('PersonNameUnicode', unicode),
    ]
    cls_name = tag.__class__.__name__
    val = dict(type_map).get(cls_name, lambda _: _)(tag)
    return val


def cal_age_by_study_and_birth_date(study_date, birth_date):
    if not study_date:
        raise Exception("StudyDate, SeriesDate, AcquisitionDate and "
                        "ContentDate do not exist!")
    if isinstance(study_date, date) and isinstance(birth_date, date):
        return study_date.year - birth_date.year - \
               ((study_date.month, study_date.day) <
                (birth_date.month, birth_date.day))
    raise Exception("StudyDate or BirthDate is not date type.")

以下是相應的測試case:
case1:

case2:

參考鏈接:

未完待續…

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章