Como anotar dados desidentificados

Esta página explica como configurar armazenamentos de anotações e registros de anotações ao desidentificar dados confidenciais de FHIR e DICOM.

Visão geral de como anotar dados desidentificados

Sempre que você desidentifica dados confidenciais de FHIR ou DICOM, é possível gerar informações sobre os dados confidenciais removidos em um armazenamento de anotações. Essas informações são armazenadas como um ou mais registros de anotação no armazenamento de anotações.

É possível criar o armazenamento de anotações em um conjunto de dados existente ou no novo conjunto de dados criado durante a operação de desidentificação. Se você criar o armazenamento de anotações em um conjunto de dados existente, um armazenamento de anotações com o mesmo nome não poderá existir nesse conjunto de dados.

O armazenamento de anotações criado precisa estar no mesmo projeto que os dados de origem desidentificados. Por exemplo, não é possível desidentificar dados em um projeto e, ao mesmo tempo, gerar registros de anotação para um armazenamento de anotações em um projeto diferente.

Para especificar um armazenamento de anotações e o comportamento dele durante a desidentificação, defina o campo annotation_store_name em um objeto annotation no objeto DeidentifyConfig.

Como opção, defina o campo store_quote, dependendo do seu caso de uso. As informações sobre como definir o campo store_quote estão disponíveis na próxima seção.

Como usar o campo store_quote

As informações a seguir aplicam-se aos dados de FHIR e DICOM.

Quando o campo store_quote em annotation na solicitação é definido como true, os valores originais dos dados desidentificados são exibidos no registro de anotação no campo quote. Exemplo:

  • Se uma DATE for desidentificada e se store_quote for definida como true, as seguintes informações serão exibidas no registro de anotação:

    • O valor da data (como 1980-12-05), exibido no campo quote
    • O infoType de DATE
    • Os locais de início e término em que os dados foram encontrados. Os locais de início e término usam um índice baseado em zero e são inclusivos.
  • Se store_quote for definida como false, a data (1980-12-05) não será exibida no registro de anotação, e apenas as informações a seguir serão exibidas:

    • O infoType de DATE
    • Os locais de início e término em que os dados foram encontrados. Os locais de início e término usam um índice baseado em zero e são inclusivos.

Anotações para dados de FHIR desidentificados

Nesta seção, você verá os conceitos explicados em Como desidentificar os dados de FHIR com a API Cloud Healthcare.

Estrutura do registro de anotações

A operação de desidentificação cria um registro de anotação para cada recurso de FHIR desidentificado. Cada registro de anotação contém um objeto textAnnotation que contém informações sobre os dados desidentificados que foram inspecionados e transformados. Para que um campo desidentificado apareça no registro de anotação, ele precisa ter o INSPECT_AND_TRANSFORM Action aplicado a ele.

Como configurar anotações para dados do FHIR desidentificados

As amostras a seguir usam a desidentificação de dados de FHIR padrão como ponto de partida. As amostras exibem como desidentificar um recurso do paciente usando o método FHIR padrão e armazenar informações sobre os dados desidentificados em um registro de anotação em um novo armazenamento de anotações. Nas amostras, o campo store_quote é definido como true, o que significa que o registro da anotação de saída contém os valores originais dos dados que foram desidentificados.

O novo armazenamento de anotações está no conjunto de dados criado pela operação de desidentificação, mas também é possível criar o armazenamento de anotações em um conjunto de dados existente.

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"

Se a solicitação for bem-sucedida, o servidor retornará a resposta no formato JSON:

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

A resposta contém um nome de operação. Use o método Operation get para rastrear o status da operação:

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"

Se a solicitação for bem-sucedida, o servidor retornará a resposta no formato JSON. Depois que o processo de desidentificação for concluído, a resposta conterá "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"
  }
}

Depois de verificar se a desidentificação foi bem-sucedida, liste os armazenamentos de anotações no conjunto de dados e veja se a operação criou o armazenamento de anotações:

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"

Se a solicitação for bem-sucedida, o servidor retornará a resposta no formato JSON:

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

Use o valor ANNOTATION_STORE_ID para listar os registros de anotação no armazenamento de anotações:

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"

Se a solicitação for bem-sucedida, o servidor retornará a resposta no formato JSON:

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

Use o valor ANNOTATION_RECORD_ID para ver o registro de anotação:

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"

Se a solicitação for bem-sucedida, o servidor retornará a resposta no formato JSON.

O objeto textAnnotation contém informações sobre o texto confidencial removido pela operação de desidentificação. No campo details, é possível ver que a operação pesquisou o objeto patient.text.div e encontrou quatro infoTypes com os respectivos valores e os locais onde os valores foram encontrados.

Usando a desidentificação de FHIR padrão, os únicos dados que foram inspecionados e transformados foram os dados no objeto patient.text.div. todos os outros dados desidentificados foram transformados sem serem inspecionados porque o infoType já foi declarado no recurso FHIR original.

