Utiliser la norme DICOMweb

Cette page explique comment utiliser la mise en œuvre de DICOMweb par l'API Cloud Healthcare pour stocker et gérer des données d'image DICOM.

Pour plus d'informations sur la manière dont l'API Cloud Healthcare met en œuvre divers services REST DICOMweb, consultez la déclaration de conformité DICOM.

Seule une architecture REST permet de mettre en œuvre le protocole DICOMweb dans l'API Cloud Healthcare. Le protocole RPC n'est pas compatible.

Installer la CLI DICOMweb de l'API Cloud Healthcare

Plusieurs exemples de cette page utilisent la CLI DICOMweb de l'API Cloud Healthcare, un outil Open Source qui simplifie l'interaction avec les serveurs DICOMweb. Il fournit des fonctionnalités de stockage, de récupération, de suppression et de recherche de fichiers DICOM. La page GitHub de l'outil contient des informations supplémentaires, telles que des conditions détaillées d'installation et des moyens de personnaliser l'outil.

L'outil s'exécute à l'aide de Python. Pour plus d'informations sur la configuration de Python sur Google Cloud, consultez la page Configurer un environnement de développement Python.

Après avoir configuré Python, vous pouvez installer l'outil à l'aide de PIP :

pip install https://github.com/GoogleCloudPlatform/healthcare-api-dicomweb-cli/archive/v1.0.zip

Pour utiliser l'outil, vous devez vous authentifier auprès des serveurs Google Cloud. Pour ce faire, utilisez l'une des méthodes suivantes :

Après avoir configuré l'une de ces options, l'outil détecte automatiquement vos identifiants.

Stocker des données DICOM

Avant de pouvoir stocker des données DICOM, vous devez créer un magasin DICOM.

L'API Cloud Healthcare met en œuvre la transaction en magasin. Service Web RESTful pour le stockage de données DICOM. Pour en savoir plus, consultez la section Transaction en magasin de la déclaration de conformité DICOM de l'API Cloud Healthcare.

Vous pouvez stocker des données DICOM à l'aide des méthodes suivantes. Dans les deux cas, vous devez transmettre un en-tête Accept application/dicom dans votre requête.

  • Stocker une instance DICOM (généralement un fichier .dcm).
  • Stocker des métadonnées JSON DICOM avec des fichiers JPEG.

    Toutes les requêtes de stockage de métadonnées JSON DICOM avec des fichiers JPEG sont composées de messages en plusieurs parties, désignés par la partie multipart/related de leur Content-Type. La partie multipart/related de Content-Type indique que la requête est composée de plusieurs parties de données qui sont combinées une fois la requête terminée. Chacun de ces ensembles de données doit être séparé à l'aide d'une limite, comme indiqué par la partie boundary de Content-Type.

Les exemples suivants montrent comment stocker une instance dans un magasin DICOM. Pour plus d'informations, consultez la page projects.locations.datasets.dicomStores.storeInstances.

Stocker une instance DICOM

Les exemples suivants montrent comment stocker une instance DICOM. Pour en savoir plus, consultez les sections sur projects.locations.datasets.dicomStores.storeInstances

REST

Avant d'utiliser les données de requête ci-dessous, effectuez les remplacements suivants :

  • PROJECT_ID : ID de votre projet Google Cloud
  • LOCATION : emplacement de l'ensemble de données
  • DATASET_ID : ensemble de données parent du magasin DICOM
  • DICOM_STORE_ID : ID du magasin DICOM
  • DICOM_INSTANCE_FILE : chemin d'accès à un fichier d'instance DICOM sur votre ordinateur local, se terminant par le suffixe .dcm

Pour envoyer votre requête, choisissez l'une des options suivantes :

curl

Exécutez la commande suivante :

curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/dicom" \
--data-binary @DICOM_INSTANCE_FILE \
"https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies"

PowerShell

Exécutez la commande suivante :

$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }

Invoke-WebRequest `
-Method POST `
-Headers $headers `
-InFile DICOM_INSTANCE_FILE `
-Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies" | Select-Object -Expand Content
La sortie est la réponse XML suivante:

Go

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"io/ioutil"

	healthcare "google.golang.org/api/healthcare/v1"
)

// dicomWebStoreInstance stores the given dicomFile with the dicomWebPath.
func dicomWebStoreInstance(w io.Writer, projectID, location, datasetID, dicomStoreID, dicomWebPath, dicomFile string) error {
	ctx := context.Background()

	dicomData, err := ioutil.ReadFile(dicomFile)
	if err != nil {
		return fmt.Errorf("ReadFile: %w", err)
	}

	healthcareService, err := healthcare.NewService(ctx)
	if err != nil {
		return fmt.Errorf("healthcare.NewService: %w", err)
	}

	storesService := healthcareService.Projects.Locations.Datasets.DicomStores

	parent := fmt.Sprintf("projects/%s/locations/%s/datasets/%s/dicomStores/%s", projectID, location, datasetID, dicomStoreID)

	call := storesService.StoreInstances(parent, dicomWebPath, bytes.NewReader(dicomData))
	call.Header().Set("Content-Type", "application/dicom")
	resp, err := call.Do()
	if err != nil {
		return fmt.Errorf("StoreInstances: %w", err)
	}
	defer resp.Body.Close()

	respBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("could not read response: %w", err)
	}

	if resp.StatusCode > 299 {
		return fmt.Errorf("StoreInstances: status %d %s: %s", resp.StatusCode, resp.Status, respBytes)
	}
	fmt.Fprintf(w, "%s", respBytes)
	return nil
}

Java

import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.healthcare.v1.CloudHealthcare;
import com.google.api.services.healthcare.v1.CloudHealthcareScopes;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Collections;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.HttpClients;

public class DicomWebStoreInstance {
  private static final String DICOM_NAME = "projects/%s/locations/%s/datasets/%s/dicomStores/%s";
  private static final JsonFactory JSON_FACTORY = new GsonFactory();
  private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport();

  public static void dicomWebStoreInstance(String dicomStoreName, String filePath)
      throws IOException, URISyntaxException {
    // String dicomStoreName =
    //    String.format(
    //        DICOM_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-dicom-id");
    // String filePath = "path/to/file.dcm";

    // Initialize the client, which will be used to interact with the service.
    CloudHealthcare client = createClient();

    HttpClient httpClient = HttpClients.createDefault();
    String uri = String.format("%sv1/%s/dicomWeb/studies", client.getRootUrl(), dicomStoreName);
    URIBuilder uriBuilder = new URIBuilder(uri).setParameter("access_token", getAccessToken());
    // Load the data from file representing the study.
    File f = new File(filePath);
    byte[] dicomBytes = Files.readAllBytes(Paths.get(filePath));
    ByteArrayEntity requestEntity = new ByteArrayEntity(dicomBytes);

    HttpUriRequest request =
        RequestBuilder.post(uriBuilder.build())
            .setEntity(requestEntity)
            .addHeader("Content-Type", "application/dicom")
            .build();

    // Execute the request and process the results.
    HttpResponse response = httpClient.execute(request);
    HttpEntity responseEntity = response.getEntity();
    if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
      System.err.print(
          String.format(
              "Exception storing DICOM instance: %s\n", response.getStatusLine().toString()));
      responseEntity.writeTo(System.err);
      throw new RuntimeException();
    }
    System.out.println("DICOM instance stored: ");
    responseEntity.writeTo(System.out);
  }

  private static CloudHealthcare createClient() throws IOException {
    // Use Application Default Credentials (ADC) to authenticate the requests
    // For more information see https://cloud.google.com/docs/authentication/production
    GoogleCredentials credential =
        GoogleCredentials.getApplicationDefault()
            .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM));

    // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests.
    HttpRequestInitializer requestInitializer =
        request -> {
          new HttpCredentialsAdapter(credential).initialize(request);
          request.setConnectTimeout(60000); // 1 minute connect timeout
          request.setReadTimeout(60000); // 1 minute read timeout
        };

    // Build the client for interacting with the service.
    return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer)
        .setApplicationName("your-application-name")
        .build();
  }

  private static String getAccessToken() throws IOException {
    GoogleCredentials credential =
        GoogleCredentials.getApplicationDefault()
            .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM));

    return credential.refreshAccessToken().getTokenValue();
  }
}

Node.js

const google = require('@googleapis/healthcare');
const healthcare = google.healthcare({
  version: 'v1',
  auth: new google.auth.GoogleAuth({
    scopes: ['https://www.googleapis.com/auth/cloud-platform'],
  }),
});
const fs = require('fs');

const dicomWebStoreInstance = async () => {
  // TODO(developer): uncomment these lines before running the sample
  // const cloudRegion = 'us-central1';
  // const projectId = 'adjective-noun-123';
  // const datasetId = 'my-dataset';
  // const dicomStoreId = 'my-dicom-store';
  // const dcmFile = 'file.dcm';
  const parent = `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/dicomStores/${dicomStoreId}`;
  const dicomWebPath = 'studies';
  // Use a stream because other types of reads overwrite the client's HTTP
  // headers and cause storeInstances to fail.
  const binaryData = fs.createReadStream(dcmFile);
  const request = {
    parent,
    dicomWebPath,
    requestBody: binaryData,
  };

  const instance =
    await healthcare.projects.locations.datasets.dicomStores.storeInstances(
      request,
      {
        headers: {
          'Content-Type': 'application/dicom',
          Accept: 'application/dicom+json',
        },
      }
    );
  console.log('Stored DICOM instance:\n', JSON.stringify(instance.data));
};

dicomWebStoreInstance();

Python

def dicomweb_store_instance(project_id, location, dataset_id, dicom_store_id, dcm_file):
    """Handles the POST requests specified in the DICOMweb standard.

    See https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/healthcare/api-client/v1/dicom
    before running the sample."""

    # Imports the google.auth.transport.requests transport
    from google.auth.transport import requests

    # Imports a module to allow authentication using Application Default Credentials (ADC)
    import google.auth

    # Gets credentials from the environment. google.auth.default() returns credentials and the
    # associated project ID, but in this sample, the project ID is passed in manually.
    credentials, _ = google.auth.default()

    scoped_credentials = credentials.with_scopes(
        ["https://www.googleapis.com/auth/cloud-platform"]
    )
    # Creates a requests Session object with the credentials.
    session = requests.AuthorizedSession(scoped_credentials)

    # URL to the Cloud Healthcare API endpoint and version
    base_url = "https://healthcare.googleapis.com/v1"

    # TODO(developer): Uncomment these lines and replace with your values.
    # project_id = 'my-project'  # replace with your GCP project ID
    # location = 'us-central1'  # replace with the parent dataset's location
    # dataset_id = 'my-dataset'  # replace with the parent dataset's ID
    # dicom_store_id = 'my-dicom-store' # replace with the DICOM store ID
    # dcm_file = 'dicom000_0001.dcm'  # replace with a DICOM file
    url = f"{base_url}/projects/{project_id}/locations/{location}"

    dicomweb_path = "{}/datasets/{}/dicomStores/{}/dicomWeb/studies".format(
        url, dataset_id, dicom_store_id
    )

    with open(dcm_file, "rb") as dcm:
        dcm_content = dcm.read()

    # Sets required "application/dicom" header on the request
    headers = {"Content-Type": "application/dicom"}

    response = session.post(dicomweb_path, data=dcm_content, headers=headers)
    response.raise_for_status()
    print("Stored DICOM instance:")
    print(response.text)
    return response

