Utilizzo dell'API Cloud Healthcare per anonimizzare i dati clinici FHIR


Questo tutorial mostra a ricercatori, data scientist e team IT che lavorano con organizzazioni sanitarie e di scienze biologiche come utilizzare l'operazione di anonimizzazione di Fast Healthcare Interoperability Resources (FHIR) dell'API Cloud Healthcare per rimuovere o modificare le informazioni che consentono l'identificazione personale (PII), tra cui le informazioni sanitarie protette (PHI), dai dati clinici FHIR. L'anonimizzazione dei dati medici contribuisce a proteggere la privacy dei pazienti e a preparare i dati sanitari per l'utilizzo nella ricerca, nella condivisione dei dati e nel machine learning.

Questo tutorial presuppone che tu abbia una conoscenza di base di Linux. È utile anche avere una conoscenza di base di Google Cloud e della specifica FHIR e del suo utilizzo nei sistemi di cartelle cliniche elettroniche (EHR). Esegui tutti i comandi di questo tutorial in Cloud Shell.

Obiettivi

  • Crea un set di dati e un archivio FHIR dell'API Cloud Healthcare.
  • Importa i dati FHIR nell'archivio FHIR dell'API Cloud Healthcare.
  • Utilizza l'operazione di anonimizzazione FHIR dell'API Cloud Healthcare per rimuovere o modificare le PII e le PHI nelle istanze FHIR in un archivio FHIR.
  • Utilizza lo strumento a riga di comando curl per effettuare una chiamata di anonimizzazione FHIR tramite l'API Cloud Healthcare.

Costi

Questo tutorial utilizza i seguenti componenti fatturabili di Google Cloud:

Per generare una stima dei costi in base all'utilizzo previsto, utilizza il Calcolatore prezzi.

Prima di iniziare

L'API Cloud Healthcare viene utilizzata sempre all'interno di un progetto Google Cloud. I progetti sono la base per creare, abilitare e utilizzare tutti iGoogle Cloud servizi, tra cui gestire le API, attivare la fatturazione, aggiungere e rimuovere collaboratori e gestire le autorizzazioni per le Google Cloudrisorse. Utilizza la procedura seguente per creare un progetto Google Cloud o seleziona un progetto che hai già creato.

  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. In Cloud Shell, esegui il comando gcloud components update per assicurarti di avere la versione più recente del gcloud CLI che include le funzionalità relative all'API Cloud Healthcare.

Al termine delle attività descritte in questo documento, puoi evitare la fatturazione continua eliminando le risorse che hai creato. Per ulteriori informazioni, consulta la sezione Pulizia.

Creazione di un account di servizio IAM

Per questo tutorial sono necessari i ruoli Amministratore set di dati sanitari, Amministratore FHIR e Editor risorse FHIR. Per creare un account di servizio e assegnare i ruoli corretti:

  1. Crea un account di servizio.
  2. Assegna i ruoli all'account di servizio:

    • Healthcare Dataset Administrator
    • Amministratore FHIR Healthcare
    • Healthcare FHIR Resource Editor
  3. Crea e scarica la chiave JSON dell'account di servizio.

  4. Attiva la chiave dell'account di servizio:

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

    L'output è il seguente:

    Activated service account credentials for: [key-name@project-name.iam.gserviceaccount.com]
    
    • key-name è il nome che hai assegnato alla chiave dell'account di servizio.
    • project-name è il nome del tuo progetto Google Cloud.

Ottenere un token di accesso OAuth 2.0

Per utilizzare l'API Cloud Healthcare per importare i dati, devi disporre di un token di accesso OAuth 2.0 ottenuto con i comandi di questo tutorial. In questo tutorial, alcune delle richieste dell'API Cloud Healthcare di esempio utilizzano lo strumento a riga di comando curl. Questi esempi utilizzano il comando gcloud auth print-access-token per ottenere un token di accesso OAuth 2.0 e per includerlo nell'intestazione di autorizzazione della richiesta. Per ulteriori informazioni su questo comando, consulta gcloud auth application-default print-access-token.

Configurazione del set di dati FHIR per l'anonimizzazione

Ogni risorsa FHIR è un oggetto di tipo JSON che contiene coppie chiave-valore. Alcuni elementi sono standardizzati, mentre altri sono in testo libero. Puoi utilizzare l'operazione di anonimizzazione per:

  • Rimuovi i valori per chiavi specifiche nella risorsa FHIR.
  • Elabora il testo non strutturato in modo da rimuovere solo gli elementi PII, lasciando il resto dei contenuti nel testo invariato.