{
  "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"
          }
        ]
      }
    }
  }
}

Anotações para dados de DICOM desidentificados

Esta seção se baseia nos conceitos explicados em Como desidentificar dados do DICOM usando a API Cloud Healthcare.

Estrutura do registro de anotações

A operação de desidentificação cria dois tipos de registros de anotações para dados do DICOM desidentificados. Os dois tipos de registros de anotação são:

  • Registros de anotações de texto: contêm metadados, como tags DICOM, dos dados desidentificados. Cada registro de anotação de texto contém um objeto textAnnotation que contém informações sobre os dados desidentificados que foram inspecionados e transformados. Para que uma tag desidentificada apareça no registro de anotação, ela precisa ter sido inspecionada quanto às Informações protegidas de saúde (PHI) com base na configuração fornecida no campo TagFilterProfile. Por exemplo, as amostras em Como configurar anotações para dados do DICOM desidentificados usam a configuração DEIDENTIFY_TAG_CONTENTS.
  • Registros de anotação de imagem: contêm a localização de informações confidenciais em frames DICOM individuais. Cada registro de anotação de imagem tem um objeto ImageAnnotation que contém as coordenadas das informações confidenciais encontradas.

A operação de desidentificação cria registros de anotação para cada frame em uma instância do DICOM. Por exemplo, se uma instância do DICOM tiver três frames, a operação de desidentificação criará os seguintes registros de anotação:

  • Um registro de anotação de texto, contendo um textAnnotation, para as tags do DICOM na instância do DICOM.
  • Três registros de anotação de imagem, cada um contendo um imageAnnotation, para cada um dos três frames. Cada registro de anotação de imagem contém um campo frame_index para indicar o frame ao qual o registro corresponde.

Todos esses quatro registros de anotação têm o mesmo valor cloudHealthcareSource.name, que é o caminho da instância do DICOM no formato: projects/PROJECT_ID/locations/REGION/datasets/SOURCE_DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_UID/series/SERIES_UID/instances/INSTANCE_UID.

Como configurar anotações para dados do DICOM desidentificados

As amostras a seguir usam Como combinar a desidentificação de tags e a edição de texto gravado como ponto de partida. As amostras exibem como desidentificar uma instância do DICOM para editar todo o texto gravado na imagem e inspecionar e transformar textos confidenciais. As amostras também exibem como armazenar informações sobre os dados desidentificados em um registro de anotação em um novo armazenamento de anotações. Nas amostras, o campo store_quote é definido como true, o que significa que o registro da anotação de saída contém os valores originais dos dados que foram desidentificados.

O novo armazenamento de anotações está no conjunto de dados criado pela operação de desidentificação, mas também é possível criar o armazenamento de anotações em um conjunto de dados existente.

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"

Se a solicitação for bem-sucedida, o servidor retornará a resposta no formato JSON:

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

A resposta contém um nome de operação. Use o método Operation get para rastrear o status da operação:

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"

Se a solicitação for bem-sucedida, o servidor retornará a resposta no formato JSON. Depois que o processo de desidentificação for concluído, a resposta conterá "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"
  }
}

Depois de verificar se a desidentificação foi bem-sucedida, liste os armazenamentos de anotações no conjunto de dados e veja se a operação criou o novo armazenamento de anotações:

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"

Se a solicitação for bem-sucedida, o servidor retornará a resposta no formato JSON:

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

Use o valor ANNOTATION_STORE_ID para listar os registros de anotação no armazenamento de anotações:

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"

Se a solicitação for bem-sucedida, o servidor retornará a resposta no formato 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",
    ...
  ]
}

Veja que dois registros de anotação foram criados: um registro de anotação de texto e um registro de anotação de imagem.

Primeiro, use o valor TEXT_ANNOTATION_RECORD_ID para ver o registro de anotação de texto:

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"

Se a solicitação for bem-sucedida, o servidor retornará a resposta no formato JSON.

O objeto textAnnotation contém informações sobre o texto confidencial removido pela operação de desidentificação. No campo details, é possível ver que a operação forneceu uma lista de tags DICOM. Quando uma tag DICOM foi encontrada, suas informações foram fornecidas no objeto findings, que mostra o infoType, o valor do infoType e os locais onde os valores foram encontrados.

{
  "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"
          }
        ]
      }
    }
  }
}

Em seguida, use o valor IMAGE_ANNOTATION_RECORD_ID para ver o registro de anotação de imagem:

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"

Se a solicitação for bem-sucedida, o servidor retornará a resposta no formato JSON.

No objeto imageAnnotation, há vários vertices, cada um contendo quatro pontos X/Y que vinculam os locais em que a operação de desidentificação detectou dados de imagem confidenciais e texto gravado.

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