匿名化データにアノテーションを付ける

このページでは、機密の FHIR データと DICOM データを匿名化する際に、アノテーション ストアとアノテーション レコードを構成する方法について説明します。

匿名化データのアノテーションの概要

FHIR または DICOM の機密データを匿名化するたびに、削除された機密データに関する情報をアノテーション ストアに出力できます。この情報は、アノテーション ストア内に 1 つ以上のアノテーション レコードとして保存されます。

アノテーション ストアは、既存のデータセットに作成することも、匿名化オペレーションで作成した新しいデータセットに作成することもできます。既存のデータセットにアノテーション ストアを作成すると、そのデータセットには、同じ名前のアノテーション ストアは存在できません。

作成されたアノテーション ストアは、匿名化されたソースデータと同じプロジェクトに存在する必要があります。たとえば、あるプロジェクト内のデータを匿名化するのと同時に、アノテーション レコードを別のプロジェクトのアノテーション ストアに出力することはできません。

匿名化中のアノテーション ストアとその動作を指定するには、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
    • データが検出された場所の開始位置と終了位置。開始位置と終了位置では、ゼロベースのインデックスを使用し、両方とも範囲に含まれます。
  • store_quotefalse に設定されている場合、日付(1980-12-05)はアノテーション レコードに表示されず、次の情報のみが表示されます。

    • DATE infoType
    • データが検出された場所の開始位置と終了位置。開始位置と終了位置では、ゼロベースのインデックスを使用し、両方とも範囲に含まれます。

匿名化された FHIR データのアノテーション

このセクションは、Cloud Healthcare API を使用した FHIR データの匿名化で説明したコンセプトに基づいています。

アノテーション レコードの構造

匿名化オペレーションでは、匿名化された FHIR リソースごとに 1 つのアノテーション レコードが作成されます。各アノテーション レコードには、検査され、変換された匿名化データに関する情報を保持する textAnnotation オブジェクトが含まれています。匿名化されたフィールドをアノテーション レコードに表示するには、INSPECT_AND_TRANSFORM Action がデータに適用されている必要があります。

匿名化された FHIR データのアノテーションの構成

次のサンプルでは、デフォルトの FHIR データ匿名化を開始点として使用しています。サンプルは、FHIR のデフォルトのメソッドを使用して Patient リソースを匿名化し、匿名化されたデータに関する情報を新しいアノテーション ストア内のアノテーション レコードに保存する方法を示しています。サンプルでは、store_quote フィールドは true に設定されています。つまり、出力アノテーション レコードには、匿名化されたデータの元の値が含まれています。

新しいアノテーション ストアは、匿名化オペレーションによって作成されたデータセットにありますが、既存のデータセットにアノテーション ストアを作成することもできます。

curl

curl -X POST \
    -H "Authorization: Bearer $(gcloud auth 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"
}

レスポンスにはオペレーション名が含まれています。Operation get メソッドを使用して、このオペレーションのステータスを追跡できます。

curl -X GET \
    -H "Authorization: Bearer $(gcloud auth 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 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 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 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 データ用に 2 種類のアノテーション レコードが作成されます。アノテーション レコードには次の 2 種類があります。

  • テキスト アノテーション レコード: 匿名化されたデータのメタデータ(DICOM タグなど)が含まれます。各テキスト アノテーション レコードには、検査され、変換された匿名化データに関する情報を保持する textAnnotation オブジェクトが含まれています。匿名化されたタグをアノテーション レコードに表示するには、TagFilterProfile フィールドで指定された構成に基づいて、保護対象保健情報(PHI)のために検査される必要があります。たとえば、匿名化された DICOM データのアノテーションの構成のサンプルでは、DEIDENTIFY_TAG_CONTENTS 構成を使用しています。
  • 画像アノテーション レコード: 個々の DICOM フレーム内の機密情報の場所が含まれます。各画像アノテーション レコードには、検出された機密情報の座標を保持する ImageAnnotation オブジェクトが含まれています。

匿名化オペレーションは、DICOM インスタンス内の各フレームのアノテーション レコードを作成します。たとえば、DICOM インスタンスに 3 つのフレームがある場合、匿名化オペレーションでは次のアノテーション レコードが作成されます。

  • DICOM インスタンス内の DICOM タグ用の textAnnotation を含む 1 つのテキスト アノテーション レコード。
  • 3 つのフレームのそれぞれに imageAnnotation を含む 3 つの画像アノテーション レコード。各画像アノテーション レコードには、レコードが対応するフレームを示す frame_index フィールドが含まれています。

これらの 4 つのアノテーション レコードにはすべて、同じ cloudHealthcareSource.name 値があります。これは、次の形式の DICOM インスタンス パスです。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 インスタンスを匿名化して画像内のすべての焼き付きテキストの秘匿化する方法と、機密テキストを検査して変換する方法を示しています。また、匿名化されたデータに関する情報を新しいアノテーション ストアのアノテーション レコードに保存する方法も示しています。サンプルでは、store_quote フィールドは true に設定されています。つまり、出力アノテーション レコードには、匿名化されたデータの元の値が含まれています。

新しいアノテーション ストアは、匿名化オペレーションによって作成されたデータセットにありますが、既存のデータセットにアノテーション ストアを作成することもできます。

curl

curl -X POST \
    -H "Authorization: Bearer $(gcloud auth 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 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 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 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",
    ...
  ]
}

テキスト アノテーション レコードと画像アノテーション レコードの 2 つのアノテーション レコードが作成されたことを確認できます。

まず、TEXT_ANNOTATION_RECORD_ID 値を使用してテキスト アノテーション レコードを表示します。

curl -X GET \
    -H "Authorization: Bearer $(gcloud auth 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 タグが見つかった場合、その情報は findings オブジェクトで提供され、infoType、infoType の値、値が見つかった場所を示しています。

{
  "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 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": [
        ...
        ]
      },
      ...
    ]
  }
}