Spécifier la classe de stockage pour stocker des instances DICOM (version Preview)

Par défaut, la méthode projects.locations.datasets.dicomStores.storeInstances stocke une instance DICOM dans un magasin DICOM avec une classe de stockage standard. Vous pouvez définir la classe de stockage lorsque vous stockez des objets DICOM à partir de votre machine locale. Pour en savoir plus, consultez Modifiez la classe de stockage DICOM.

Les exemples suivants montrent comment spécifier la classe de stockage lorsque vous stockez des objets DICOM à partir de votre machine locale.

curl

Utilisez le projects.locations.datasets.dicomStores.storeInstances. Avant d'utiliser les données de requête ci-dessous, effectuez les remplacements suivants :

  • PROJECT_ID : ID de votre projet Google Cloud
  • LOCATION : emplacement de l'ensemble de données
  • DATASET_ID : ensemble de données parent du magasin DICOM
  • DICOM_STORE_ID : ID du magasin DICOM
  • DICOM_INSTANCE_FILE : chemin d'accès à un fichier d'instance DICOM sur votre ordinateur local, se terminant par le suffixe .dcm
  • STORAGE_CLASS: classe de stockage de l'instance DICOM dans le magasin DICOM de STANDARD, NEARLINE, COLDLINE et ARCHIVE

curl -X POST \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    -H "Content-Type: application/dicom" \
    -H "Storage-Class: STORAGE_CLASS"
    --data-binary @DICOM_INSTANCE_FILE \
    "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies"

Si la requête aboutit, le serveur renvoie la réponse suivante :

<NativeDicomModel>
  <DicomAttribute tag="00081190" vr="UR" keyword="RetrieveURL">
    <Value number="1">https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_INSTANCE_UID</Value>
  </DicomAttribute>
  <DicomAttribute tag="00081199" vr="SQ" keyword="ReferencedSOPSequence">
    <Item number="1">
      <DicomAttribute tag="00081150" vr="UI" keyword="ReferencedSOPClassUID">
        <Value number="1">SOP_CLASS_UID</Value>
      </DicomAttribute>
      <DicomAttribute tag="00081155" vr="UI" keyword="ReferencedSOPInstanceUID">
        <Value number="1">SOP_INSTANCE_UID</Value>
      </DicomAttribute>
      <DicomAttribute tag="00081190" vr="UR" keyword="RetrieveURL">
        <Value number="1">https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_INSTANCE_UID/series/SERIES_INSTANCE_UID/instances/INSTANCE_UID</Value>
      </DicomAttribute>
    </Item>
  </DicomAttribute>
</NativeDicomModel>

PowerShell

Utilisez la méthode projects.locations.datasets.dicomStores.storeInstances.

Avant d'utiliser les données de requête ci-dessous, effectuez les remplacements suivants :

  • PROJECT_ID : ID de votre projet Google Cloud
  • LOCATION : emplacement de l'ensemble de données
  • DATASET_ID : ensemble de données parent du magasin DICOM
  • DICOM_STORE_ID : ID du magasin DICOM
  • DICOM_INSTANCE_FILE : chemin d'accès à un fichier d'instance DICOM sur votre ordinateur local, se terminant par le suffixe .dcm
  • STORAGE_CLASS: classe de stockage de l'instance DICOM dans le magasin DICOM de STANDARD, NEARLINE, COLDLINE et ARCHIVE

$cred = gcloud auth application-default print-access-token
$headers = @{ "Authorization" = "Bearer $cred"; "Storage-Class" = "STORAGE_CLASS" }

Invoke-WebRequest `
  -Method Post `
  -Headers $headers `
  -ContentType: "application/dicom" `
  -InFile DCM_FILE.dcm `
  -Uri "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies" | Select-Object -Expand Content

Si la requête aboutit, le serveur renvoie la réponse au format JSON :

<NativeDicomModel>
  <DicomAttribute tag="00081190" vr="UR" keyword="RetrieveURL">
    <Value number="1">https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_INSTANCE_UID</Value>
  </DicomAttribute>
  <DicomAttribute tag="00081199" vr="SQ" keyword="ReferencedSOPSequence">
    <Item number="1">
      <DicomAttribute tag="00081150" vr="UI" keyword="ReferencedSOPClassUID">
        <Value number="1">SOP_CLASS_UID</Value>
      </DicomAttribute>
      <DicomAttribute tag="00081155" vr="UI" keyword="ReferencedSOPInstanceUID">
        <Value number="1">SOP_INSTANCE_UID</Value>
      </DicomAttribute>
      <DicomAttribute tag="00081190" vr="UR" keyword="RetrieveURL">
        <Value number="1">https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_INSTANCE_UID/series/SERIES_INSTANCE_UID/instances/INSTANCE_UID</Value>
      </DicomAttribute>
    </Item>
  </DicomAttribute>
</NativeDicomModel>

Créer des instances DICOM à partir de métadonnées JSON et d'images JPEG

L'API Cloud Healthcare peut créer des instances DICOM à l'aide de métadonnées JSON. et un fichier JPEG. Créez des instances DICOM à partir de métadonnées JSON et d'un fichier JPEG si vous préférez ne pas effectuer d'analyse et de sérialisation DICOM vous-même, car l'API Cloud Healthcare peut effectuer ces tâches à votre place.

La requête HTTP qui stocke ces données doit inclure les éléments suivants dans le fichier Content-Type de la requête :

  • Type de média multipart/related
  • Type MIME application/dicom+json
  • Un séparateur de type boundary

Les exemples suivants montrent comment stocker un fichier de métadonnées JSON avec un fichier JPEG.

curl

L'exemple suivant suppose que vous avez une image JPEG existante.

L'enregistrement d'un fichier de métadonnées JSON avec une image JPEG comprend trois étapes :

  1. Créez un fichier contenant une représentation JSON d'une instance DICOM contenant une image JPEG. Un fichier de modèle est fourni ci-dessous.
  2. Créez trois fichiers de limites :

    • opening.file : contient la limite d'ouverture du fichier de métadonnées JSON
    • middle.file : contient la limite centrale de l'image JPEG
    • closing.file : contient la limite de fermeture pour toutes les parties du message
  3. Créez un fichier nommé multipart-request.file en plaçant le fichier de métadonnées JSON et l'image JPEG dans les fichiers de limites.

Notez les valeurs suivantes fournies par défaut dans le fichier de modèle de métadonnées JSON :

  • L'UID de la syntaxe de transfert (1.2.840.10008.1.2.4.50) désigne la syntaxe de transfert en tant que référence JPEG. La plupart des images JPEG sont au format JPEG Baseline. La valeur d'interaction photométrique (YBR_FULL_422) indique que l'image est en couleur et non en nuances de gris.
  • BulkDataUri est un descripteur arbitraire de l'image et, dans le modèle, il est défini sur jpeg-image. Cette valeur est utilisée lors de la création de la limite de l'image.

Les valeurs de SOP_CLASS_UID, SOP_INSTANCE_UID, STUDY_INSTANCE_UID et SERIES_INSTANCE_UID peuvent être n'importe quelle valeur numérique séparées par un point. DICOM applique une hiérarchie des identifiants pour les instances, les patients, les études et les séries. Choisissez donc un ensemble logique d'identifiants pour ces variables.

Remplacez SOP Class UID par une valeur issue de tableau des classes de SOP standard qui désigne le type d'image stockée.

Remplacez Rows par la hauteur verticale de l'image JPEG en pixels. Remplacez Columns par la largeur horizontale de l'image JPEG en pixels.

Procédez comme suit :

  1. Enregistrez le texte suivant dans un fichier nommé instance.json en remplaçant les variables spécifiées.

    [{
     "00020010":{"vr":"UI","Value":["1.2.840.10008.1.2.4.50"]},
     "00080005":{"vr":"CS","Value":["ISO_IR 192"]},
     "00080016":{"vr":"UI","Value":["SOP_CLASS_UID"]},
     "00080018":{"vr":"UI","Value":["SOP_INSTANCE_UID"]},
     "0020000D":{"vr":"UI","Value":["STUDY_INSTANCE_UID"]},
     "0020000E":{"vr":"UI","Value":["SERIES_INSTANCE_UID"]},
     "00280002":{"vr":"US","Value":[3]},
     "00280004":{"vr":"CS","Value":["YBR_FULL_422"]},
     "00280006":{"vr":"US","Value":[0]},
     "00280008":{"vr":"IS","Value":[1]},
     "00280010":{"vr":"US","Value":[Rows]},
     "00280011":{"vr":"US","Value":[Columns]},
     "00280100":{"vr":"US","Value":[8]},
     "00280101":{"vr":"US","Value":[8]},
     "00280102":{"vr":"US","Value":[7]},
     "00280103":{"vr":"US","Value":[0]},
     "7FE00010":{"vr":"OB","BulkDataURI":"jpeg-image"}
    }]
  2. Pour créer les limites d'ouverture (pour les métadonnées JSON), centrales (pour l'image JPEG) et de fermeture, exécutez les commandes suivantes :

    echo -ne "--DICOMwebBoundary\r\nContent-Type: application/dicom+json\r\n\r\n" > opening.file
    echo -ne "\r\n--DICOMwebBoundary\r\nContent-Location: jpeg-image\r\nContent-Type: image/jpeg; transfer-syntax=1.2.840.10008.1.2.4.50\r\n\r\n" > middle.file
    echo -ne "\r\n--DICOMwebBoundary--" > closing.file
  3. Encapsulez l'image JPEG entre les limites du milieu et de la fermeture. Le fichier de sortie, que vous envoyez à l'API Cloud Healthcare, est dénommé multipart-request.file :

    cat opening.file instance.json middle.file image.jpg closing.file > multipart-request.file
  4. Envoyez une requête POST et spécifiez les informations suivantes :

    • Nom de l'ensemble de données parent
    • Le nom du magasin DICOM
    • Le fichier multipart-request.file
    • Un jeton d'accès

L'exemple suivant montre une requête POST utilisant curl.

curl -X POST \
    -H "Content-Type: multipart/related; type=\"application/dicom+json\"; boundary=DICOMwebBoundary" \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies \
    --data-binary @multipart-request.file

Si la requête aboutit, le serveur affiche la réponse au format XML :

<NativeDicomModel>
  <DicomAttribute tag="00081190" vr="UR" keyword="RetrieveURL">
    <Value number="1">https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_INSTANCE_UID</Value>
  </DicomAttribute>
  <DicomAttribute tag="00081199" vr="SQ" keyword="ReferencedSOPSequence">
    <Item number="1">
      <DicomAttribute tag="00081150" vr="UI" keyword="ReferencedSOPClassUID">
        <Value number="1">SOP_CLASS_UID</Value>
      </DicomAttribute>
      <DicomAttribute tag="00081155" vr="UI" keyword="ReferencedSOPInstanceUID">
        <Value number="1">SOP_INSTANCE_UID</Value>
      </DicomAttribute>
      <DicomAttribute tag="00081190" vr="UR" keyword="RetrieveURL">
        <Value number="1">https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_INSTANCE_UID/series/SERIES_INSTANCE_UID/instances/INSTANCE_UID</Value>
      </DicomAttribute>
    </Item>
  </DicomAttribute>
</NativeDicomModel>

Utiliser la CLI DICOMweb

Les exemples suivants montrent comment utiliser le CLI DICOMweb de l'API Cloud Healthcare pour stocker une ou plusieurs instances DICOM. D'autres exemples sont disponibles dans le dépôt GitHub de la CLI DICOMweb.

Stockage d'une seule instance DICOM :

dcmweb \
  https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb \
  store DCM_FILE

Si la requête aboutit, le serveur affiche une réponse semblable à l'exemple suivant :

TIMESTAMP -- DCM_FILE.dcm uploaded as https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_INSTANCE_UID/series/SERIES_INSTANCE_UID TIMESTAMP -- INSTANCE_UID
TIMESTAMP -- Transferred SIZE in COUNT files

Stocker plusieurs fichiers en parallèle à l'aide de caractères génériques :

L'exemple suivant montre comment stocker de manière récursive plusieurs fichiers DICOM en parallèle depuis le répertoire de travail actuel. Pour stocker les fichiers en parallèle, ajoutez l'option -m.

dcmweb -m \
  https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb \
  store "./**.dcm"

Si la requête aboutit, le serveur affiche une réponse semblable à l'exemple suivant :

TIMESTAMP -- DCM_FILE_1.dcm uploaded as https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_INSTANCE_UID/series/SERIES_INSTANCE_UID TIMESTAMP -- INSTANCE_UID
TIMESTAMP -- DCM_FILE_2.dcm uploaded as https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_INSTANCE_UID/series/SERIES_INSTANCE_UID TIMESTAMP -- INSTANCE_UID
TIMESTAMP -- DCM_FILE_3.dcm uploaded as https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_INSTANCE_UID/series/SERIES_INSTANCE_UID TIMESTAMP -- INSTANCE_UID
...
TIMESTAMP -- Transferred SIZE in COUNT files

Rechercher des données DICOM

Vous pouvez rechercher des études, des séries, des instances et des cadres. Les exemples suivants illustrent la mise en œuvre d'une transaction de recherche pour rechercher des instances dans un magasin DICOM. Pour en savoir plus, consultez la section Transaction de recherche de la déclaration de conformité DICOM de l'API Cloud Healthcare.

Les exemples suivants montrent comment rechercher des instances dans un magasin DICOM. Pour en savoir plus, consultez les sections sur projects.locations.datasets.dicomStores.searchForInstances

REST

Avant d'utiliser les données de requête ci-dessous, effectuez les remplacements suivants :

  • PROJECT_ID : ID de votre projet Google Cloud
  • LOCATION : emplacement de l'ensemble de données
  • DATASET_ID : ensemble de données parent du magasin DICOM
  • DICOM_STORE_ID : ID du store DICOM

Pour envoyer votre requête, choisissez l'une des options suivantes :

curl

Exécutez la commande suivante :

curl -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/instances"

PowerShell

Exécutez la commande suivante :

$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }

Invoke-WebRequest `
-Method GET `
-Headers $headers `
-Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/instances" | Select-Object -Expand Content

