익명화된 데이터 주석 추가

이 페이지에서는 민감한 FHIRDICOM 데이터를 익명화할 때 주석 저장소 및 주석 레코드를 구성하는 방법을 설명합니다.

익명화된 데이터 주석 달기 개요

민감한 FHIR 또는 DICOM 데이터를 익명화할 때마다 주석 저장소에 삭제된 민감한 정보에 대한 정보를 출력할 수 있습니다. 이 정보는 주석 저장소 내에 하나 이상의 주석 레코드로 저장됩니다.

기존 데이터 세트에 주석 저장소를 만들거나 익명화 작업 중에 생성된 새 데이터 세트에 주석 저장소를 만들 수 있습니다. 기존 데이터 세트에 주석 저장소를 만드는 경우 같은 이름의 주석 저장소가 이미 해당 데이터 세트에 존재할 수 없습니다.

생성된 주석 저장소는 익명화된 소스 데이터와 동일한 프로젝트에 있어야 합니다. 예를 들어 한 프로젝트의 데이터를 동시에 익명화하고 다른 프로젝트의 주석 저장소로 주석 레코드를 출력할 수 없습니다.

익명화 중 주석 저장소와 그 동작을 지정하려면 DeidentifyConfig 객체의 annotation 객체 내에서 annotation_store_name 필드를 설정합니다.

사용 사례에 따라 store_quote 필드를 선택적으로 설정할 수 있습니다. store_quote 필드 설정에 대한 자세한 내용은 다음 섹션에서 확인할 수 있습니다.

store_quote 필드 사용

다음 정보는 FHIR 데이터와 DICOM 데이터 모두에 적용됩니다.

요청에서 annotation 내부의 store_quote 필드가 true로 설정되면 익명화된 데이터의 원래 값이 quote 필드의 주석 레코드에 표시됩니다. 예:

  • DATE가 익명화되고 store_quotetrue로 설정되면 주석 레코드에 다음 정보가 표시됩니다.

    • quote 필드에 표시되는 날짜의 값(예시: 1980-12-05)
    • DATE infoType.
    • 데이터가 발견된 시작 및 종료 위치. 시작 및 종료 위치는 0부터 시작하는 색인을 사용하며 모두 포함됩니다.
  • store_quotefalse로 설정하면 주석 레코드에 날짜(1980-12-05)가 표시되지 않으며 다음 정보만 표시됩니다.

    • DATE infoType.
    • 데이터가 발견된 시작 및 종료 위치. 시작 및 종료 위치는 0부터 시작하는 색인을 사용하며 모두 포함됩니다.

익명화된 FHIR 데이터의 주석

이 섹션에서는 Cloud Healthcare API를 사용하여 FHIR 데이터 익명화에 설명된 개념을 기반으로 합니다.

주석 레코드 구조

익명화 작업은 익명화된 각 FHIR 리소스에 대해 하나의 주석 레코드를 만듭니다. 각 주석 레코드에는 검사 및 변환된 익명화된 데이터에 대한 정보가 포함된 textAnnotation 객체가 포함됩니다. 익명화된 필드를 주석 레코드에 표시하려면 INSPECT_AND_TRANSFORM Action가 적용되어야 합니다.

익명화된 FHIR 데이터에 대한 주석 구성

다음 샘플은 기본 FHIR 데이터 익명화를 시작점으로 사용합니다. 이 샘플은 FHIR 기본 메서드를 사용하여 환자 리소스 익명화를 수행하고 익명화된 데이터에 대한 정보를 새 주석 저장소의 주석 레코드에 저장하는 방법을 보여줍니다. 샘플에서 store_quote 필드는 true로 설정됩니다. 즉, 출력 주석 레코드에는 익명화된 데이터의 원래 값이 포함됩니다.

새 주석 저장소는 익명화 작업을 통해 생성된 데이터 세트에 있지만 기존 데이터 세트에 주석 저장소를 만들 수도 있습니다.

curl

