Usa la API de Cloud Healthcare para desidentificar los datos clínicos de FHIR


En este instructivo, se explica a los investigadores, los científicos de datos y los equipos de TI que trabajan con organizaciones dedicadas a la atención médica y a las ciencias biológicas cómo usar la operación de desidentificación de Fast Healthcare Interoperability Resources (FHIR) de la API de Cloud Healthcare con el fin de quitar o modificar la información de identificación personal (PII), incluida la información de salud protegida (PHI), de los datos clínicos de FHIR. La desidentificación de los datos médicos ayuda a proteger la privacidad de los pacientes y a preparar los datos de la atención médica para su uso en la investigación, el intercambio de datos y el aprendizaje automático.

En este instructivo, se da por hecho que tienes un conocimiento fundamental de Linux. También es útil conocer los conceptos básicos de Google Cloud, además de los de la especificación de FHIR y su uso en sistemas de registros médicos electrónicos (EHR). Debes ejecutar todos los comandos de este instructivo en Cloud Shell.

Objetivos

  • Crear un conjunto de datos de la API de Cloud Healthcare y un almacén de FHIR
  • Importar datos de FHIR al almacén de FHIR de la API de Cloud Healthcare
  • Usar la operación de desidentificación de FHIR de la API de Cloud Healthcare para quitar o modificar la PII y la PHI de las instancias de FHIR en un almacén de FHIR
  • Usar la herramienta de línea de comandos de curl para realizar una llamada de desidentificación de FHIR a través de la API de Cloud Healthcare

Costos

En este instructivo, se usan los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios.

Antes de comenzar

Todo el uso de la API de Cloud Healthcare se realiza en el contexto de un proyecto de Google Cloud. Los proyectos constituyen la base para la creación, la habilitación y el uso de todos los servicios de Google Cloud, dentro de los que se incluyen la administración de las API, la habilitación de la facturación, el agregado y la eliminación de colaboradores, y la administración de los permisos de los recursos de Google Cloud. Usa el siguiente procedimiento para crear un proyecto de Google Cloud o selecciona un proyecto que ya hayas creado.

  1. In the Google Cloud console, go to the project selector page.

    Go to project selector

  2. Select or create a Google Cloud project.

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the Cloud Healthcare API.

    Enable the API

  5. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  6. En Cloud Shell, ejecuta el comando gcloud components update para asegurarte de tener la versión más reciente de la CLI de gcloud, en la que se incluyen funciones relacionadas con la API de Cloud Healthcare.

Cuando finalices las tareas que se describen en este documento, puedes borrar los recursos que creaste para evitar que continúe la facturación. Para obtener más información, consulta Cómo realizar una limpieza.

Crea una cuenta de servicio de IAM

En este instructivo, se requieren las funciones de administrador de conjuntos de datos de Healthcare, administrador de FHIR y editor de recursos de FHIR. Sigue los pasos que se incluyen a continuación para crear una cuenta de servicio y asignarle las funciones correctas:

  1. Crea una cuenta de servicio.
  2. Asígnale las siguientes funciones a la cuenta de servicio:

    • Administrador de conjuntos de datos de Healthcare
    • Administrador de FHIR de Healthcare
    • Editor de recursos FHIR de Healthcare
  3. Crea y descarga la clave JSON de la cuenta de servicio.

  4. Activa la clave de tu cuenta de servicio mediante la ejecución del siguiente comando:

    gcloud auth activate-service-account --key-file=path-to-key-file
    

    Este es el resultado:

    Activated service account credentials for: [key-name@project-name.iam.gserviceaccount.com]
    
    • key-name es el nombre que asignaste a la clave de la cuenta de servicio.
    • project-name es el nombre del proyecto de Google Cloud.

Obtén un token de acceso de OAuth 2.0