API Explorer

Ouvrez le page de référence de la méthode. Le panneau APIs Explorer s'ouvre dans la partie droite de la page. Vous pouvez interagir avec cet outil pour envoyer des requêtes. Renseignez tous les champs obligatoires, puis cliquez sur Exécuter.

Vous devriez recevoir une réponse JSON de ce type :

Go

import (
	"context"
	"fmt"
	"io"
	"io/ioutil"

	healthcare "google.golang.org/api/healthcare/v1"
)

// dicomWebSearchInstances searches instances.
func dicomWebSearchInstances(w io.Writer, projectID, location, datasetID, dicomStoreID string) error {
	// projectID := "my-project"
	// location := "us-central1"
	// datasetID := "my-dataset"
	// dicomStoreID := "my-dicom-store"
	ctx := context.Background()

	healthcareService, err := healthcare.NewService(ctx)
	if err != nil {
		return fmt.Errorf("healthcare.NewService: %w", err)
	}

	storesService := healthcareService.Projects.Locations.Datasets.DicomStores

	parent := fmt.Sprintf("projects/%s/locations/%s/datasets/%s/dicomStores/%s", projectID, location, datasetID, dicomStoreID)

	resp, err := storesService.SearchForInstances(parent, "instances").Do()
	if err != nil {
		return fmt.Errorf("SearchForInstances: %w", err)
	}

	defer resp.Body.Close()

	respBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("ioutil.ReadAll: %w", err)
	}

	if resp.StatusCode > 299 {
		return fmt.Errorf("SearchForInstances: status %d %s: %s", resp.StatusCode, resp.Status, respBytes)
	}

	respString := string(respBytes)
	fmt.Fprintf(w, "Found instances: %s\n", respString)
	return nil
}

Java

import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.healthcare.v1.CloudHealthcare;
import com.google.api.services.healthcare.v1.CloudHealthcare.Projects.Locations.Datasets.DicomStores;
import com.google.api.services.healthcare.v1.CloudHealthcareScopes;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.IOException;
import java.util.Collections;

public class DicomWebSearchForInstances {
  private static final String DICOM_NAME = "projects/%s/locations/%s/datasets/%s/dicomStores/%s";
  private static final JsonFactory JSON_FACTORY = new GsonFactory();
  private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport();

  public static void dicomWebSearchForInstances(String dicomStoreName) throws IOException {
    // String dicomStoreName =
    //    String.format(
    //        DICOM_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-dicom-id");

    // Initialize the client, which will be used to interact with the service.
    CloudHealthcare client = createClient();

    // Create request and configure any parameters.
    DicomStores.SearchForInstances request =
        client
            .projects()
            .locations()
            .datasets()
            .dicomStores()
            .searchForInstances(dicomStoreName, "instances");

    // Execute the request and process the results.
    HttpResponse response = request.executeUnparsed();
    System.out.println("Dicom store instances found: \n" + response.toString());
  }

  private static CloudHealthcare createClient() throws IOException {
    // Use Application Default Credentials (ADC) to authenticate the requests
    // For more information see https://cloud.google.com/docs/authentication/production
    GoogleCredentials credential =
        GoogleCredentials.getApplicationDefault()
            .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM));

    // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests.
    HttpRequestInitializer requestInitializer =
        request -> {
          new HttpCredentialsAdapter(credential).initialize(request);
          request.setConnectTimeout(60000); // 1 minute connect timeout
          request.setReadTimeout(60000); // 1 minute read timeout
        };

    // Build the client for interacting with the service.
    return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer)
        .setApplicationName("your-application-name")
        .build();
  }
}

Node.js

const google = require('@googleapis/healthcare');
const healthcare = google.healthcare({
  version: 'v1',
  auth: new google.auth.GoogleAuth({
    scopes: ['https://www.googleapis.com/auth/cloud-platform'],
  }),
});

const dicomWebSearchForInstances = async () => {
  // TODO(developer): uncomment these lines before running the sample
  // const cloudRegion = 'us-central1';
  // const projectId = 'adjective-noun-123';
  // const datasetId = 'my-dataset';
  // const dicomStoreId = 'my-dicom-store';
  const parent = `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/dicomStores/${dicomStoreId}`;
  const dicomWebPath = 'instances';
  const request = {parent, dicomWebPath};

  const instances =
    await healthcare.projects.locations.datasets.dicomStores.searchForInstances(
      request,
      {
        headers: {Accept: 'application/dicom+json,multipart/related'},
      }
    );
  console.log(`Found ${instances.data.length} instances:`);
  console.log(JSON.stringify(instances.data));
};

dicomWebSearchForInstances();

Python

def dicomweb_search_instance(project_id, location, dataset_id, dicom_store_id):
    """Handles the GET requests specified in DICOMweb standard.

    See https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/healthcare/api-client/v1/dicom
    before running the sample."""

    # Imports the google.auth.transport.requests transport
    from google.auth.transport import requests

    # Imports a module to allow authentication using Application Default Credentials (ADC)
    import google.auth

    # Gets credentials from the environment. google.auth.default() returns credentials and the
    # associated project ID, but in this sample, the project ID is passed in manually.
    credentials, _ = google.auth.default()

    scoped_credentials = credentials.with_scopes(
        ["https://www.googleapis.com/auth/cloud-platform"]
    )
    # Creates a requests Session object with the credentials.
    session = requests.AuthorizedSession(scoped_credentials)

    # URL to the Cloud Healthcare API endpoint and version
    base_url = "https://healthcare.googleapis.com/v1"

    # TODO(developer): Uncomment these lines and replace with your values.
    # project_id = 'my-project'  # replace with your GCP project ID
    # location = 'us-central1'  # replace with the parent dataset's location
    # dataset_id = 'my-dataset'  # replace with the parent dataset's ID
    # dicom_store_id = 'my-dicom-store' # replace with the DICOM store ID
    url = f"{base_url}/projects/{project_id}/locations/{location}"

    dicomweb_path = "{}/datasets/{}/dicomStores/{}/dicomWeb/instances".format(
        url, dataset_id, dicom_store_id
    )

    # Sets required application/dicom+json; charset=utf-8 header on the request
    headers = {"Content-Type": "application/dicom+json; charset=utf-8"}

    response = session.get(dicomweb_path, headers=headers)
    response.raise_for_status()

    instances = response.json()

    print("Instances:")
    print(json.dumps(instances, indent=2))

    return instances

Rechercher à l'aide de tags DICOM

Vous pouvez affiner vos recherches en ajoutant des tags DICOM à vos requêtes sous la forme de paramètres de requête. Par exemple, vous pouvez rechercher des études contenant le nom d'un patient.

À l'instar des exemples précédents, les exemples suivants illustrent une implémentation de la méthode Rechercher une transaction pour rechercher des études dans un magasin DICOM. Toutefois, ces exemples montrent comment rechercher des études pour lesquelles le nom du patient est "Sally Zhang".

L'exemple suivant montre une partie des métadonnées d'une instance DICOM dans laquelle le nom du patient est répertorié :

...
{
  "vr": "PN",
  "Value": [
    {
      "Alphabetic": "Sally Zhang"
    }
  ]
}
...

Pour rechercher des études dans un magasin DICOM qui concerne le patient, ajoutez un paramètre de requête lorsque vous effectuez la recherche à l'aide du tag DICOM PatientName. Pour obtenir la liste des paramètres de recherche compatibles avec l'API Cloud Healthcare, consultez la documentation sur le service Transaction de recherche.

REST

Avant d'utiliser les données de requête ci-dessous, effectuez les remplacements suivants :

  • PROJECT_ID : ID de votre projet Google Cloud
  • LOCATION : emplacement de l'ensemble de données
  • DATASET_ID : ensemble de données parent du magasin DICOM
  • DICOM_STORE_ID : ID du store DICOM

Pour envoyer votre requête, choisissez l'une des options suivantes :

curl

Exécutez la commande suivante :

curl -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies?PatientName=Sally%20Zhang"

PowerShell

Exécutez la commande suivante :

$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }

Invoke-WebRequest `
-Method GET `
-Headers $headers `
-Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies?PatientName=Sally%20Zhang" | Select-Object -Expand Content

API Explorer

Ouvrez la page de référence de la méthode. Le panneau APIs Explorer s'ouvre dans la partie droite de la page. Vous pouvez interagir avec cet outil pour envoyer des requêtes. Renseignez tous les champs obligatoires, puis cliquez sur Exécuter.

Vous devriez recevoir une réponse JSON de ce type :

Go

import (
	"context"
	"fmt"
	"io"
	"io/ioutil"

	healthcare "google.golang.org/api/healthcare/v1"
)

// queryParamOpt is a googleapi.Option (https://godoc.org/google.golang.org/api/googleapi#CallOption)
// that adds query parameters to an API call.
type queryParamOpt struct {
	key, value string
}

func (qp queryParamOpt) Get() (string, string) { return qp.key, qp.value }

// dicomWebSearchStudies refines a DICOMweb studies search by appending DICOM tags to the request.
func dicomWebSearchStudies(w io.Writer, projectID, location, datasetID, dicomStoreID, dicomWebPath string) error {
	// projectID := "my-project"
	// location := "us-central1"
	// datasetID := "my-dataset"
	// dicomStoreID := "my-dicom-store"
	// dicomWebPath := "studies"
	ctx := context.Background()

	healthcareService, err := healthcare.NewService(ctx)
	if err != nil {
		return fmt.Errorf("healthcare.NewService: %w", err)
	}

	storesService := healthcareService.Projects.Locations.Datasets.DicomStores

	name := fmt.Sprintf("projects/%s/locations/%s/datasets/%s/dicomStores/%s", projectID, location, datasetID, dicomStoreID)

	call := storesService.SearchForStudies(name, dicomWebPath)
	// Refine your search by appending DICOM tags to the
	// request in the form of query parameters. This sample
	// searches for studies containing a patient's name.
	patientName := queryParamOpt{key: "PatientName", value: "Sally Zhang"}
	resp, err := call.Do(patientName)
	if err != nil {
		return fmt.Errorf("Get: %w", err)
	}

	defer resp.Body.Close()

	respBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("ioutil.ReadAll: %w", err)
	}

	if resp.StatusCode > 299 {
		return fmt.Errorf("SearchForStudies: status %d %s: %s", resp.StatusCode, resp.Status, respBytes)
	}
	respString := string(respBytes)
	if len(respString) > 0 {
		fmt.Fprintf(w, "Found studies: %s\n", respString)
	} else {
		fmt.Println("No studies found.")
	}

	return nil
}

Java

import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.healthcare.v1.CloudHealthcare;
import com.google.api.services.healthcare.v1.CloudHealthcare.Projects.Locations.Datasets.DicomStores;
import com.google.api.services.healthcare.v1.CloudHealthcareScopes;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.IOException;
import java.util.Collections;

public class DicomWebSearchStudies {
  private static final String DICOM_NAME = "projects/%s/locations/%s/datasets/%s/dicomStores/%s";
  private static final JsonFactory JSON_FACTORY = new GsonFactory();
  private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport();

  public static void dicomWebSearchStudies(String dicomStoreName) throws IOException {
    // String dicomStoreName =
    //    String.format(
    //        DICOM_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-dicom-id");

    // Initialize the client, which will be used to interact with the service.
    CloudHealthcare client = createClient();

    DicomStores.SearchForStudies request =
        client
            .projects()
            .locations()
            .datasets()
            .dicomStores()
            .searchForStudies(dicomStoreName, "studies")
            // Refine your search by appending DICOM tags to the
            // request in the form of query parameters. This sample
            // searches for studies containing a patient's name.
            .set("PatientName", "Sally Zhang");

    // Execute the request and process the results.
    HttpResponse response = request.executeUnparsed();
    System.out.println("Studies found: \n" + response.toString());
  }

  private static CloudHealthcare createClient() throws IOException {
    // Use Application Default Credentials (ADC) to authenticate the requests
    // For more information see https://cloud.google.com/docs/authentication/production
    GoogleCredentials credential =
        GoogleCredentials.getApplicationDefault()
            .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM));

    // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests.
    HttpRequestInitializer requestInitializer =
        request -> {
          new HttpCredentialsAdapter(credential).initialize(request);
          request.setConnectTimeout(60000); // 1 minute connect timeout
          request.setReadTimeout(60000); // 1 minute read timeout
        };

    // Build the client for interacting with the service.
    return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer)
        .setApplicationName("your-application-name")
        .build();
  }
}

Node.js

const google = require('@googleapis/healthcare');
const healthcare = google.healthcare({
  version: 'v1',
  auth: new google.auth.GoogleAuth({
    scopes: ['https://www.googleapis.com/auth/cloud-platform'],
  }),
});

const dicomWebSearchStudies = async () => {
  // TODO(developer): uncomment these lines before running the sample
  // const cloudRegion = 'us-central1';
  // const projectId = 'adjective-noun-123';
  // const datasetId = 'my-dataset';
  // const dicomStoreId = 'my-dicom-store';
  const parent = `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/dicomStores/${dicomStoreId}`;
  const dicomWebPath = 'studies';
  const request = {parent, dicomWebPath};

  const studies =
    await healthcare.projects.locations.datasets.dicomStores.searchForStudies(
      request,
      {
        // Refine your search by appending DICOM tags to the
        // request in the form of query parameters. This sample
        // searches for studies containing a patient's name.
        params: {PatientName: 'Sally Zhang'},
        headers: {Accept: 'application/dicom+json'},
      }
    );
  console.log(studies);

  console.log(`Found ${studies.data.length} studies:`);
  console.log(JSON.stringify(studies.data));
};

dicomWebSearchStudies();

Python

def dicomweb_search_studies(project_id, location, dataset_id, dicom_store_id):
    """Handles the GET requests specified in the DICOMweb standard.

    See https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/healthcare/api-client/v1/dicom
    before running the sample."""

    # Imports the google.auth.transport.requests transport
    from google.auth.transport import requests

    # Imports a module to allow authentication using Application Default Credentials (ADC)
    import google.auth

    # Gets credentials from the environment. google.auth.default() returns credentials and the
    # associated project ID, but in this sample, the project ID is passed in manually.
    credentials, _ = google.auth.default()

    scoped_credentials = credentials.with_scopes(
        ["https://www.googleapis.com/auth/cloud-platform"]
    )
    # Creates a requests Session object with the credentials.
    session = requests.AuthorizedSession(scoped_credentials)

    # URL to the Cloud Healthcare API endpoint and version
    base_url = "https://healthcare.googleapis.com/v1"

    # TODO(developer): Uncomment these lines and replace with your values.
    # project_id = 'my-project'  # replace with your GCP project ID
    # location = 'us-central1'  # replace with the parent dataset's location
    # dataset_id = 'my-dataset'  # replace with the parent dataset's ID
    # dicom_store_id = 'my-dicom-store' # replace with the DICOM store ID
    url = f"{base_url}/projects/{project_id}/locations/{location}"

    dicomweb_path = "{}/datasets/{}/dicomStores/{}/dicomWeb/studies".format(
        url, dataset_id, dicom_store_id
    )

    # Refine your search by appending DICOM tags to the
    # request in the form of query parameters. This sample
    # searches for studies containing a patient's name.
    params = {"PatientName": "Sally Zhang"}

    response = session.get(dicomweb_path, params=params)

    response.raise_for_status()

    print(f"Studies found: response is {response}")

    # Uncomment the following lines to process the response as JSON.
    # patients = response.json()
    # print('Patients found matching query:')
    # print(json.dumps(patients, indent=2))

    # return patients

Utiliser la CLI DICOMweb

L'exemple suivant montre comment utiliser la classe CLI DICOMweb de l'API Cloud Healthcare pour rechercher des instances dans un magasin DICOM. D'autres exemples, y compris la manière de filtrer la recherche, sont disponibles dans le dépôt GitHub de la CLI DICOMweb.

dcmweb \
  https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb \
  search instances

Si la requête aboutit, le serveur renvoie la réponse au format JSON :

[
   {
      "00080005":{
         "vr":"CS",
         "Value":[
            "CODE_STRING"
         ]
      },
      "00080016":{
         "vr":"UI",
         "Value":[
            "UNIQUE_IDENTIFIER"
         ]
      },
      "00080018":{
         "vr":"UI",
         "Value":[
            "UNIQUE_IDENTIFIER"
         ]
      },
      "00080020":{
         "vr":"DA",
         "Value":[
            "DATE_TIME"
         ]
      },
      "00080030":{
         "vr":"TM",
         "Value":[
            "TIME"
         ]
      },
      "00080060":{
         "vr":"CS",
         "Value":[
            "CODE_STRING"
         ]
      },
      "0008103E":{
         "vr":"LO",
         "Value":[
            "LONG_STRING"
         ]
      },
      "00100010":{
         "vr":"PN",
         "Value":[
            {
               "Alphabetic":"Anonymized"
            }
         ]
      },
   },

...

]

Récupérer des données DICOM

L'API Cloud Healthcare met en œuvre l'option Récupérer la transaction. permettant de récupérer des études, des séries, des instances et des trames dans un magasin DICOM.

Pour en savoir plus, consultez la section Transaction de récupération dans la déclaration de conformité DICOM de l'API Cloud Healthcare.

Récupérer une étude

Les exemples suivants montrent comment récupérer une étude. Pour en savoir plus, consultez la section Étude/série/instances DICOM dans la déclaration de conformité DICOM de l'API Cloud Healthcare.

Lorsque vous spécifiez le fichier de sortie, utilisez une extension telle que .multipart. Analysez ensuite le fichier en plusieurs parties pour obtenir les séries et instances individuelles de l'étude.

Pour en savoir plus, consultez les sections sur projects.locations.datasets.dicomStores.studies.retrieveStudy

curl

Pour récupérer une étude, envoyez une requête GET et spécifiez les informations suivantes :

  • Nom de l'ensemble de données parent
  • Le nom du magasin DICOM
  • L'identifiant unique (UID) de l'étude
  • Un fichier de sortie
  • Un jeton d'accès

L'exemple suivant montre une requête GET utilisant curl.

curl -X GET \
     -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
     -H "Accept: multipart/related; type=application/dicom; transfer-syntax=*" \
     "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_INSTANCE_UID" \
     --output FILENAME.multipart

Si la requête aboutit, le fichier DICOM est écrit sur votre ordinateur.

PowerShell

Pour récupérer une étude, envoyez une requête GET et spécifiez les informations suivantes :

  • Nom de l'ensemble de données parent
  • Le nom du magasin DICOM
  • L'identifiant unique (UID) de l'étude
  • Un fichier de sortie
  • Un jeton d'accès

L'exemple suivant montre une requête GET utilisant Windows PowerShell.

$cred = gcloud auth application-default print-access-token
$headers = @{ Authorization = "Bearer $cred"; Accept = "multipart/related; type=application/dicom; transfer-syntax=*" }

Invoke-WebRequest `
  -Method Get `
  -Headers $headers `
  -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_INSTANCE_UID" | Select-Object -Expand Content
  -OutFile FILENAME.multipart `

Si la requête aboutit, le fichier DICOM est écrit sur votre ordinateur.

Go

import (
	"context"
	"fmt"
	"io"
	"os"

	healthcare "google.golang.org/api/healthcare/v1"
)

// dicomWebRetrieveStudy retrieves all instances in the given dicomWebPath
// study.
func dicomWebRetrieveStudy(w io.Writer, projectID, location, datasetID, dicomStoreID, dicomWebPath string, outputFile string) error {
	// projectID := "my-project"
	// location := "us-central1"
	// datasetID := "my-dataset"
	// dicomStoreID := "my-dicom-store"
	// dicomWebPath := "studies/1.3.6.1.4.1.11129.5.5.111396399857604"
	// outputFile := "study.multipart"
	ctx := context.Background()

	healthcareService, err := healthcare.NewService(ctx)
	if err != nil {
		return fmt.Errorf("healthcare.NewService: %w", err)
	}

	storesService := healthcareService.Projects.Locations.Datasets.DicomStores.Studies

	parent := fmt.Sprintf("projects/%s/locations/%s/datasets/%s/dicomStores/%s", projectID, location, datasetID, dicomStoreID)

	resp, err := storesService.RetrieveStudy(parent, dicomWebPath).Do()
	if err != nil {
		return fmt.Errorf("RetrieveStudy: %w", err)
	}

	defer resp.Body.Close()

	if resp.StatusCode > 299 {
		return fmt.Errorf("RetrieveStudy: status %d %s: %s", resp.StatusCode, resp.Status, resp.Body)
	}

	file, err := os.Create(outputFile)
	if err != nil {
		return fmt.Errorf("os.Create: %w", err)
	}
	defer file.Close()
	if _, err := io.Copy(file, resp.Body); err != nil {
		return fmt.Errorf("io.Copy: %w", err)
	}

	// When specifying the output file, use an extension like ".multipart".
	// Then, parse the downloaded multipart file to get each individual DICOM
	// file.
	fmt.Fprintf(w, "Study retrieved and downloaded to file: %v\n", outputFile)

	return nil
}

Java

import com.google.api.client.http.HttpHeaders;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.healthcare.v1.CloudHealthcare;
import com.google.api.services.healthcare.v1.CloudHealthcare.Projects.Locations.Datasets.DicomStores.Studies;
import com.google.api.services.healthcare.v1.CloudHealthcareScopes;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collections;

public class DicomWebRetrieveStudy {
  private static final String DICOM_NAME = "projects/%s/locations/%s/datasets/%s/dicomStores/%s";
  private static final JsonFactory JSON_FACTORY = new GsonFactory();
  private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport();

  public static void dicomWebRetrieveStudy(String dicomStoreName, String studyId)
      throws IOException {
    // String dicomStoreName =
    //    String.format(
    //        DICOM_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-dicom-id");
    // String studyId = "your-study-id";

    // Initialize the client, which will be used to interact with the service.
    CloudHealthcare client = createClient();

    // Create request and configure any parameters.
    Studies.RetrieveStudy request =
        client
            .projects()
            .locations()
            .datasets()
            .dicomStores()
            .studies()
            .retrieveStudy(dicomStoreName, "studies/" + studyId);

    // Execute the request and process the results.
    HttpResponse response = request.executeUnparsed();

    // When specifying the output file, use an extension like ".multipart".
    // Then, parse the downloaded multipart file to get each individual
    // DICOM file.
    String outputPath = "study.multipart";
    OutputStream outputStream = new FileOutputStream(new File(outputPath));
    try {
      response.download(outputStream);
      System.out.println("DICOM study written to file " + outputPath);
    } finally {
      outputStream.close();
    }

    if (!response.isSuccessStatusCode()) {
      System.err.print(
          String.format("Exception retrieving DICOM study: %s\n", response.getStatusMessage()));
      throw new RuntimeException();
    }
  }

  private static CloudHealthcare createClient() throws IOException {
    // Use Application Default Credentials (ADC) to authenticate the requests
    // For more information see https://cloud.google.com/docs/authentication/production
    GoogleCredentials credential =
        GoogleCredentials.getApplicationDefault()
            .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM));

    HttpHeaders headers = new HttpHeaders();
    // The response's default transfer syntax is Little Endian Explicit.
    // As a result, if the file was uploaded using a compressed transfer syntax,
    // the returned object will be decompressed. This can negatively impact performance and lead
    // to errors for transfer syntaxes that the Cloud Healthcare API doesn't support.
    // To avoid these issues, and if the returned object's transfer syntax doesn't matter to
    // your application, use the
    // multipart/related; type="application/dicom"; transfer-syntax=* Accept Header.
    headers.setAccept("multipart/related; type=application/dicom; transfer-syntax=*");
    // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests.
    HttpRequestInitializer requestInitializer =
        request -> {
          new HttpCredentialsAdapter(credential).initialize(request);
          request.setConnectTimeout(60000); // 1 minute connect timeout
          request.setReadTimeout(60000); // 1 minute read timeout
        };

    // Build the client for interacting with the service.
    return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer)
        .setApplicationName("your-application-name")
        .build();
  }
}

Node.js

const google = require('@googleapis/healthcare');
const healthcare = google.healthcare({
  version: 'v1',
  auth: new google.auth.GoogleAuth({
    scopes: ['https://www.googleapis.com/auth/cloud-platform'],
  }),
});
const fs = require('fs');
const util = require('util');
const writeFile = util.promisify(fs.writeFile);
// When specifying the output file, use an extension like ".multipart."
// Then, parse the downloaded multipart file to get each individual
// DICOM file.
const fileName = 'study_file.multipart';

const dicomWebRetrieveStudy = async () => {
  // TODO(developer): uncomment these lines before running the sample
  // const cloudRegion = 'us-central1';
  // const projectId = 'adjective-noun-123';
  // const datasetId = 'my-dataset';
  // const dicomStoreId = 'my-dicom-store';
  // const studyUid = '1.3.6.1.4.1.5062.55.1.2270943358.716200484.1363785608958.61.0';
  const parent = `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/dicomStores/${dicomStoreId}`;
  const dicomWebPath = `studies/${studyUid}`;
  const request = {parent, dicomWebPath};

  const study =
    await healthcare.projects.locations.datasets.dicomStores.studies.retrieveStudy(
      request,
      {
        headers: {
          Accept:
            'multipart/related; type=application/dicom; transfer-syntax=*',
        },
        responseType: 'arraybuffer',
      }
    );

  const fileBytes = Buffer.from(study.data);

  await writeFile(fileName, fileBytes);
  console.log(
    `Retrieved study and saved to ${fileName} in current directory`
  );
};

dicomWebRetrieveStudy();

Python

def dicomweb_retrieve_study(
    project_id, location, dataset_id, dicom_store_id, study_uid
):
    """Handles the GET requests specified in the DICOMweb standard.

    See https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/healthcare/api-client/v1/dicom
    before running the sample."""

    # Imports the google.auth.transport.requests transport
    from google.auth.transport import requests

    # Imports a module to allow authentication using Application Default Credentials (ADC)
    import google.auth

    # Gets credentials from the environment. google.auth.default() returns credentials and the
    # associated project ID, but in this sample, the project ID is passed in manually.
    credentials, _ = google.auth.default()

    scoped_credentials = credentials.with_scopes(
        ["https://www.googleapis.com/auth/cloud-platform"]
    )
    # Creates a requests Session object with the credentials.
    session = requests.AuthorizedSession(scoped_credentials)

    # URL to the Cloud Healthcare API endpoint and version
    base_url = "https://healthcare.googleapis.com/v1"

    # TODO(developer): Uncomment these lines and replace with your values.
    # project_id = 'my-project'  # replace with your GCP project ID
    # location = 'us-central1'  # replace with the parent dataset's location
    # dataset_id = 'my-dataset'  # replace with the parent dataset's ID
    # dicom_store_id = 'my-dicom-store' # replace with the DICOM store ID
    # study_uid = '1.3.6.1.4.1.5062.55.1.227'  # replace with the study UID
    url = f"{base_url}/projects/{project_id}/locations/{location}"

    dicomweb_path = "{}/datasets/{}/dicomStores/{}/dicomWeb/studies/{}".format(
        url, dataset_id, dicom_store_id, study_uid
    )

    # When specifying the output file, use an extension like ".multipart."
    # Then, parse the downloaded multipart file to get each individual
    # DICOM file.
    file_name = "study.multipart"

    response = session.get(dicomweb_path)

    response.raise_for_status()

    with open(file_name, "wb") as f:
        f.write(response.content)
        print(f"Retrieved study and saved to {file_name} in current directory")

    return response

Récupérer une instance

Les exemples suivants montrent comment récupérer une instance. Pour en savoir plus, consultez la page Instances DICOM dans la déclaration de conformité DICOM de l'API Cloud Healthcare.

Si vous récupérez une instance, vous pouvez éviter d'avoir à analyser les limites en plusieurs parties à l'aide de l'en-tête HTTP Accept: application/dicom. L'ajout de transfer-syntax=* évite le transcodage en renvoyant le fichier dans son format d'origine.

Pour en savoir plus, consultez la page projects.locations.datasets.dicomStores.studies.series.instances.retrieveInstance.

curl

Pour récupérer une instance entière, envoyez une requête GET et spécifiez les informations suivantes :

  • Nom de l'ensemble de données parent
  • Le nom du magasin DICOM
  • L'identifiant unique (UID) de l'étude
  • L'UID de la série, l'UID de l'instance
  • Un nom de fichier de sortie
  • Un jeton d'accès

L'exemple suivant montre une requête GET utilisant curl.

curl -X GET \
     -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
     -H "Accept: application/dicom; transfer-syntax=*" \
     "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_INSTANCE_UID/series/SERIES_INSTANCE_UID/instances/INSTANCE_UID" \
     --output FILENAME.dcm

Si la requête aboutit, le fichier DICOM est écrit sur votre ordinateur.

PowerShell

Pour récupérer une instance entière, envoyez une requête GET et spécifiez les informations suivantes :

  • Nom de l'ensemble de données parent
  • Le nom du magasin DICOM
  • L'identifiant unique (UID) de l'étude
  • L'UID de la série
  • L'UID de l'instance
  • Un nom de fichier de sortie
  • Un jeton d'accès

L'exemple suivant montre une requête GET utilisant Windows PowerShell.

$cred = gcloud auth application-default print-access-token
$headers = @{ Authorization = "Bearer $cred"; Accept = "application/dicom; transfer-syntax=*" }

Invoke-RestMethod `
  -Method Get `
  -Headers $headers `
  -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_INSTANCE_UID/series/SERIES_INSTANCE_UID/instances/INSTANCE_UID"
  -OutFile FILENAME.dcm `

Si la requête aboutit, le fichier DICOM est écrit sur votre ordinateur.

Go

import (
	"context"
	"fmt"
	"io"
	"os"

	healthcare "google.golang.org/api/healthcare/v1"
)

// dicomWebRetrieveInstance retrieves a specific instance.
func dicomWebRetrieveInstance(w io.Writer, projectID, location, datasetID, dicomStoreID, dicomWebPath string, outputFile string) error {
	// projectID := "my-project"
	// location := "us-central1"
	// datasetID := "my-dataset"
	// dicomStoreID := "my-dicom-store"
	// dicomWebPath := "studies/1.3.6.1.4.1.11129.5.5.1113639985/series/1.3.6.1.4.1.11129.5.5.1953511724/instances/1.3.6.1.4.1.11129.5.5.9562821369"
	// outputFile := "instance.dcm"
	ctx := context.Background()

	healthcareService, err := healthcare.NewService(ctx)
	if err != nil {
		return fmt.Errorf("healthcare.NewService: %w", err)
	}

	storesService := healthcareService.Projects.Locations.Datasets.DicomStores.Studies.Series.Instances

	parent := fmt.Sprintf("projects/%s/locations/%s/datasets/%s/dicomStores/%s", projectID, location, datasetID, dicomStoreID)

	call := storesService.RetrieveInstance(parent, dicomWebPath)
	call.Header().Set("Accept", "application/dicom; transfer-syntax=*")
	resp, err := call.Do()
	if err != nil {
		return fmt.Errorf("RetrieveInstance: %w", err)
	}

	defer resp.Body.Close()

	if resp.StatusCode > 299 {
		return fmt.Errorf("RetrieveInstance: status %d %s: %s", resp.StatusCode, resp.Status, resp.Body)
	}

	file, err := os.Create(outputFile)
	if err != nil {
		return fmt.Errorf("os.Create: %w", err)
	}
	defer file.Close()
	if _, err := io.Copy(file, resp.Body); err != nil {
		return fmt.Errorf("io.Copy: %w", err)
	}

	fmt.Fprintf(w, "DICOM instance retrieved and downloaded to file: %v\n", outputFile)

	return nil
}

Java

import com.google.api.client.http.HttpHeaders;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.healthcare.v1.CloudHealthcare;
import com.google.api.services.healthcare.v1.CloudHealthcare.Projects.Locations.Datasets.DicomStores.Studies.Series.Instances;
import com.google.api.services.healthcare.v1.CloudHealthcareScopes;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collections;

public class DicomWebRetrieveInstance {
  private static final String DICOM_NAME = "projects/%s/locations/%s/datasets/%s/dicomStores/%s";
  private static final String DICOMWEB_PATH = "studies/%s/series/%s/instances/%s";
  private static final JsonFactory JSON_FACTORY = new GsonFactory();
  private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport();

  public static void dicomWebRetrieveInstance(String dicomStoreName, String dicomWebPath)
      throws IOException {
    // String dicomStoreName =
    //    String.format(
    //        DICOM_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-dicom-id");
    // String dicomWebPath = String.format(DICOMWEB_PATH, "your-study-id", "your-series-id",
    // "your-instance-id");

    // Initialize the client, which will be used to interact with the service.
    CloudHealthcare client = createClient();

    // Create request and configure any parameters.
    Instances.RetrieveInstance request =
        client
            .projects()
            .locations()
            .datasets()
            .dicomStores()
            .studies()
            .series()
            .instances()
            .retrieveInstance(dicomStoreName, dicomWebPath);

    // Execute the request and process the results.
    HttpResponse response = request.executeUnparsed();

    String outputPath = "instance.dcm";
    OutputStream outputStream = new FileOutputStream(new File(outputPath));
    try {
      response.download(outputStream);
      System.out.println("DICOM instance written to file " + outputPath);
    } finally {
      outputStream.close();
    }

    if (!response.isSuccessStatusCode()) {
      System.err.print(
          String.format("Exception retrieving DICOM instance: %s\n", response.getStatusMessage()));
      throw new RuntimeException();
    }
  }

  private static CloudHealthcare createClient() throws IOException {
    // Use Application Default Credentials (ADC) to authenticate the requests
    // For more information see https://cloud.google.com/docs/authentication/production
    GoogleCredentials credential =
        GoogleCredentials.getApplicationDefault()
            .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM));

    HttpHeaders headers = new HttpHeaders();
    headers.set("X-GFE-SSL", "yes");
    // Avoid parsing multipart boundaries by setting 'application/dicom' HTTP header.
    // Add 'transfer-syntax=*' to avoid transcoding by returning the file in the format it
    // was originally stored in.
    headers.setAccept("application/dicom; transfer-syntax=*");
    // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests.
    HttpRequestInitializer requestInitializer =
        request -> {
          new HttpCredentialsAdapter(credential).initialize(request);
          request.setConnectTimeout(60000); // 1 minute connect timeout
          request.setReadTimeout(60000); // 1 minute read timeout
        };

    // Build the client for interacting with the service.
    return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer)
        .setApplicationName("your-application-name")
        .build();
  }
}

Node.js

const google = require('@googleapis/healthcare');
const healthcare = google.healthcare({
  version: 'v1',
  auth: new google.auth.GoogleAuth({
    scopes: ['https://www.googleapis.com/auth/cloud-platform'],
  }),
});
const fs = require('fs');
const util = require('util');
const writeFile = util.promisify(fs.writeFile);
const fileName = 'instance_file.dcm';

const dicomWebRetrieveInstance = async () => {
  // TODO(developer): uncomment these lines before running the sample
  // const cloudRegion = 'us-central1';
  // const projectId = 'adjective-noun-123';
  // const datasetId = 'my-dataset';
  // const dicomStoreId = 'my-dicom-store';
  // const studyUid = '1.3.6.1.4.1.5062.55.1.2270943358.716200484.1363785608958.61.0';
  // const seriesUid = '2.24.52329571877967561426579904912379710633';
  // const instanceUid = '1.3.6.2.4.2.14619.5.2.1.6280.6001.129311971280445372188125744148';
  const parent = `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/dicomStores/${dicomStoreId}`;
  const dicomWebPath = `studies/${studyUid}/series/${seriesUid}/instances/${instanceUid}`;
  const request = {parent, dicomWebPath};

  const instance =
    await healthcare.projects.locations.datasets.dicomStores.studies.series.instances.retrieveInstance(
      request,
      {
        headers: {Accept: 'application/dicom; transfer-syntax=*'},
        responseType: 'arraybuffer',
      }
    );
  const fileBytes = Buffer.from(instance.data);

  await writeFile(fileName, fileBytes);
  console.log(
    `Retrieved DICOM instance and saved to ${fileName} in current directory`
  );
};

dicomWebRetrieveInstance();

Python

def dicomweb_retrieve_instance(
    project_id,
    location,
    dataset_id,
    dicom_store_id,
    study_uid,
    series_uid,
    instance_uid,
):
    """Handles the GET requests specified in the DICOMweb standard.

    See https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/healthcare/api-client/v1/dicom
    before running the sample."""

    # Imports the google.auth.transport.requests transport
    from google.auth.transport import requests

    # Imports a module to allow authentication using Application Default Credentials (ADC)
    import google.auth

    # Gets credentials from the environment. google.auth.default() returns credentials and the
    # associated project ID, but in this sample, the project ID is passed in manually.
    credentials, _ = google.auth.default()

    scoped_credentials = credentials.with_scopes(
        ["https://www.googleapis.com/auth/cloud-platform"]
    )
    # Creates a requests Session object with the credentials.
    session = requests.AuthorizedSession(scoped_credentials)

    # URL to the Cloud Healthcare API endpoint and version
    base_url = "https://healthcare.googleapis.com/v1"

    # TODO(developer): Uncomment these lines and replace with your values.
    # project_id = 'my-project'  # replace with your GCP project ID
    # location = 'us-central1'  # replace with the parent dataset's location
    # dataset_id = 'my-dataset'  # replace with the parent dataset's ID
    # dicom_store_id = 'my-dicom-store' # replace with the DICOM store ID
    # study_uid = '1.3.6.1.4.1.5062.55.1.2270943358.716200484.1363785608958.61.0'  # replace with the study UID
    # series_uid = '2.24.52329571877967561426579904912379710633'  # replace with the series UID
    # instance_uid = '1.3.6.2.4.2.14619.5.2.1.6280.6001.129311971280445372188125744148'  # replace with the instance UID
    url = f"{base_url}/projects/{project_id}/locations/{location}"

    dicom_store_path = "{}/datasets/{}/dicomStores/{}".format(
        url, dataset_id, dicom_store_id
    )

    dicomweb_path = "{}/dicomWeb/studies/{}/series/{}/instances/{}".format(
        dicom_store_path, study_uid, series_uid, instance_uid
    )

    file_name = "instance.dcm"

    # Set the required Accept header on the request
    headers = {"Accept": "application/dicom; transfer-syntax=*"}
    response = session.get(dicomweb_path, headers=headers)
    response.raise_for_status()

    with open(file_name, "wb") as f:
        f.write(response.content)
        print(
            "Retrieved DICOM instance and saved to {} in current directory".format(
                file_name
            )
        )

    return response

Récupérer des formats d'image courants

Les exemples suivants montrent comment récupérer un format d'image courant tel que JPEG ou PNG à l'aide de la mise en œuvre de ressources du rendu de l'API Cloud Healthcare. Pour plus d'informations, consultez la section Ressources du rendu dans la déclaration de conformité DICOM de l'API Cloud Healthcare.

Pour en savoir plus, consultez les sections sur projects.locations.datasets.dicomStores.studies.series.instances.retrieveRendered

curl

Pour récupérer une image, envoyez une requête GET et spécifiez les informations suivantes :

  • Nom de l'ensemble de données parent
  • Le nom du magasin DICOM
  • L'identifiant unique (UID) de l'étude
  • L'UID de la série
  • L'UID de l'instance
  • Un nom de fichier de sortie
  • Un jeton d'accès

L'exemple suivant montre comment récupérer une image PNG avec une requête GET à l'aide de curl.

curl -X GET \
     -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
     -H "Accept: image/png" \
     "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_INSTANCE_UID/series/SERIES_INSTANCE_UID/instances/INSTANCE_UID/rendered" \
     --output FILENAME.png

Si la requête aboutit, le fichier PNG est écrit sur votre ordinateur.

PowerShell

Pour récupérer une image, envoyez une requête GET et spécifiez les informations suivantes :

  • Nom de l'ensemble de données parent
  • Le nom du magasin DICOM
  • L'identifiant unique (UID) de l'étude
  • L'UID de la série
  • L'UID de l'instance
  • Un nom de fichier de sortie
  • Un jeton d'accès

L'exemple suivant montre comment récupérer une image PNG avec une requête GET à l'aide de Windows PowerShell.

$cred = gcloud auth application-default print-access-token
$headers = @{ Authorization = "Bearer $cred"; Accept = "image/png" }

Invoke-RestMethod `
  -Method Get `
  -Headers $headers `
  -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_INSTANCE_UID/series/SERIES_INSTANCE_UID/instances/INSTANCE_UID/rendered"
  -OutFile FILENAME.png `

Si la requête aboutit, le fichier PNG est écrit sur votre ordinateur.

Go

import (
	"context"
	"fmt"
	"io"
	"os"

	healthcare "google.golang.org/api/healthcare/v1"
)

// dicomWebRetrieveRendered retrieves a consumer imaging format like JPEG or PNG.
func dicomWebRetrieveRendered(w io.Writer, projectID, location, datasetID, dicomStoreID, dicomWebPath string, outputFile string) error {
	// projectID := "my-project"
	// location := "us-central1"
	// datasetID := "my-dataset"
	// dicomStoreID := "my-dicom-store"
	// dicomWebPath := "studies/1.3.6.1.4.1.11129.5.5.1113639985/series/1.3.6.1.4.1.11129.5.5.1953511724/instances/1.3.6.1.4.1.11129.5.5.9562821369/rendered"
	// outputFile := "rendered_image.png"
	ctx := context.Background()

	healthcareService, err := healthcare.NewService(ctx)
	if err != nil {
		return fmt.Errorf("healthcare.NewService: %w", err)
	}

	storesService := healthcareService.Projects.Locations.Datasets.DicomStores.Studies.Series.Instances

	parent := fmt.Sprintf("projects/%s/locations/%s/datasets/%s/dicomStores/%s", projectID, location, datasetID, dicomStoreID)

	call := storesService.RetrieveRendered(parent, dicomWebPath)
	call.Header().Set("Accept", "image/png")
	resp, err := call.Do()
	if err != nil {
		return fmt.Errorf("RetrieveRendered: %w", err)
	}

	defer resp.Body.Close()

	if resp.StatusCode > 299 {
		return fmt.Errorf("RetrieveRendered: status %d %s: %s", resp.StatusCode, resp.Status, resp.Body)
	}

	file, err := os.Create(outputFile)
	if err != nil {
		return fmt.Errorf("os.Create: %w", err)
	}
	defer file.Close()
	if _, err := io.Copy(file, resp.Body); err != nil {
		return fmt.Errorf("io.Copy: %w", err)
	}

	fmt.Fprintf(w, "Rendered PNG image retrieved and downloaded to file: %v\n", outputFile)

	return nil
}

Java

import com.google.api.client.http.HttpHeaders;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.healthcare.v1.CloudHealthcare;
import com.google.api.services.healthcare.v1.CloudHealthcare.Projects.Locations.Datasets.DicomStores.Studies.Series.Instances;
import com.google.api.services.healthcare.v1.CloudHealthcareScopes;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collections;

public class DicomWebRetrieveRendered {
  private static final String DICOM_NAME = "projects/%s/locations/%s/datasets/%s/dicomStores/%s";
  private static final String DICOMWEB_PATH = "studies/%s/series/%s/instances/%s/rendered";
  private static final JsonFactory JSON_FACTORY = new GsonFactory();
  private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport();

  public static void dicomWebRetrieveRendered(String dicomStoreName, String dicomWebPath)
      throws IOException {
    // String dicomStoreName =
    //    String.format(
    //        DICOM_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-dicom-id");
    // String dicomWebPath = String.format(DICOMWEB_PATH, "your-study-id", "your-series-id",
    // "your-instance-id");

    // Initialize the client, which will be used to interact with the service.
    CloudHealthcare client = createClient();

    // Create request and configure any parameters.
    Instances.RetrieveRendered request =
        client
            .projects()
            .locations()
            .datasets()
            .dicomStores()
            .studies()
            .series()
            .instances()
            .retrieveRendered(dicomStoreName, dicomWebPath);

    // Execute the request and process the results.
    HttpResponse response = request.executeUnparsed();

    String outputPath = "image.png";
    OutputStream outputStream = new FileOutputStream(new File(outputPath));
    try {
      response.download(outputStream);
      System.out.println("DICOM rendered PNG image written to file " + outputPath);
    } finally {
      outputStream.close();
    }

    if (!response.isSuccessStatusCode()) {
      System.err.print(
          String.format(
              "Exception retrieving DICOM rendered image: %s\n", response.getStatusMessage()));
      throw new RuntimeException();
    }
  }

  private static CloudHealthcare createClient() throws IOException {
    // Use Application Default Credentials (ADC) to authenticate the requests
    // For more information see https://cloud.google.com/docs/authentication/production
    GoogleCredentials credential =
        GoogleCredentials.getApplicationDefault()
            .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM));

    HttpHeaders headers = new HttpHeaders();
    headers.set("X-GFE-SSL", "yes");
    // Retrieve using the PNG consumer imaging format.
    headers.setAccept("image/png");
    // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests.
    HttpRequestInitializer requestInitializer =
        request -> {
          new HttpCredentialsAdapter(credential).initialize(request);
          request.setConnectTimeout(60000); // 1 minute connect timeout
          request.setReadTimeout(60000); // 1 minute read timeout
        };

    // Build the client for interacting with the service.
    return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer)
        .setApplicationName("your-application-name")
        .build();
  }
}

Node.js

const google = require('@googleapis/healthcare');
const healthcare = google.healthcare({
  version: 'v1',
  auth: new google.auth.GoogleAuth({
    scopes: ['https://www.googleapis.com/auth/cloud-platform'],
  }),
});
const fs = require('fs');
const util = require('util');
const writeFile = util.promisify(fs.writeFile);
const fileName = 'rendered_image.png';

const dicomWebRetrieveRendered = async () => {
  // TODO(developer): uncomment these lines before running the sample
  // const cloudRegion = 'us-central1';
  // const projectId = 'adjective-noun-123';
  // const datasetId = 'my-dataset';
  // const dicomStoreId = 'my-dicom-store';
  // const studyUid = '1.3.6.1.4.1.5062.55.1.2270943358.716200484.1363785608958.61.0';
  // const seriesUid = '2.24.52329571877967561426579904912379710633';
  // const instanceUid = '1.3.6.2.4.2.14619.5.2.1.6280.6001.129311971280445372188125744148';
  const parent = `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/dicomStores/${dicomStoreId}`;
  const dicomWebPath = `studies/${studyUid}/series/${seriesUid}/instances/${instanceUid}/rendered`;
  const request = {parent, dicomWebPath};

  const rendered =
    await healthcare.projects.locations.datasets.dicomStores.studies.series.instances.retrieveRendered(
      request,
      {
        headers: {Accept: 'image/png'},
        responseType: 'arraybuffer',
      }
    );
  const fileBytes = Buffer.from(rendered.data);

  await writeFile(fileName, fileBytes);
  console.log(
    `Retrieved rendered image and saved to ${fileName} in current directory`
  );
};

dicomWebRetrieveRendered();

Python

def dicomweb_retrieve_rendered(
    project_id,
    location,
    dataset_id,
    dicom_store_id,
    study_uid,
    series_uid,
    instance_uid,
):
    """Handles the GET requests specified in the DICOMweb standard.

    See https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/healthcare/api-client/v1/dicom
    before running the sample."""

    # Imports the google.auth.transport.requests transport
    from google.auth.transport import requests

    # Imports a module to allow authentication using Application Default Credentials (ADC)
    import google.auth

    # Gets credentials from the environment. google.auth.default() returns credentials and the
    # associated project ID, but in this sample, the project ID is passed in manually.
    credentials, _ = google.auth.default()

    scoped_credentials = credentials.with_scopes(
        ["https://www.googleapis.com/auth/cloud-platform"]
    )
    # Creates a requests Session object with the credentials.
    session = requests.AuthorizedSession(scoped_credentials)

    # URL to the Cloud Healthcare API endpoint and version
    base_url = "https://healthcare.googleapis.com/v1"

    # TODO(developer): Uncomment these lines and replace with your values.
    # project_id = 'my-project'  # replace with your GCP project ID
    # location = 'us-central1'  # replace with the parent dataset's location
    # dataset_id = 'my-dataset'  # replace with the parent dataset's ID
    # dicom_store_id = 'my-dicom-store' # replace with the DICOM store ID
    # study_uid = '1.3.6.1.4.1.5062.55.1.2270943358.716200484.1363785608958.61.0'  # replace with the study UID
    # series_uid = '2.24.52329571877967561426579904912379710633'  # replace with the series UID
    # instance_uid = '1.3.6.2.4.2.14619.5.2.1.6280.6001.129311971280445372188125744148'  # replace with the instance UID
    url = f"{base_url}/projects/{project_id}/locations/{location}"

    dicom_store_path = "{}/datasets/{}/dicomStores/{}".format(
        url, dataset_id, dicom_store_id
    )

    dicomweb_path = "{}/dicomWeb/studies/{}/series/{}/instances/{}/rendered".format(
        dicom_store_path, study_uid, series_uid, instance_uid
    )

    file_name = "rendered_image.png"

    # Sets the required Accept header on the request for a PNG image
    headers = {"Accept": "image/png"}
    response = session.get(dicomweb_path, headers=headers)
    response.raise_for_status()

    with open(file_name, "wb") as f:
        f.write(response.content)
        print(
            "Retrieved rendered image and saved to {} in current directory".format(
                file_name
            )
        )

    return response

Récupérer les métadonnées

Vous pouvez récupérer les métadonnées de toutes les instances d'une étude ou d'une série. L'exemple suivant montre comment récupérer les métadonnées d'une instance. Pour en savoir plus, consultez la section Ressources de métadonnées dans la déclaration de conformité de l'API Cloud Healthcare.

Pour en savoir plus, consultez la page projects.locations.datasets.dicomStores.studies.series.instances.retrieveMetadata.

Lorsque vous appelez retrieveMetadata, la méthode renvoie le même ensemble de champs que ceux qui sont renvoyés lorsque vous recherchez une instance avec le paramètre de requête includefield=all. Si votre application est sensible à la latence et que vous souhaitez récupérer les métadonnées d'un ensemble spécifique de champs (et non de tous les champs), n'appelez pas retrieveMetadata. Appelez plutôt l'une des méthodes searchForInstances et spécifiez les champs. La réponse sera un ensemble de champs plus petits et un plus petit ensemble, ce qui facilite les opérations pour les applications sensibles à la latence.

Par défaut, retrieveMetadata renvoie une réponse JSON. Pour renvoyer une réponse XML, transmettez un en-tête HTTP Accept: multipart/related; type="application/dicom+xml" dans votre requête.

REST

Avant d'utiliser les données de requête ci-dessous, effectuez les remplacements suivants :

  • PROJECT_ID : ID de votre projet Google Cloud
  • LOCATION : emplacement de l'ensemble de données
  • DATASET_ID : ensemble de données parent du magasin DICOM
  • DICOM_STORE_ID : ID du magasin DICOM
  • STUDY_INSTANCE_UID: identifiant unique de l'instance d'étude
  • SERIES_INSTANCE_UID: identifiant unique de l'instance de la série
  • INSTANCE_UID : identifiant unique de l'instance

Pour envoyer votre requête, choisissez l'une des options suivantes :

curl

Exécutez la commande suivante :

curl -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_INSTANCE_UID/series/SERIES_INSTANCE_UID/instances/INSTANCE_UID/metadata"

PowerShell

Exécutez la commande suivante :

$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }

Invoke-WebRequest `
-Method GET `
-Headers $headers `
-Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_INSTANCE_UID/series/SERIES_INSTANCE_UID/instances/INSTANCE_UID/metadata" | Select-Object -Expand Content