curl -X POST \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    -H "Content-Type: application/json; charset=utf-8" \
    --data "{
      'destinationDataset': 'projects/PROJECT_ID/locations/REGION/datasets/DESTINATION_DATASET_ID',
      'config': {
        'fhir': {},
        'annotation': {
          'annotation_store_name': 'projects/PROJECT_ID/locations/REGION/datasets/DESTINATION_DATASET_ID/annotationStores/ANNOTATION_STORE_ID',
          'store_quote': 'true'
        }
      }
    }" "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/REGION/datasets/SOURCE_DATASET_ID:deidentify"

요청이 성공하면 서버가 JSON 형식으로 응답을 반환합니다.

{
  "name": "projects/PROJECT_ID/locations/REGION/datasets/SOURCE_DATASET_ID/operations/OPERATION_ID"
}

응답에 작업 이름이 포함됩니다. 작업 get 메서드를 사용하여 작업 상태를 추적할 수 있습니다.

curl -X GET \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    -H "Content-Type: application/json; charset=utf-8" \
    "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/REGION/datasets/SOURCE_DATASET_ID/operations/OPERATION_ID"

요청이 성공하면 서버가 JSON 형식으로 응답을 반환합니다. 익명화 프로세스가 완료되면 응답에 "done": true가 포함됩니다.

{
  "name": "projects/PROJECT_ID/locations/REGION/datasets/SOURCE_DATASET_ID/operations/OPERATION_ID",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.healthcare.v1beta1.OperationMetadata",
    "apiMethodName": "google.cloud.healthcare.v1beta1.dataset.DatasetService.DeidentifyDataset",
    "createTime": "CREATE_TIME",
    "endTime": "END_TIME"
  },
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.cloud.healthcare.v1beta1.deidentify.DeidentifySummary",
    "successStoreCount": "1",
    "successResourceCount": "1"
  }
}

익명화가 완료되었는지 확인한 후 데이터 세트에 주석 저장소를 나열하고 작업에서 주석 저장소를 만들었는지 확인할 수 있습니다.

curl -X GET \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/REGION/datasets/DESTINATION_DATASET_ID/annotationStores"

요청이 성공하면 서버가 JSON 형식으로 응답을 반환합니다.

{
  "annotationStores": [
    {
      "name": "projects/PROJECT_ID/locations/REGION/datasets/DESTINATION_DATASET_ID/annotationStores/ANNOTATION_STORE_ID"
    },
    {
      ...
    }
  ]
}

ANNOTATION_STORE_ID 값을 사용하여 주석 저장소의 주석 레코드를 나열합니다.

curl -X GET \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/REGION/datasets/DESTINATION_DATASET_ID/annotationStores/ANNOTATION_STORE_ID/annotations"

요청이 성공하면 서버가 JSON 형식으로 응답을 반환합니다.

{
  "annotations": [
    "projects/PROJECT_ID/locations/REGION/datasets/DESTINATION_DATASET_ID/annotationStores/ANNOTATION_STORE_ID/annotations/ANNOTATION_RECORD_ID",
    ...
  ]
}

ANNOTATION_RECORD_ID 값을 사용하여 주석 레코드를 확인합니다.

curl -X GET \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/REGION/datasets/DESTINATION_DATASET_ID/annotationStores/ANNOTATION_STORE_ID/annotations/ANNOTATION_RECORD_ID"

요청이 성공하면 서버가 JSON 형식으로 응답을 반환합니다.

textAnnotation 객체에는 익명화 작업이 삭제한 민감한 텍스트에 대한 정보가 포함됩니다. details 필드에서는 작업이 patient.text.div 객체를 검색하고, 값 및 값이 발견된 위치와 함께 4개의 infoType을 찾은 것을 볼 수 있습니다.

기본 FHIR 익명화를 사용하여 검사 및 변환된 유일한 데이터는 patient.text.div 객체의 데이터였습니다. 다른 모든 익명화 데이터는 infoType이 이미 원래 FHIR 리소스에 선언되었기 때문에 검사되지 않고 변환되었습니다.