Quando anonimizzi un set di dati, il set di dati di destinazione non deve esistere prima di effettuare la chiamata all'API di anonimizzazione. L'operazione di anonimizzazione crea il set di dati di destinazione.

Quando anonimizzi un singolo archivio FHIR, il set di dati di destinazione deve esistere prima di effettuare la chiamata all'API di anonimizzazione.

Il set di dati di origine, l'archivio FHIR e l'archivio FHIR del set di dati di destinazione devono trovarsi nello stesso progetto Google Cloud. Quando esegui l'operazione di anonimizzazione, il set di dati di destinazione e l'archivio FHIR vengono creati nello stesso progetto Google Cloud del set di dati di origine e dell'archivio FHIR.

Se vuoi generare dati FHIR sintetici da utilizzare per questo tutorial, puoi utilizzare Synthea per generare dati sintetici nel formato FHIR STU3, copiarli in un bucket Cloud Storage e poi importarli nel datastore FHIR dell'API Cloud Healthcare. Synthea non genera dati FHIR con componenti di testo libero o non strutturato, pertanto non puoi utilizzarlo per esplorare questi aspetti dell'anonimizzazione.

Per questo tutorial, importa i dati FHIR di esempio nell'archivio FHIR come indicato nella procedura seguente.

  1. Configura le variabili di ambiente per il progetto e la posizione in cui verranno archiviati il set di dati, il datastore FHIR e i dati FHIR. I valori assegnati alle variabili di ambiente sono valori di esempio, come segue:

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

    Le definizioni delle variabili di ambiente dichiarate nell'esempio precedente sono le seguenti:

    • $PROJECT_ID è l'identificatore del Google Cloud progetto.
    • $REGION è la regione Google Cloud in cui viene creato il set di dati dell'API Cloud Healthcare.
    • $SOURCE_DATASET_ID è il nome del set di dati dell'API Cloud Healthcare dove sono archiviati i dati di origine.
    • $FHIR_STORE_ID è il nome dell'archivio FHIR dell'API Cloud Healthcare di origine.
    • $DESTINATION_DATASET_ID è il nome del set di dati di destinazione dell'API Cloud Healthcare in cui vengono scritti i dati anonimizzati.

    Utilizzerai queste variabili di ambiente anche più avanti in questo tutorial.

  2. Crea un set di dati dell'API Cloud Healthcare:

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

    L'output è simile al seguente, dove [OPERATION_NUMBER] è l'identificatore dell'operazione di creazione del set di dati utilizzato per monitorare la richiesta:

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

    Il comando precedente crea il set di dati di origine con il nome $SOURCE_DATASET_ID nella regione $REGION.

  3. Crea un archivio FHIR utilizzando il seguente comando:

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

    Il comando precedente crea un archivio FHIR con il nome $FHIR_STORE_ID nel set di dati $SOURCE_DATASET_ID.

  4. Aggiungi la risorsa Patient FHIR all'archivio FHIR utilizzando la funzione FHIR create con il seguente 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"
    

    L'argomento del comando corrisponde alla risorsa FHIR di esempio, una risorsa paziente 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"
    }
    

    Se la richiesta riesce, il server restituisce un output simile al seguente:

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

    Il comando curl precedente inserisce una nuova risorsa Patient nell'archivio FHIR di origine. Nell'output viene generato un identificatore paziente (id). L'identificatore del paziente è una stringa alfanumerica anonimizzata utilizzata nella risorsa FHIR Encounter per creare un link alla risorsa FHIR Patient.

  5. Aggiungi la risorsa FHIR Encounter all'archivio FHIR utilizzando la funzione FHIR create con il seguente comando. Nel comando, sostituisci il valore subject.reference con il valore dell'identificatore del paziente dall'output del comando curl precedente:

    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"
    

    L'argomento del comando corrisponde alla risorsa FHIR di esempio, una risorsa FHIR Encounter:

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

    Se la richiesta riesce, il server restituisce un output simile al seguente:

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

    Il comando curl precedente inserisce una nuova risorsa Encounter nell'archivio FHIR di origine.

Anonimizzazione dei dati FHIR

Successivamente, anonimizza i dati FHIR inseriti nell'archivio FHIR di origine. Oscurisci o trasforma tutti gli elementi PII in campi strutturati, come i campi Patient.name e Patient.address. Inoltre, anonimizzi gli elementi di PII nei dati non strutturati in testo, ad esempio Encounter.reason.text.