API Explorer

Ouvrez la page de référence de la méthode. Le panneau APIs Explorer s'ouvre dans la partie droite de la page. Vous pouvez interagir avec cet outil pour envoyer des requêtes. Renseignez tous les champs obligatoires, puis cliquez sur Exécuter.

Vous devriez recevoir une réponse JSON de ce type :

Récupérer les données groupées

Vous pouvez récupérer les octets bruts d'une balise bulkdata spécifique dans une instance stockée. Lors de la récupération de métadonnées à partir d'une instance à l'aide de méthodes d'aperçu, BulkDataURIs seront générées pour les balises de données groupées acceptées (voir Définition des données groupées).

Pour en savoir plus, consultez la page projects.locations.datasets.dicomStores.studies.series.instances.bulkdata.retrieveBulkdata.

Dans l'exemple suivant, l'URL de requête est créée directement en fonction du nom chemin d'accès d'un tag Bulkdata (sans utiliser retrieveMetadata pour obtenir le BulkDataURI).

curl

Pour récupérer des données en masse, envoyez une requête GET et spécifiez les informations suivantes:

  • Nom de l'ensemble de données parent
  • Le nom du magasin DICOM
  • L'identifiant unique (UID) de l'étude
  • L'UID de la série
  • L'UID de l'instance
  • Chemin d'accès de la balise de données groupées cible
    • Pour une balise (XXXX,XXXX) dans une séquence (YYYY,YYYY) à l'indice i, le chemin d'accès est "YYYYYYYY/i/XXXXXXXX".
  • Un nom de fichier de sortie
  • Un jeton d'accès