{
  "name": "projects/PROJECT_ID/locations/REGION/datasets/DESTINATION_DATASET_ID/annotationStores/ANNOTATION_STORE_ID/annotations/ANNOTATION_RECORD_ID",
  "annotationSource": {
    "cloudHealthcareSource": {
      "name": "projects/PROJECT_ID/locations/REGION/datasets/SOURCE_DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Patient/PATIENT_ID"
    }
  },
  "textAnnotation": {
    "details": {
      "patient.text.div": {
        "findings": [
          {
            "infoType": "PERSON_NAME",
            "start": "42",
            "end": "54",
            "quote": "Smith, Darcy"
          },
          {
            "infoType": "PERSON_NAME",
            "start": "42",
            "end": "47",
            "quote": "Smith"
          },
          {
            "infoType": "PERSON_NAME",
            "start": "49",
            "end": "54",
            "quote": "Darcy"
          },
          {
            "infoType": "DATE",
            "start": "81",
            "end": "91",
            "quote": "1980-12-05"
          }
        ]
      }
    }
  }
}

익명화된 DICOM 데이터의 주석

이 섹션에서는 Cloud Healthcare API를 사용하여 DICOM 데이터 익명화에 설명된 개념을 기반으로 합니다.

주석 레코드 구조

익명화 작업은 익명화된 DICOM 데이터에 대해 두 가지 유형의 주석 레코드를 만듭니다. 주석 레코드의 두 가지 유형은 다음과 같습니다.

  • 텍스트 주석 레코드: 익명화된 데이터의 메타데이터(예시: DICOM 태그)를 포함합니다. 각 텍스트 주석 레코드에는 검사 및 변환된 익명화된 데이터에 대한 정보가 포함된 textAnnotation 객체가 포함됩니다. 익명화된 태그가 주석 레코드에 표시되려면 TagFilterProfile 필드에 제공된 구성에 따라 보호 건강 정보(PHI)를 검사해야 합니다. 예를 들어 익명화된 DICOM 데이터에 대한 주석 구성의 샘플은 DEIDENTIFY_TAG_CONTENTS 구성을 사용합니다.
  • 이미지 주석 레코드: 개별 DICOM 프레임에 민감한 정보의 위치를 포함합니다. 각 이미지 주석 레코드에는 발견된 민감한 정보의 좌표를 포함하는 ImageAnnotation 객체가 포함됩니다.

익명화 작업은 DICOM 인스턴스의 각 프레임에 대한 주석 레코드를 만듭니다. 예를 들어 DICOM 인스턴스에 프레임이 3개 있는 경우 익명화 작업은 다음 주석 레코드를 만듭니다.

  • DICOM 인스턴스의 DICOM 태그에 대한 textAnnotation가 포함된 하나의 텍스트 주석 레코드입니다.
  • 3개의 프레임 각각에 대해 imageAnnotation가 포함된 3개의 이미지 주석 레코드입니다. 각 이미지 주석 레코드에는 레코드가 해당하는 프레임을 나타내는 frame_index 필드가 포함되어 있습니다.

이러한 주석 레코드 4개는 모두 동일한 cloudHealthcareSource.name 값(projects/PROJECT_ID/locations/REGION/datasets/SOURCE_DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_UID/series/SERIES_UID/instances/INSTANCE_UID 형식의 DICOM 인스턴스 경로)을 갖습니다.

익명화된 DICOM 데이터에 대한 주석 구성

다음 샘플은 태그 익명화 및 번인 텍스트 수정 결합을 시작점으로 사용합니다. 샘플은 DICOM 인스턴스를 익명화하여 이미지의 모든 번인 텍스트를 수정하고 민감한 텍스트를 검사하고 변환하는 방법을 보여줍니다. 또한 샘플은 익명화된 데이터에 대한 정보를 새 주석 저장소의 주석 레코드에 저장하는 방법도 보여줍니다. 샘플에서 store_quote 필드는 true로 설정됩니다. 즉, 출력 주석 레코드에는 익명화된 데이터의 원래 값이 포함됩니다.