Facoltativamente, puoi esportare i dati risultanti direttamente in BigQuery per l'analisi e l'addestramento del machine learning.

Questa configurazione di anonimizzazione può essere utilizzata per un'analisi della salute della popolazione o per un caso d'uso simile. Nel contesto di questo tutorial, puoi spostare i dati strutturati anonimizzati in BigQuery per valutare le tendenze su larga scala. Potresti non avere bisogno di campi non strutturati, che sono difficili da normalizzare e analizzare su larga scala. Tuttavia, i campi non strutturati sono inclusi in questo tutorial come riferimento.

Esistono molti potenziali casi d'uso per l'anonimizzazione dei dati FHIR. Esistono inoltre molte opzioni di configurazione supportate dall'API Cloud Healthcare. Per ulteriori informazioni, inclusi comandi curl di esempio e strumenti per PowerShell per scenari diversi, consulta Anonimizzazione dei dati FHIR.

I campi che contengono una data vengono trasformati tramite spostamento della data, una tecnica che modifica tutte le date in una risorsa FHIR di un valore coerente e randomico. Lo spostamento delle date mantiene la coerenza all'interno di una risorsa FHIR in modo che i dettagli clinicamente pertinenti, come l'età del paziente e il tempo tra gli appuntamenti, vengano mantenuti senza rivelare informazioni di identificazione sul paziente. Vengono trasformati anche tutti gli identificatori nei campi non strutturati.

Il seguente esempio include anche una trasformazione di hashing sui campi name. L'hashing è una tecnica di crittografia unidirezionale che garantisce che un nome venga sempre trasformato nello stesso valore di output, generando output coerenti per lo stesso nome del paziente in più record del set di dati. In questa operazione, offuschi le PII mantenendo al contempo i link tra le risorse.

In questo esempio, la chiave di crittografia fornita, U2FsdGVkX19bS2oZsdbK9X5zi2utBn22uY+I2Vo0zOU=, è una chiave campionata con crittografia AES, a 256 bit e con codifica Base64 generata utilizzando il seguente comando.

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

Il comando ti chiede di inserire una password. Inserisci una password a tua scelta.

  1. Utilizza il comando curl per oscurare o trasformare tutti gli elementi PII nei campi strutturati, come i campi name e address, e per trasformare tutti gli identificatori nei campi non strutturati.

    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"
    

    Se la richiesta riesce, il server restituisce una risposta in formato JSON come la seguente:

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

    Nell'esempio precedente, il comando curl anonimizza la risorsa FHIR trasformando i valori nei seguenti modi:

    • Oscura il valore Patient.address.line, il valore Patient.address.text e il valore Patient.address.postalCode.
    • Sostituisce il valore Patient.name.family con un valore hash e il valore Patient.name.given con un valore hash.
    • Sostituisce i valori nel campo Patient.birthDate e nel campo period.start con valori prodotti dallo spostamento della data con un differenziale di 100 giorni.
    • Nel campo Encounter.reason.text, sostituisce il cognome del paziente con un valore hash e l'età del paziente con il valore letterale [AGE].
  2. La risposta all'operazione precedente contiene il nome di un'operazione. Utilizza il metodo get per monitorare lo stato dell'operazione:

    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"
    

    Se la richiesta riesce, il server restituisce una risposta in formato JSON. Al termine del processo di anonimizzazione, la risposta include"done": true.

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

    Il comando precedente restituisce lo stato dell'operazione di anonimizzazione.

  3. Utilizza l'identificatore del paziente per recuperare i dettagli della risorsa FHIR Patient nel nuovo set di dati di destinazione eseguendo il seguente 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"
    

    Se la richiesta riesce, il server restituisce una risposta come la seguente, ovvero la versione anonimizzata delle risorse FHIR originali:

      "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"\
    }
    

    Il comando precedente verifica che l'operazione di anonimizzazione abbia avuto esito positivo nell'anonimizzazione delle risorse FHIR.

Esegui la pulizia

Per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial, elimina il progetto che contiene le risorse oppure mantieni il progetto ed elimina le singole risorse.

Elimina il progetto

  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.

Elimina le singole risorse

  • Elimina i set di dati di destinazione:

    gcloud healthcare datasets delete $DESTINATION_DATASET_ID
    

Passaggi successivi