L'exemple suivant montre comment récupérer un fichier DAT avec une requête GET à l'aide de curl.

curl -X GET \
     -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
     -H "Accept: application/octet-stream; transfer-syntax=*" \
     "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_INSTANCE_UID/series/SERIES_INSTANCE_UID/instances/INSTANCE_UID/bulkdata/BULKDATA_PATH" \
     --output FILENAME.dat

Si la requête aboutit, le fichier DAT contenant les octets bruts de l'instance est écrit sur votre ordinateur.

PowerShell

Pour récupérer des données en masse, envoyez une requête GET et spécifiez les informations suivantes:

  • Nom de l'ensemble de données parent
  • Le nom du magasin DICOM
  • L'identifiant unique (UID) de l'étude
  • L'UID de la série
  • L'UID de l'instance
  • Chemin d'accès de la balise de données groupées cible
    • Pour une balise (XXXX,XXXX) dans une séquence (YYYY,YYYY) à l'indice i, le chemin d'accès est "YYYYYYYY/i/XXXXXXXX".
  • Un nom de fichier de sortie
  • Un jeton d'accès

L'exemple suivant montre comment récupérer un fichier DAT avec une requête GET à l'aide de Windows PowerShell.

$cred = gcloud auth application-default print-access-token
$headers = @{ Authorization = "Bearer $cred"; Accept = "application/octet-stream; transfer-syntax=*" }