Si deseas usar la API de Cloud Healthcare para transferir datos, necesitas un token de acceso de OAuth 2.0, que se puede obtener mediante los comandos de este instructivo. En este instructivo, en algunas de las solicitudes a la API de Cloud Healthcare de ejemplo, se usa la herramienta de línea de comandos de curl. En estos ejemplos, se usa el comando gcloud auth print-access-token para obtener un token del portador de OAuth 2.0 y, luego, incluirlo en el encabezado de autorización de la solicitud. Para obtener más información sobre este comando, consulta gcloud auth application-default print-access-token.

Configura el conjunto de datos de FHIR para la desidentificación

Cada recurso de FHIR es un objeto similar a un archivo JSON que contiene pares clave-valor. Algunos elementos están estandarizados y otros son de texto libre. Puedes usar la operación de desidentificación para llevar a cabo las siguientes acciones:

  • Quitar los valores de claves específicas en el recurso de FHIR
  • Procesar el texto sin estructurar para quitar solo los elementos de PII y dejar el resto del contenido como está

Cuando desidentificas un conjunto de datos, el conjunto de datos de destino no debe existir antes de que realices la llamada a la API de desidentificación. La operación de desidentificación crea el conjunto de datos de destino.

Cuando desidentificas un solo almacén de FHIR, el conjunto de datos de destino debe existir antes de que realices la llamada a la API de desidentificación.

El conjunto de datos de origen, el almacén de FHIR y el almacén de FHIR del conjunto de datos de destino deben estar en el mismo proyecto de Google Cloud. Cuando ejecutas la operación de desidentificación, el conjunto de datos de destino y el almacén de FHIR se crean en el mismo proyecto de Google Cloud que el conjunto de datos de origen y el almacén de FHIR.

Si deseas generar datos sintéticos de FHIR para usarlos en este instructivo, puedes usar Synthea a fin de generar datos sintéticos con el formato STU3 de FHIR, copiar los datos generados en un bucket de Cloud Storage y, luego, importarlos al almacén de FHIR de la API de Cloud Healthcare. Synthea no genera datos de FHIR con componentes de texto libre o sin estructurar, por lo que no puedes usarlo para explorar estos aspectos de la desidentificación.