새 주석 저장소는 익명화 작업을 통해 생성된 데이터 세트에 있지만 기존 데이터 세트에 주석 저장소를 만들 수도 있습니다.

curl

curl -X POST \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    -H "Content-Type: application/json; charset=utf-8" \
    --data "{
      'destinationDataset': 'projects/PROJECT_ID/locations/REGION/datasets/DESTINATION_DATASET_ID',
      'config': {
        'dicom': {
          'filterProfile': 'DEIDENTIFY_TAG_CONTENTS'
        },
        'image': {
          'textRedactionMode': 'REDACT_ALL_TEXT'
        },
        'annotation': {
          'annotation_store_name': 'projects/PROJECT_ID/locations/REGION/datasets/DESTINATION_DATASET_ID/annotationStores/ANNOTATION_STORE_ID',
          'store_quote': 'true'
        }
      }
    }" "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/REGION/datasets/SOURCE_DATASET_ID:deidentify"

요청이 성공하면 서버가 JSON 형식으로 응답을 반환합니다.

{
  "name": "projects/PROJECT_ID/locations/REGION/datasets/SOURCE_DATASET_ID/operations/OPERATION_ID"
}

응답에 작업 이름이 포함됩니다. 작업 get 메서드를 사용하여 작업 상태를 추적할 수 있습니다.

curl -X GET \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    -H "Content-Type: application/json; charset=utf-8" \
    "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/REGION/datasets/SOURCE_DATASET_ID/operations/OPERATION_ID"

요청이 성공하면 서버가 JSON 형식으로 응답을 반환합니다. 익명화 프로세스가 완료되면 응답에 "done": true가 포함됩니다.

{
  "name": "projects/PROJECT_ID/locations/REGION/datasets/SOURCE_DATASET_ID/operations/OPERATION_ID",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.healthcare.v1beta1.OperationMetadata",
    "apiMethodName": "google.cloud.healthcare.v1beta1.dataset.DatasetService.DeidentifyDataset",
    "createTime": "CREATE_TIME",
    "endTime": "END_TIME"
  },
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.cloud.healthcare.v1beta1.deidentify.DeidentifySummary",
    "successStoreCount": "1",
    "successResourceCount": "1"
  }
}

익명화가 완료되었는지 확인한 후 데이터 세트에 주석 저장소를 나열하고 작업에서 새 주석 저장소를 만들었는지 확인할 수 있습니다.

curl -X GET \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/REGION/datasets/DESTINATION_DATASET_ID/annotationStores"

요청이 성공하면 서버가 JSON 형식으로 응답을 반환합니다.

{
  "annotationStores": [
    {
      "name": "projects/PROJECT_ID/locations/REGION/datasets/DESTINATION_DATASET_ID/annotationStores/ANNOTATION_STORE_ID"
    },
    {
      ...
    }
  ]
}

ANNOTATION_STORE_ID 값을 사용하여 주석 저장소의 주석 레코드를 나열합니다.

curl -X GET \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/REGION/datasets/DESTINATION_DATASET_ID/annotationStores/ANNOTATION_STORE_ID/annotations"

요청이 성공하면 서버가 JSON 형식으로 응답을 반환합니다.

{
  "annotations": [
    "projects/PROJECT_ID/locations/REGION/datasets/DESTINATION_DATASET_ID/annotationStores/ANNOTATION_STORE_ID/annotations/TEXT_ANNOTATION_RECORD_ID",
    "projects/PROJECT_ID/locations/REGION/datasets/DESTINATION_DATASET_ID/annotationStores/ANNOTATION_STORE_ID/annotations/IMAGE_ANNOTATION_RECORD_ID",
    ...
  ]
}

두 개의 주석 레코드(텍스트 주석 레코드와 이미지 주석 레코드)가 생성된 것을 볼 수 있습니다.