Invoke-RestMethod `
  -Method Get `
  -Headers $headers `
  -Uri "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_INSTANCE_UID/series/SERIES_INSTANCE_UID/instances/INSTANCE_UID/bulkdata/BULKDATA_PATH"
  -OutFile FILENAME.DAT `

Si la requête aboutit, le fichier DAT contenant les octets bruts du est écrite sur votre machine.

Utiliser la CLI DICOMweb

L'exemple suivant montre comment utiliser la CLIweb de l'API Cloud Healthcare pour récupérer toutes les instances d'un magasin DICOM et les enregistrer sur votre ordinateur dans le répertoire de travail actuel. D'autres exemples sont disponibles dans le dépôt GitHub de la CLI DICOMweb.

dcmweb \
  https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb \
  retrieve

Si la requête aboutit, le serveur renvoie une réponse semblable à la suivante et les fichiers DICOM sont écrits sur votre ordinateur :

TIMESTAMP -- Saving files into ./
TIMESTAMP -- Transferred SIZE in COUNT files

Supprimer une étude, une série ou une instance

L'API Cloud Healthcare met en œuvre un service Web propriétaire pour la suppression d'études, de séries et d'instances DICOM. Ce service ne fait pas partie des services standards de DICOMweb. Pour en savoir plus, consultez la section Supprimer dans la déclaration de conformité DICOM de l'API Cloud Healthcare.