Para este instructivo, debes importar datos de FHIR de muestra al almacén de FHIR, como se indica en el siguiente procedimiento.

  1. Configura variables de entorno para el proyecto y la ubicación en la que se almacenarán el conjunto de datos, el almacén de FHIR y los datos de FHIR. Los valores asignados a las variables de entorno son valores de muestra, como los siguientes:

    export PROJECT_ID=MyProj
    export REGION=us-central1
    export SOURCE_DATASET_ID=dataset1
    export FHIR_STORE_ID=FHIRstore1
    export DESTINATION_DATASET_ID=deid-dataset1
    

    Las definiciones de las variables de entorno declaradas en el ejemplo anterior son las siguientes:

    • $PROJECT_ID es el identificador de tu proyecto de Google Cloud.
    • $REGION es la región de Google Cloud en la que se crea el conjunto de datos de la API de Cloud Healthcare.
    • $SOURCE_DATASET_ID es el nombre del conjunto de datos de la API de Cloud Healthcare en el que se almacenan los datos de origen.
    • $FHIR_STORE_ID es el nombre del almacén de FHIR de origen de la API de Cloud Healthcare.
    • $DESTINATION_DATASET_ID es el nombre del conjunto de datos de destino de la API de Cloud Healthcare en el que se escriben los datos desidentificados.

    Usarás estas variables de entorno más adelante en este instructivo.

  2. Crea un conjunto de datos de la API de Cloud Healthcare:

    gcloud healthcare datasets create $SOURCE_DATASET_ID --location=$REGION
    

    El resultado es similar al siguiente, en el que [OPERATION_NUMBER] es el identificador de la operación de creación del conjunto de datos que se usa para realizar el seguimiento de la solicitud:

    Create request issued for: $SOURCE_DATASET_ID
    
    Waiting for operation [OPERATION_NUMBER] to complete...done.
    Created dataset $SOURCE_DATASET_ID.
    

    Mediante el comando anterior, se crea el conjunto de datos de origen con el nombre $SOURCE_DATASET_ID en la región $REGION.

  3. Crea un almacén de FHIR mediante el siguiente comando:

    gcloud healthcare fhir-stores create $FHIR_STORE_ID \
        --dataset=$SOURCE_DATASET_ID --location=$REGION
    

    Mediante el comando anterior, se crea un almacén de FHIR con el nombre $FHIR_STORE_ID en el conjunto de datos $SOURCE_DATASET_ID.

  4. Para agregar el recurso de paciente de FHIR al almacén de FHIR, usa la función create de FHIR con el siguiente comando:

    curl -X POST \
        -H "Authorization: Bearer $(gcloud auth print-access-token)" \
        -H "Content-Type: application/fhir+json; charset=utf-8" \
        --data "{
           \"address\": [
        {
          \"city\": \"Anycity\",
          \"district\": \"Anydistrict\",
          \"line\": [
            \"123 Main Street\"
          ],
          \"period\": {
            \"start\": \"1990-12-05\"
          },
          \"postalCode\": \"12345\",
          \"state\": \"CA\",
          \"text\": \"123 Main Street Anycity, Anydistrict, CA 12345\",
          \"use\": \"home\"
        }
      ],
              \"name\": [
            {
              \"family\": \"Smith\",
              \"given\": [
                \"Darcy\"
              ],
              \"use\": \"official\"
            }
          ],
          \"gender\": \"female\",
          \"birthDate\": \"1980-12-05\",
          \"resourceType\": \"Patient\"
        }" \
    "https://healthcare.googleapis.com/v1/projects/$PROJECT_ID/locations/$REGION/datasets/$SOURCE_DATASET_ID/fhirStores/$FHIR_STORE_ID/fhir/Patient"
    

    El argumento del comando corresponde al recurso de FHIR de ejemplo, un recurso de paciente de FHIR.

    {
      "address": [
        {
          "city": "Anycity",
          "district": "Anydistrict",
          "line": [
            "123 Main Street"
          ],
          "period": {
            "start": "1990-12-05"
          },
          "postalCode": "12345",
          "state": "CA",
          "text": "123 Main Street Anycity, Anydistrict, CA 12345",
          "use": "home"
        }
      ],
      "name": [
        {
          "family": "Smith",
          "given": [
            "Darcy"
          ],
    "use": "official"
        }
      ],
    "gender": "female",
    "birthDate": "1980-12-05",
     "resourceType": "Patient"
    }
    

    Si la solicitud se completa de forma correcta, se mostrará un resultado como el siguiente en el servidor:

    {
      "address": [
        {
          "city": "Anycity",
          "district": "Anydistrict",
          "line": [
            "123 Main Street"
          ],
          "period": {
            "start": "1990-12-05"
          },
          "postalCode": "12345",
          "state": "CA",
          "text": "123 Main Street Anycity, Anydistrict, CA 12345",
          "use": "home"
        }
      ],
      "birthDate": "1980-12-05",
      "gender": "female",
      "id": "0359c226-5d63-4845-bd55-74063535e4ef",
      "meta": {
        "lastUpdated": "2020-02-08T00:03:21.745220+00:00",
        "versionId": "MTU4MTEyMDIwMTc0NTIyMDAwMA"
      },
      "name": [
        {
          "family": "Smith",
          "given": [
            "Darcy"
          ],
          "use": "official"
        }
      ],
      "resourceType": "Patient"
    }
    

    Mediante el comando de curl, anterior, se inserta un recurso de paciente nuevo en el almacén de FHIR de origen. Se genera un identificador del paciente (id) en el resultado. El identificador del paciente es una string alfanumérica desidentificada que se usa en el recurso de encuentro de FHIR para vincularlo al recurso de paciente de FHIR.

  5. Para agregar el recurso de encuentro de FHIR al almacén de FHIR, usa la función create de FHIR con el siguiente comando. En el comando, reemplaza el valor subject.reference por el valor del identificador del paciente que se generó en el resultado del comando de curl anterior:

    curl -X POST \
        -H "Authorization: Bearer $(gcloud auth print-access-token)" \
        -H "Content-Type: application/fhir+json; charset=utf-8" \
        --data "{
          \"status\": \"finished\",
          \"class\": {
            \"system\": \"http://hl7.org/fhir/v3/ActCode\",
            \"code\": \"IMP\",
            \"display\": \"inpatient encounter\"
          },
          \"reason\": [
            {
              \"text\": \"Mrs. Smith is a 39-year-old female who has a past
    medical history significant for a myocardial infarction. Catheterization
    showed a possible kink in one of her blood vessels.\"
            }
          ],
          \"subject\": {
            \"reference\":
    \"Patient/0359c226-5d63-4845-bd55-74063535e4ef\"
          },
          \"resourceType\": \"Encounter\"
        }" \
    
    "https://healthcare.googleapis.com/v1/projects/$PROJECT_ID/locations/$REGION/datasets/$SOURCE_DATASET_ID/fhirStores/$FHIR_STORE_ID/fhir/Encounter"
    

    El argumento del comando corresponde al recurso de FHIR de ejemplo, un recurso de encuentro de FHIR:

    {
          "status": "finished",
          "class": {
            "system": "http://hl7.org/fhir/v3/ActCode",
            "code": "IMP",
            "display": "inpatient encounter"
          },
          "reason": [
            {
              "text": "Mrs. Smith is a 39-year-old female who has a past medical
    history significant for a myocardial infarction. Catheterization showed a
    possible kink in one of her blood vessels."
            }
          ],
          "subject": {
            "reference": "Patient/0359c226-5d63-4845-bd55-74063535e4ef"
          },
          "resourceType": "Encounter"
        }
    

    Si la solicitud se completa de forma correcta, se mostrará un resultado como el siguiente en el servidor:

    {
      "class": {
        "code": "IMP",
        "display": "inpatient encounter",
        "system": "http://hl7.org/fhir/v3/ActCode"
      },
      "id": "0038a95f-3c11-4163-8c2e-10842b6b1547",
      "meta": {
        "lastUpdated": "2020-02-12T00:39:16.822443+00:00",
        "versionId": "MTU4MTQ2Nzk1NjgyMjQ0MzAwMA"
      },
      "reason": [
        {
          "text": "Mrs. Smith is a 39-year-old female who has a past medical history
    significant for a myocardial infarction. Catheterization showed a possible
    kink in one of her blood vessels."
        }
      ],
      "resourceType": "Encounter",
      "status": "finished",
      "subject": {
        "reference": "Patient/0359c226-5d63-4845-bd55-74063535e4ef"
      }
    

    Mediante el comando de curl anterior, se inserta un recurso de encuentro nuevo en el almacén de FHIR de origen.

Desidentifica los datos de FHIR

A continuación, debes desidentificar los datos de FHIR que insertaste en el almacén de FHIR de origen. Puedes ocultar o transformar todos los elementos de PII en campos estructurados, como los campos Patient.name y Patient.address. También puedes desidentificar los elementos de PII en los datos sin estructurar del texto, como Encounter.reason.text.

Luego, de forma opcional, puedes exportar los datos resultantes directamente a BigQuery para que se usen en el análisis y el entrenamiento de aprendizaje automático.

Esta configuración de desidentificación se puede usar en un análisis de la salud de la población o en un caso de uso similar. En el contexto de este instructivo, puedes mover los datos estructurados desidentificados a BigQuery para evaluar las tendencias a gran escala. Es posible que no necesites usar campos sin estructurar, que son difíciles de normalizar y analizar a gran escala. Sin embargo, en este instructivo, se incluyen campos sin estructurar como referencia.

Existen muchos casos de uso posibles para la desidentificación de datos de FHIR. También hay muchas opciones de configuración que son compatibles con la API de Cloud Healthcare. Si deseas obtener más información, además de muestras de comandos y herramientas de curl para ejemplos de PowerShell en distintas situaciones, consulta Desidentifica datos de FHIR.

Los campos que contienen una fecha se transforman mediante el cambio de fecha, una técnica mediante la que se cambian todas las fechas de un recurso de FHIR de a una cantidad aleatoria y coherente. El cambio de fecha mantiene la coherencia dentro de un recurso de FHIR para que se conserven los detalles que son relevantes desde el punto de vista médico, como la edad del paciente y el tiempo transcurrido entre las consultas, sin revelar la información de identificación del paciente. También se transforman todos los identificadores en los campos sin estructurar.

En el siguiente ejemplo, también se incluye una transformación de hashing en los campos name. El hashing es una técnica de encriptación unidireccional que garantiza que un nombre se transforme siempre en el mismo valor de salida, lo que genera resultados coherentes para el nombre del mismo paciente en varios registros del conjunto de datos. En esta operación, debes ocultar la PII y, a la vez, conservar los vínculos entre los recursos.

En este ejemplo, la clave criptográfica que se proporciona, U2FsdGVkX19bS2oZsdbK9X5zi2utBn22uY+I2Vo0zOU=, es una clave de 256 bits con encriptación AES que está codificada en Base64 y se genera mediante el siguiente comando.

echo -n "test" | openssl enc -e -aes-256-ofb -a -salt

En el comando, se te solicita que ingreses una contraseña. Ingresa una contraseña que elijas.

  1. Usa el comando de curl con el fin de ocultar o transformar todos los elementos de PII en los campos estructurados, como los campos name y address, y para transformar todos los identificadores en campos sin estructurar.

    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': {
              'fieldMetadataList': {
                'paths': [
                  'Patient.address.state',
                  'Patient.address.line',
                  'Patient.address.text',
                  'Patient.address.postalCode'
                ],
                'action': 'TRANSFORM'
              },
             'fieldMetadataList': {
               'paths': [
                 'Encounter.reason.text'
               ],
               'action': 'INSPECT_AND_TRANSFORM'
             },
           'text': {
             'transformations': [
               {
                 'infoTypes': [],
                 'replaceWithInfoTypeConfig': {}
               }
             ]
           },
              'fieldMetadataList': {
                'paths': [
                  'Patient.name.family',
                  'Patient.name.given'
                ],
                'action': 'TRANSFORM'
              },
            'text': {
              'transformations': {
                'infoTypes': [
                  'PERSON_NAME'
                ],
                'cryptoHashConfig': {
                  'cryptoKey':
    'U2FsdGVkX19bS2oZsdbK9X5zi2utBn22uY+I2Vo0zOU='
                }
              }
            },
              'fieldMetadataList': {
                'paths': [
                  'Patient.birthDate',
                  'Patient.address.period.start'
                ],
                'action': 'TRANSFORM'
              },
            'text': {
              'transformations': {
                'infoTypes': [
                  'DATE'
                ],
                'dateShiftConfig': {
                  'cryptoKey':
    'U2FsdGVkX19bS2oZsdbK9X5zi2utBn22uY+I2Vo0zOU='
                }
              }
            }
          }
        }"
    "https://healthcare.googleapis.com/v1/projects/$PROJECT_ID/locations/$REGION/datasets/$SOURCE_DATASET_ID:deidentify"
    

    Si la solicitud se completa de forma correcta, se mostrará una respuesta en formato JSON en el servidor, como la que se encuentra a continuación:

    {
      "name": "projects/$PROJECT_ID/locations/$REGION/datasets/$SOURCE_DATASET_ID/OPERATION_NAME"
    }
    

    En el ejemplo anterior, a través del comando de curl, se desidentifica el recurso de FHIR mediante la transformación de los valores de las siguientes maneras:

    • Se ocultan los valores Patient.address.line, Patient.address.text y Patient.address.postalCode.
    • Se reemplazan los valores Patient.name.family y Patient.name.given por valores de hash.
    • Se reemplazan los valores en los campos Patient.birthDate y period.start por los valores que se producen mediante el cambio de fechas con una diferencia de 100 días.
    • En el campo Encounter.reason.text, se reemplaza el apellido del paciente por un valor de hash y su edad por el valor literal de [AGE].
  2. En la respuesta a la operación anterior, se incluye un nombre de operación. Usa el método get para realizar un seguimiento del estado de la operación:

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

    Si la solicitud tiene éxito, en el servidor se mostrará una respuesta en formato JSON. Cuando se complete el proceso de desidentificación, se incluirá "done": true en la respuesta.

    {
      "name": "projects/$PROJECT_ID/locations/$REGION/datasets/$SOURCE_DATASET_ID/operations/OPERATION_NAME",
      "metadata": {
        "@type": "type.googleapis.com/google.cloud.healthcare.v1.OperationMetadata",
        "apiMethodName": "google.cloud.healthcare.v1.dataset.DatasetService.DeidentifyDataset",
        "createTime": "2018-01-01T00:00:00Z",
        "endTime": "2018-01-01T00:00:00Z"
      },
      "done": true,
      "response": {
        "@type": "...",
        "successStoreCount": "SUCCESS_STORE_COUNT"
      }
    }
    

    Mediante el comando anterior, se muestra el estado de la operación de desidentificación.

  3. Usa el identificador del paciente para obtener los detalles del recurso de paciente de FHIR en el nuevo conjunto de datos de destino mediante la ejecución del siguiente comando:

    curl -X GET \
         -H "Authorization: Bearer $(gcloud auth print-access-token)" \
     "https://healthcare.googleapis.com/v1/projects/$PROJECT_ID/locations/$REGION/datasets/$DESTINATION_DATASET_ID/fhirStores/$FHIR_STORE_ID/fhir/Patient/a952e409-2403-43e6-9815-cb78c5b5eca2/\$everything"
    

    Si la solicitud se completa de forma correcta, se mostrará una respuesta como la siguiente en el servidor, que es la versión desidentificada de los recursos de FHIR originales:

      "entry": [\
        {\
          "resource": {\
            "class": {\
              "code": "IMP",\
              "display": "inpatient encounter",\
              "system": "http://hl7.org/fhir/v3/ActCode"\
            },\
            "id": "0038a95f-3c11-4163-8c2e-10842b6b1547",\
            "reason": [\
              {\
                "text": "Mr. NlVBV12Hhb5DD8WNqlTpXboFxzlUSlqAmYDet/jIViQ= is a [AGE]
    gentleman who has a past medical history significant for a myocardial
    infarction. Catheterization showed a possible kink in one of his vessels."\
              }\
            ],\
            "resourceType": "Encounter",\
            "status": "finished",\
            "subject": {\
              "reference": "Patient/0359c226-5d63-4845-bd55-74063535e4ef"\
            }\
          }\
        },\
        {\
          "resource": {\
            "address": [\
              {\
                "city": "Anycity",\
                "district": "Anydistrict",\
                "line": [\
                  ""\
                ],\
                "period": {\
                  "start": "1990-09-23"\
                },\
                "postalCode": "",\
                "state": "",\
                "text": "",\
                "use": "home"\
              }\
            ],\
            "birthDate": "1980-09-23",\
            "gender": "female",\
            "id": "0359c226-5d63-4845-bd55-74063535e4ef",\
            "name": [\
              {\
                "family": "NlVBV12Hhb5DD8WNqlTpXboFxzlUSlqAmYDet/jIViQ=",\
                "given": [\
                  "FSH4e the project.D/IGb80a1rS0L0kqfC3DCDt6//17VPhIkOzH2pk="\
                ],\
                "use": "official"\
              }\
            ],\
            "resourceType": "Patient"\
          }\
        }\
      ],\
      "resourceType": "Bundle",\
      "total": 2,\
      "type": "searchset"\
    }
    

    Mediante el comando anterior, se verifica que la operación de desidentificación logre desidentificar los recursos de FHIR.

Realiza una limpieza

Para evitar que se apliquen cargos a tu cuenta de Google Cloud por los recursos usados en este instructivo, borra el proyecto que contiene los recursos o conserva el proyecto y borra los recursos individuales.

Borra el proyecto

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

Borra los recursos individuales

  • Borra los conjuntos de datos de destino mediante la ejecución del siguiente comando:

    gcloud healthcare datasets delete $DESTINATION_DATASET_ID
    

¿Qué sigue?