먼저 TEXT_ANNOTATION_RECORD_ID 값을 사용하여 텍스트 주석 레코드를 확인합니다.

curl -X GET \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/REGION/datasets/DATASET_ID/annotationStores/ANNOTATION_STORE_ID/annotations/TEXT_ANNOTATION_RECORD_ID"

요청이 성공하면 서버가 JSON 형식으로 응답을 반환합니다.

textAnnotation 객체에는 익명화 작업이 삭제한 민감한 텍스트에 대한 정보가 포함되어 있습니다. details 필드에서 작업이 DICOM 태그 목록을 제공했음을 확인할 수 있습니다. DICOM 태그가 발견되면 infoType, infoType의 값, 값이 발견된 위치를 표시하는 findings 객체에 정보가 제공된 것입니다.

{
  "name": "projects/PROJECT_ID/locations/REGION/datasets/DESTINATION_DATASET_ID/annotationStores/ANNOTATION_STORE_ID/annotations/TEXT_ANNOTATION_RECORD_ID",
  "annotationSource": {
    "cloudHealthcareSource": {
      "name": "projects/PROJECT_ID/locations/REGION/datasets/SOURCE_DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_UID/series/SERIES_UID/instances/INSTANCE_UID"
    }
  },
  "textAnnotation": {
    "details": {
      "00080070": {},
      "00080090": {
        "findings": [
          {
            "infoType": "PERSON_NAME",
            "end": "8",
            "quote": "John Doe"
          }
        ]
      },
      "00081090": {},
      "00100010": {
        "findings": [
          {
            "infoType": "PERSON_NAME",
            "end": "11",
            "quote": "Ann Johnson"
          }
        ]
      },
      "00100020": {},
      "00100030": {
        "findings": [
          {
            "infoType": "DATE",
            "end": "8",
            "quote": "19880812"
          }
        ]
      },
      "00020013": {
        "findings": [
          {
            "infoType": "LOCATION",
            "end": "5",
            "quote": "OFFIS"
          }
        ]
      },
      "00080020": {
        "findings": [
          {
            "infoType": "DATE",
            "end": "8",
            "quote": "20110909"
          }
        ]
      }
    }
  }
}

그런 다음 IMAGE_ANNOTATION_RECORD_ID 값을 사용하여 이미지 주석 레코드를 확인합니다.

curl -X GET \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/REGION/datasets/DATASET_ID/annotationStores/ANNOTATION_STORE_ID//annotations/IMAGE_ANNOTATION_RECORD_ID"

요청이 성공하면 서버가 JSON 형식으로 응답을 반환합니다.

imageAnnotation 객체 내에는 여러 vertices가 있으며 각각 익명화 작업이 민감한 이미지 데이터와 번인 텍스트를 감지한 위치를 묶은 4개의 X/Y 포인트가 포함되어 있습니다.

{
  "name": "projects/PROJECT_ID/locations/REGION/datasets/DESTINATION_DATASET_ID/annotationStores/ANNOTATION_STORE_ID/annotations/IMAGE_ANNOTATION_RECORD_ID",
  "annotationSource": {
    "cloudHealthcareSource": {
      "name": "projects/PROJECT_ID/locations/REGION/datasets/SOURCE_DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_UID/series/SERIES_UID/instances/INSTANCE_UID"
    }
  },
  "imageAnnotation": {
    "boundingPolys": [
      {
        "vertices": [
          {
            "x": 439,
            "y": 919
          },
          {
            "x": 495,
            "y": 919
          },
          {
            "x": 495,
            "y": 970
          },
          {
            "x": 439,
            "y": 970
          }
        ]
      },
      {
        "vertices": [
          {
            "x": 493,
            "y": 919
          },
          {
            "x": 610,
            "y": 919
          },
          {
            "x": 610,
            "y": 972
          },
          {
            "x": 493,
            "y": 972
          }
        ]
      },
      {
        "vertices": [
        ...
        ]
      },
      ...
    ]
  }
}