Les requêtes de suppression des études et des séries renvoient une opération de longue durée. Une fois l'opération terminée, toutes les instances de l'étude ou de la série sont supprimées.

Les requêtes de suppression pour les instances ne renvoient pas d'opération de longue durée, mais renvoient un corps de réponse vide comme celui-ci :

{}

Les exemples suivants montrent comment supprimer une étude DICOM. Pour en savoir plus, consultez la page projects.locations.datasets.dicomStores.studies.delete.

REST

  1. Supprimez l'étude.

    Avant d'utiliser les données de requête ci-dessous, effectuez les remplacements suivants :

    • PROJECT_ID : ID de votre projet Google Cloud
    • LOCATION : emplacement de l'ensemble de données
    • DATASET_ID : ensemble de données parent du magasin DICOM
    • DICOM_STORE_ID : ID du magasin DICOM
    • STUDY_INSTANCE_UID: identifiant unique de l'instance d'étude

    Pour envoyer votre requête, choisissez l'une des options suivantes :

    curl

    Exécutez la commande suivante :

    curl -X DELETE \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_INSTANCE_UID"

    PowerShell

    Exécutez la commande suivante :

    $cred = gcloud auth print-access-token
    $headers = @{ "Authorization" = "Bearer $cred" }

    Invoke-WebRequest `
    -Method DELETE `
    -Headers $headers `
    -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_INSTANCE_UID" | Select-Object -Expand Content

    API Explorer

    Ouvrez le page de référence de la méthode. Le panneau APIs Explorer s'ouvre dans la partie droite de la page. Vous pouvez interagir avec cet outil pour envoyer des requêtes. Renseignez tous les champs obligatoires, puis cliquez sur Exécuter.

    Vous devriez recevoir une réponse JSON de ce type :

  2. Obtenez l'état de l'opération de longue durée.

    Avant d'utiliser les données de requête ci-dessous, effectuez les remplacements suivants :

    • PROJECT_ID : ID de votre projet Google Cloud
    • LOCATION : emplacement de l'ensemble de données
    • DATASET_ID : ensemble de données parent du magasin DICOM
    • OPERATION_ID : ID renvoyé par l'opération de longue durée

    Pour envoyer votre requête, choisissez l'une des options suivantes :

    curl

    Exécutez la commande suivante :

    curl -X GET \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"

    PowerShell

    Exécutez la commande suivante :

    $cred = gcloud auth print-access-token
    $headers = @{ "Authorization" = "Bearer $cred" }

    Invoke-WebRequest `
    -Method GET `
    -Headers $headers `
    -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID" | Select-Object -Expand Content

    API Explorer

    Ouvrez le page de référence de la méthode. Le panneau APIs Explorer s'ouvre dans la partie droite de la page. Vous pouvez interagir avec cet outil pour envoyer des requêtes. Renseignez tous les champs obligatoires, puis cliquez sur Exécuter.

    Vous devriez recevoir une réponse JSON de ce type :

Go

import (
	"context"
	"fmt"
	"io"

	healthcare "google.golang.org/api/healthcare/v1"
)

// dicomWebDeleteStudy deletes all instances in the given dicomWebPath study.
func dicomWebDeleteStudy(w io.Writer, projectID, location, datasetID, dicomStoreID, dicomWebPath string) error {
	ctx := context.Background()

	healthcareService, err := healthcare.NewService(ctx)
	if err != nil {
		return fmt.Errorf("healthcare.NewService: %w", err)
	}

	storesService := healthcareService.Projects.Locations.Datasets.DicomStores.Studies

	parent := fmt.Sprintf("projects/%s/locations/%s/datasets/%s/dicomStores/%s", projectID, location, datasetID, dicomStoreID)

	if _, err := storesService.Delete(parent, dicomWebPath).Do(); err != nil {
		return fmt.Errorf("Delete: %w", err)
	}

	fmt.Fprintf(w, "Deleted %q\n", dicomWebPath)
	return nil
}

Java

import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.healthcare.v1.CloudHealthcare;
import com.google.api.services.healthcare.v1.CloudHealthcare.Projects.Locations.Datasets.DicomStores.Studies;
import com.google.api.services.healthcare.v1.CloudHealthcareScopes;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.IOException;
import java.util.Collections;

public class DicomWebDeleteStudy {
  private static final String DICOM_NAME = "projects/%s/locations/%s/datasets/%s/dicomStores/%s";
  private static final JsonFactory JSON_FACTORY = new GsonFactory();
  private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport();

  public static void dicomWebDeleteStudy(String dicomStoreName, String studyId) throws IOException {
    // String dicomStoreName =
    //    String.format(
    //        DICOM_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-dicom-id");
    // String studyId = "your-study-id";

    // Initialize the client, which will be used to interact with the service.
    CloudHealthcare client = createClient();

    // Create request and configure any parameters.
    Studies.Delete request =
        client
            .projects()
            .locations()
            .datasets()
            .dicomStores()
            .studies()
            .delete(dicomStoreName, "studies/" + studyId);

    // Execute the request and process the results.
    request.execute();
    System.out.println("DICOM study deleted.");
  }

  private static CloudHealthcare createClient() throws IOException {
    // Use Application Default Credentials (ADC) to authenticate the requests
    // For more information see https://cloud.google.com/docs/authentication/production
    GoogleCredentials credential =
        GoogleCredentials.getApplicationDefault()
            .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM));

    // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests.
    HttpRequestInitializer requestInitializer =
        request -> {
          new HttpCredentialsAdapter(credential).initialize(request);
          request.setConnectTimeout(60000); // 1 minute connect timeout
          request.setReadTimeout(60000); // 1 minute read timeout
        };

    // Build the client for interacting with the service.
    return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer)
        .setApplicationName("your-application-name")
        .build();
  }
}

Node.js

const google = require('@googleapis/healthcare');
const healthcare = google.healthcare({
  version: 'v1',
  auth: new google.auth.GoogleAuth({
    scopes: ['https://www.googleapis.com/auth/cloud-platform'],
  }),
});

const dicomWebDeleteStudy = async () => {
  // TODO(developer): uncomment these lines before running the sample
  // const cloudRegion = 'us-central1';
  // const projectId = 'adjective-noun-123';
  // const datasetId = 'my-dataset';
  // const dicomStoreId = 'my-dicom-store';
  // const studyUid = '1.3.6.1.4.1.5062.55.1.2270943358.716200484.1363785608958.61.0';
  const parent = `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/dicomStores/${dicomStoreId}`;
  const dicomWebPath = `studies/${studyUid}`;
  const request = {parent, dicomWebPath};

  await healthcare.projects.locations.datasets.dicomStores.studies.delete(
    request
  );
  console.log('Deleted DICOM study');
};

dicomWebDeleteStudy();

Python

def dicomweb_delete_study(project_id, location, dataset_id, dicom_store_id, study_uid):
    """Handles DELETE requests equivalent to the GET requests specified in
    the WADO-RS standard.

    See https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/healthcare/api-client/v1/dicom
    before running the sample."""

    # Imports the google.auth.transport.requests transport
    from google.auth.transport import requests

    # Imports a module to allow authentication using Application Default Credentials (ADC)
    import google.auth

    # Gets credentials from the environment. google.auth.default() returns credentials and the
    # associated project ID, but in this sample, the project ID is passed in manually.
    credentials, _ = google.auth.default()

    scoped_credentials = credentials.with_scopes(
        ["https://www.googleapis.com/auth/cloud-platform"]
    )
    # Creates a requests Session object with the credentials.
    session = requests.AuthorizedSession(scoped_credentials)

    # URL to the Cloud Healthcare API endpoint and version
    base_url = "https://healthcare.googleapis.com/v1"

    # TODO(developer): Uncomment these lines and replace with your values.
    # project_id = 'my-project'  # replace with your GCP project ID
    # location = 'us-central1'  # replace with the parent dataset's location
    # dataset_id = 'my-dataset'  # replace with the parent dataset's ID
    # dicom_store_id = 'my-dicom-store' # replace with the DICOM store ID
    # study_uid = '1.3.6.1.4.1.5062.55.1.2270943358.716200484.1363785608958.61.0'  # replace with the study UID
    url = f"{base_url}/projects/{project_id}/locations/{location}"

    dicomweb_path = "{}/datasets/{}/dicomStores/{}/dicomWeb/studies/{}".format(
        url, dataset_id, dicom_store_id, study_uid
    )

    # Sets the required application/dicom+json; charset=utf-8 header on the request
    headers = {"Content-Type": "application/dicom+json; charset=utf-8"}

    response = session.delete(dicomweb_path, headers=headers)
    response.raise_for_status()

    print("Deleted study.")

    return response

Utiliser la CLI DICOMweb

L'exemple suivant montre comment utiliser la classe CLI DICOMweb de l'API Cloud Healthcare pour supprimer une étude:

dcmweb \
    https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb \
   delete studies/STUDY_INSTANCE_UID

Si la requête aboutit, le serveur affiche une opération que l'outil CLI interroge jusqu'à la fin de l'opération de suppression.