Usar el estándar DICOMweb

En esta página se explica cómo usar la implementación de DICOMweb de la API Cloud Healthcare para almacenar y gestionar datos de imágenes DICOM.

Para obtener más información sobre cómo implementa la API Cloud Healthcare varios servicios REST DICOMweb, consulta la declaración de conformidad de DICOM.

La implementación de DICOMweb en la API Cloud Healthcare solo admite REST, no RPC.

Instalar la CLI de DICOMweb de la API Cloud Healthcare

En varias de las muestras de esta página se usa la CLI DICOMweb de la API Cloud Healthcare, una herramienta de código abierto que simplifica la interacción con los servidores DICOMweb. La herramienta ofrece funciones para almacenar, recuperar, eliminar y buscar archivos DICOM. En la página de GitHub de la herramienta se incluye más información, como los requisitos de instalación detallados y las formas de personalizarla.

La herramienta se ejecuta con Python. Para obtener información sobre cómo configurar Python en Google Cloud, consulta el artículo Configurar un entorno de desarrollo de Python.

Después de configurar Python, puedes instalar la herramienta con Pip:

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

Para usar la herramienta, debes autenticarte en los servidores de Google Cloud . Para ello, puedes usar uno de los siguientes métodos:

Después de configurar cualquiera de estas opciones, la herramienta detecta automáticamente tus credenciales.

Almacenar datos DICOM

Para poder almacenar datos DICOM, antes debes crear un almacén DICOM.

La API Cloud Healthcare implementa el servicio web RESTful Store transaction al almacenar datos DICOM. Para obtener más información, consulta Transacción de almacenamiento en la declaración de conformidad de DICOM de la API Cloud Healthcare.

Almacena datos DICOM con uno de los siguientes métodos. Incluye el encabezado application/dicom Accept en tu solicitud.

  • Almacenar una instancia DICOM: normalmente un archivo .dcm.
  • Almacenar varios elementos mediante un mensaje de varias partes: crea un archivo de varias partes con varias partes de datos separadas por un límite. En tu solicitud, asigna el valor multipart/related; type=application/dicom; boundary=BOUNDARY a Content-Type, donde BOUNDARY es un valor definido por el usuario que indica las diferentes partes del mensaje. Consulta el RFC 1341 para obtener información sobre cómo crear mensajes de varias partes.

    Usa mensajes de varias partes para almacenar los siguientes tipos de datos DICOM:

Los valores SOP_CLASS_UID, SOP_INSTANCE_UID, STUDY_INSTANCE_UID y SERIES_INSTANCE_UID se rellenan con los metadatos proporcionados. Los UIDs deben cumplir estos requisitos:

  • Contener solo valores numéricos separados por puntos.
  • No deben contener información médica protegida (PHI).

En los siguientes ejemplos se muestra cómo almacenar una instancia en un almacén DICOM. Para obtener más información, consulta projects.locations.datasets.dicomStores.storeInstances.

Almacenar una instancia DICOM

En los siguientes ejemplos se muestra cómo almacenar una instancia DICOM. Para obtener más información, consulta projects.locations.datasets.dicomStores.storeInstances.

REST

Antes de usar los datos de la solicitud, haz las siguientes sustituciones:

  • PROJECT_ID: el ID de tu Google Cloud proyecto
  • LOCATION: la ubicación del conjunto de datos
  • DATASET_ID: el conjunto de datos superior del almacén DICOM
  • DICOM_STORE_ID: el ID del almacén DICOM
  • DICOM_INSTANCE_FILE: la ruta a un archivo de instancia DICOM en tu máquina local que termina con el sufijo .dcm

Para enviar tu solicitud, elige una de estas opciones:

curl

Ejecuta el comando siguiente:

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

Ejecuta el comando siguiente:

$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
El resultado es la siguiente respuesta XML:

Go

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

	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 := os.ReadFile(dicomFile)
	if err != nil {
		return fmt.Errorf("os.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 := io.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

Almacenar un estudio o una serie DICOM mediante un mensaje de varias partes

En los siguientes ejemplos se muestra cómo almacenar un estudio o una serie DICOM, que consta de varias instancias, mediante un mensaje de varias partes.

REST

Antes de usar los datos de la solicitud, haz las siguientes sustituciones:

  • PROJECT_ID: el ID de tu Google Cloud proyecto
  • LOCATION: la ubicación del conjunto de datos
  • DATASET_ID: el conjunto de datos superior del almacén DICOM
  • DICOM_STORE_ID: el ID del almacén DICOM
  • MULTIPART_FILE: la ruta a un archivo de varias partes en tu máquina local. El archivo contiene varias instancias DICOM, cada una separada por un límite.
  • BOUNDARY: el límite que se usa para separar las instancias DICOM en el archivo de varias partes

Para enviar tu solicitud, elige una de estas opciones:

curl

Ejecuta el comando siguiente:

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

PowerShell

Ejecuta el comando siguiente:

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

Invoke-WebRequest `
-Method POST `
-Headers $headers `
-InFile MULTIPART_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
El resultado es similar al siguiente, con varias instancias devueltas:

Especificar una clase de almacenamiento para instancias DICOM

De forma predeterminada, el método projects.locations.datasets.dicomStores.storeInstances almacena una instancia DICOM en un almacén DICOM con una clase de almacenamiento estándar. Puedes definir la clase de almacenamiento cuando almacenes objetos DICOM desde tu máquina local. Para obtener más información, consulta Cambiar la clase de almacenamiento de DICOM.

En los siguientes ejemplos se muestra cómo especificar la clase de almacenamiento al almacenar objetos DICOM desde tu máquina local.

curl

Usa el método projects.locations.datasets.dicomStores.storeInstances. Antes de usar los datos de la solicitud, haz las siguientes sustituciones:

  • PROJECT_ID: el ID de tu Google Cloud proyecto
  • LOCATION: la ubicación del conjunto de datos
  • DATASET_ID: el conjunto de datos superior del almacén DICOM
  • DICOM_STORE_ID: el ID del almacén DICOM
  • DICOM_INSTANCE_FILE: la ruta a un archivo de instancia DICOM en tu máquina local que termina con el sufijo .dcm
  • STORAGE_CLASS: la clase de almacenamiento de la instancia DICOM en el almacén DICOM de STANDARD, NEARLINE, COLDLINE y 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 solicitud se realiza correctamente, el servidor devuelve la respuesta:

<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

Usa el método projects.locations.datasets.dicomStores.storeInstances.

Antes de usar los datos de la solicitud, haz las siguientes sustituciones:

  • PROJECT_ID: el ID de tu Google Cloud proyecto
  • LOCATION: la ubicación del conjunto de datos
  • DATASET_ID: el conjunto de datos superior del almacén DICOM
  • DICOM_STORE_ID: el ID del almacén DICOM
  • DICOM_INSTANCE_FILE: la ruta a un archivo de instancia DICOM en tu máquina local que termina con el sufijo .dcm
  • STORAGE_CLASS: la clase de almacenamiento de la instancia DICOM en el almacén DICOM de STANDARD, NEARLINE, COLDLINE y 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 solicitud se realiza de forma correcta, el servidor devuelve la respuesta en formato 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>

Crear instancias DICOM a partir de metadatos JSON e imágenes JPEG

La API Cloud Healthcare puede crear instancias DICOM utilizando un archivo de metadatos JSON y un archivo JPEG. Crea instancias DICOM a partir de metadatos JSON y archivos JPEG si no quieres encargarte del análisis y la serialización de DICOM, ya que la API Cloud Healthcare puede hacerlo por ti.

La solicitud HTTP que almacena estos datos debe incluir lo siguiente en el Content-Type de la solicitud:

  • Tipo de contenido multipart/related
  • El tipo MIME application/dicom+json
  • Un separador boundary

En los siguientes ejemplos se muestra cómo almacenar un archivo de metadatos JSON con un archivo JPEG.

curl

En el siguiente ejemplo se da por hecho que ya tienes una imagen JPEG.

El almacenamiento de un archivo de metadatos JSON con una imagen JPEG comprende tres pasos:

  1. Crear un archivo que contenga una representación JSON de una instancia DICOM que incluya una imagen JPEG. Más abajo se proporciona un archivo de plantilla.
  2. Crear tres archivos de límites:

    • opening.file: incluye el límite de apertura para el archivo de metadatos JSON.
    • middle.file: incluye el límite intermedio para la imagen JPEG.
    • closing.file: incluye el límite de cierre para todas las partes del mensaje.
  3. Crea un archivo llamado multipart-request.file encapsulando el archivo de metadatos JSON y la imagen JPEG en los archivos de límite.

El archivo de plantilla de metadatos JSON proporciona los siguientes valores de forma predeterminada:

  • El UID de sintaxis de transferencia (1.2.840.10008.1.2.4.50) designa la sintaxis de transferencia como la referencia JPEG. La mayoría de las imágenes JPEG están en el formato de referencia JPEG. El valor de interpretación fotométrica (YBR_FULL_422) significa que la imagen está en color, no en una escala de grises.
  • BulkDataUri es un descriptor arbitrario para la imagen, y en la plantilla está definido como jpeg-image. Este valor se utiliza al crear el límite de la imagen.

Los valores de SOP_CLASS_UID, SOP_INSTANCE_UID, STUDY_INSTANCE_UID y SERIES_INSTANCE_UID pueden ser cualquier valor numérico separado por puntos. Como DICOM utiliza una jerarquía de identificadores para instancias, pacientes, estudios y series, debes elegir un conjunto lógico de identificadores para estas variables.

Sustituye SOP Class UID por un valor de la tabla de clases SOP estándar que designe el tipo de imagen que se está almacenando.

Sustituye Rows por la altura vertical de la imagen JPEG en píxeles. Sustituye Columns por la anchura horizontal de la imagen JPEG en píxeles.

Este agente debe seguir estos pasos:

  1. Guarda el siguiente texto en un archivo denominado instance.json y sustituye las variables según lo especificado.

    [{
     "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. Para crear los límites de apertura (para los metadatos JSON), intermedio (para la imagen JPEG) y de cierre, ejecuta los siguientes comandos:

    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. Encapsula la imagen JPEG entre los límites intermedio y de cierre. El archivo de salida, que será el que envíes a la API Cloud Healthcare, se denomina multipart-request.file:

    cat opening.file instance.json middle.file image.jpg closing.file > multipart-request.file
  4. Haz una POST solicitud y especifica la siguiente información:

    • Nombre del conjunto de datos principal
    • Nombre del almacén DICOM
    • El archivo multipart-request.file
    • Un token de acceso

En el siguiente ejemplo se muestra una solicitud POST que utiliza 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 solicitud se realiza de forma correcta, el servidor devuelve la respuesta en formato 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>

Usar la CLI de DICOMweb

En los siguientes ejemplos se muestra cómo usar la CLI DICOMweb de la API Cloud Healthcare para almacenar una o varias instancias DICOM. Hay más ejemplos disponibles en el repositorio de GitHub de la CLI de DICOMweb.

Almacenar una sola instancia 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 solicitud se realiza correctamente, el servidor devuelve una respuesta similar a la siguiente:

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

Almacenar varios archivos en paralelo mediante comodines:

En el siguiente ejemplo se muestra cómo almacenar de forma recursiva varios archivos DICOM en paralelo desde el directorio de trabajo actual. Para almacenar los archivos en paralelo, añade la marca -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 solicitud se realiza correctamente, el servidor devuelve una respuesta similar a la siguiente:

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

Buscar datos DICOM

Puedes buscar estudios, series, instancias y marcos. En los siguientes ejemplos se muestra una implementación de la transacción de búsqueda para buscar instancias en un almacén DICOM. Para obtener más información, consulta Transacción de búsqueda en la declaración de conformidad de DICOM de la API Cloud Healthcare.

En los siguientes ejemplos se muestra cómo buscar instancias en un almacén DICOM. Para obtener más información, consulta projects.locations.datasets.dicomStores.searchForInstances.

REST

Antes de usar los datos de la solicitud, haz las siguientes sustituciones:

  • PROJECT_ID: el ID de tu Google Cloud proyecto
  • LOCATION: la ubicación del conjunto de datos
  • DATASET_ID: el conjunto de datos superior del almacén DICOM
  • DICOM_STORE_ID: el ID del almacén DICOM

Para enviar tu solicitud, elige una de estas opciones:

curl

Ejecuta el comando siguiente:

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

Ejecuta el comando siguiente:

$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

Explorador de APIs

Abre la página de referencia del método. El panel Explorador de APIs se abre en la parte derecha de la página. Puedes interactuar con esta herramienta para enviar solicitudes. Rellena los campos obligatorios y haz clic en Ejecutar.

Deberías recibir una respuesta JSON similar a la siguiente:

Go

import (
	"context"
	"fmt"
	"io"

	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 := io.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

Buscar usando etiquetas DICOM

Puede acotar sus búsquedas añadiendo etiquetas DICOM a sus solicitudes en forma de parámetros de consulta. Por ejemplo, puede que quieras buscar estudios que contengan el nombre de un paciente.

Al igual que en los ejemplos anteriores, en los siguientes se muestra una implementación de la transacción de búsqueda para buscar estudios en un almacén DICOM. Sin embargo, en estos ejemplos se muestra cómo buscar estudios en los que el nombre del paciente sea "Sally Zhang".

En el siguiente ejemplo se muestra una parte de los metadatos de una instancia DICOM en la que se indica el nombre del paciente:

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

Para buscar estudios de un almacén DICOM que pertenezcan a un paciente, añade un parámetro de consulta a tu solicitud en el que busques por la etiqueta DICOM PatientName. Para ver una lista de los parámetros de búsqueda admitidos en la API Cloud Healthcare, consulta la documentación sobre la búsqueda de transacciones.

REST

Antes de usar los datos de la solicitud, haz las siguientes sustituciones:

  • PROJECT_ID: el ID de tu Google Cloud proyecto
  • LOCATION: la ubicación del conjunto de datos
  • DATASET_ID: el conjunto de datos superior del almacén DICOM
  • DICOM_STORE_ID: el ID del almacén DICOM

Para enviar tu solicitud, elige una de estas opciones:

curl

Ejecuta el comando siguiente:

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

Ejecuta el comando siguiente:

$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

Explorador de APIs

Abre la página de referencia del método. El panel Explorador de APIs se abre en la parte derecha de la página. Puedes interactuar con esta herramienta para enviar solicitudes. Rellena los campos obligatorios y haz clic en Ejecutar.

Deberías recibir una respuesta JSON similar a la siguiente:

Go

import (
	"context"
	"fmt"
	"io"

	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 := io.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

Usar la CLI de DICOMweb

En el siguiente ejemplo se muestra cómo usar la CLI de DICOMweb de la API Cloud Healthcare para buscar instancias en un almacén DICOM. Hay más ejemplos, incluido cómo filtrar la búsqueda, disponibles en el repositorio de GitHub de la CLI de DICOMweb.

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

Si la solicitud se realiza de forma correcta, el servidor devuelve la respuesta en formato 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"
            }
         ]
      },
   },

...

]

Recuperar datos DICOM

La API Cloud Healthcare implementa la transacción Retrieve para mostrar estudios, series, instancias y marcos en un almacén DICOM.

Para obtener más información, consulta la transacción de recuperación en la declaración de conformidad de DICOM de la API Cloud Healthcare.

Recuperar un estudio

En los siguientes ejemplos se muestra cómo mostrar un estudio. Para obtener más información, consulta Estudios, series e instancias DICOM en la declaración de conformidad de DICOM de la API Cloud Healthcare.

Al especificar el archivo de salida, utilice una extensión como .multipart. A continuación, analiza el archivo multiparte para obtener las series y las instancias individuales del estudio.

Para obtener más información, consulta projects.locations.datasets.dicomStores.studies.retrieveStudy.

curl

Para recuperar un estudio, haz una solicitud GET y especifica la siguiente información:

  • Nombre del conjunto de datos principal
  • Nombre del almacén DICOM
  • Identificador único (UID) del estudio
  • Un archivo de salida
  • Un token de acceso

En el siguiente ejemplo se muestra una solicitud GET que utiliza 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 solicitud se realiza correctamente, el archivo DICOM se escribe en tu máquina.

PowerShell

Para recuperar un estudio, haz una solicitud GET y especifica la siguiente información:

  • Nombre del conjunto de datos principal
  • Nombre del almacén DICOM
  • Identificador único (UID) del estudio
  • Un archivo de salida
  • Un token de acceso

En el siguiente ejemplo se muestra una solicitud GET que utiliza 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 solicitud se realiza correctamente, el archivo DICOM se escribe en tu máquina.

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

Recuperar una instancia

En los siguientes ejemplos se muestra cómo recuperar una instancia. Para obtener más información, consulta Instancias DICOM en la declaración de conformidad de DICOM de la API Cloud Healthcare.

Si estás recuperando una instancia, puedes evitar tener que analizar los límites de varias partes usando el encabezado HTTP Accept: application/dicom. Si añades transfer-syntax=*, se evita la transcodificación, ya que el archivo se devuelve en el formato en el que se almacenó originalmente.

Para obtener más información, consulta projects.locations.datasets.dicomStores.studies.series.instances.retrieveInstance.

curl

Para recuperar una instancia, haz una solicitud GET y especifica la siguiente información:

  • Nombre del conjunto de datos principal
  • Nombre del almacén DICOM
  • Identificador único (UID) del estudio
  • El UID de la serie y el UID de la instancia
  • Nombre del archivo de salida
  • Un token de acceso

En el siguiente ejemplo se muestra una solicitud GET que utiliza 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 solicitud se realiza correctamente, el archivo DICOM se escribe en tu máquina.

PowerShell

Para recuperar una instancia, haz una solicitud GET y especifica la siguiente información:

  • Nombre del conjunto de datos principal
  • Nombre del almacén DICOM
  • Identificador único (UID) del estudio
  • UID de la serie
  • El UID de la instancia
  • Nombre del archivo de salida
  • Un token de acceso

En el siguiente ejemplo se muestra una solicitud GET que utiliza 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 solicitud se realiza correctamente, el archivo DICOM se escribe en tu máquina.

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

Recuperar formatos de imagen de consumidor

En los siguientes ejemplos se muestra cómo obtener un formato de imagen de consumidor, como JPEG o PNG, mediante la implementación de recursos renderizados de la API Cloud Healthcare. Para obtener más información, consulta Recursos renderizados en la declaración de conformidad de DICOM de la API Cloud Healthcare.

Para obtener más información, consulta projects.locations.datasets.dicomStores.studies.series.instances.retrieveRendered.

curl

Para recuperar una imagen, haz una solicitud GET y especifica la siguiente información:

  • Nombre del conjunto de datos principal
  • Nombre del almacén DICOM
  • Identificador único (UID) del estudio
  • UID de la serie
  • El UID de la instancia
  • Nombre del archivo de salida
  • Un token de acceso

En el siguiente ejemplo se muestra cómo obtener una imagen PNG con una solicitud GET que utiliza 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 solicitud se realiza correctamente, el archivo PNG se escribe en tu máquina.

PowerShell

Para recuperar una imagen, haz una solicitud GET y especifica la siguiente información:

  • Nombre del conjunto de datos principal
  • Nombre del almacén DICOM
  • Identificador único (UID) del estudio
  • UID de la serie
  • El UID de la instancia
  • Nombre del archivo de salida
  • Un token de acceso

En el siguiente ejemplo se muestra cómo obtener una imagen PNG con una solicitud GET que utiliza 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 solicitud se realiza correctamente, el archivo PNG se escribe en tu máquina.

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

Recuperar metadatos

Puedes obtener los metadatos de todas las instancias de un estudio o una serie. En el siguiente ejemplo se muestra cómo recuperar los metadatos de una instancia. Para obtener más información, consulta Recursos de metadatos en la declaración de conformidad de DICOM de la API Cloud Healthcare.

Para obtener más información, consulta projects.locations.datasets.dicomStores.studies.series.instances.retrieveMetadata.

Cuando llamas a retrieveMetadata, el método devuelve el mismo conjunto de campos que se devuelven cuando buscas una instancia con el parámetro de consulta includefield=all.

La diferencia entre retrieveMetadata y searchForInstances es la capacidad de personalización. retrieveMetadata devuelve una respuesta coherente con un ámbito de búsqueda reducido. Es ideal para situaciones con una gran ingesta de instancias DICOM. Mientras tanto, searchForInstances se puede personalizar con varios parámetros de consulta, como includefield. Es adecuado para situaciones en las que se necesita minimizar el tamaño de la respuesta incluyendo solo los campos seleccionados.

De forma predeterminada, retrieveMetadata devuelve una respuesta JSON. Para devolver una respuesta XML, envía un encabezado HTTP Accept: multipart/related; type="application/dicom+xml" en tu solicitud.

REST

Antes de usar los datos de la solicitud, haz las siguientes sustituciones:

  • PROJECT_ID: el ID de tu Google Cloud proyecto
  • LOCATION: la ubicación del conjunto de datos
  • DATASET_ID: el conjunto de datos superior del almacén DICOM
  • DICOM_STORE_ID: el ID del almacén DICOM
  • STUDY_INSTANCE_UID: identificador único de la instancia del estudio
  • SERIES_INSTANCE_UID: identificador único de la instancia de la serie
  • INSTANCE_UID: identificador único de la instancia

Para enviar tu solicitud, elige una de estas opciones:

curl

Ejecuta el comando siguiente:

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

Ejecuta el comando siguiente:

$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

Explorador de APIs

Abre la página de referencia del método. El panel Explorador de APIs se abre en la parte derecha de la página. Puedes interactuar con esta herramienta para enviar solicitudes. Rellena los campos obligatorios y haz clic en Ejecutar.

Deberías recibir una respuesta JSON similar a la siguiente:

Recuperar datos en bloque

Una instancia DICOM consta de numerosos elementos de datos. Aunque la mayoría de los elementos de datos contienen pequeñas partes de metadatos (como el nombre de un paciente o la fecha de un estudio), algunos pueden contener grandes cantidades de datos, también llamados "datos masivos". Para saber qué datos se consideran "datos masivos" en la API Cloud Healthcare, consulta la definición de datos masivos.

La API Cloud Healthcare procesa estos elementos de "datos masivos" por separado. Para recuperar los bytes del valor sin formato, llama a projects.locations.datasets.dicomStores.studies.series.instances.bulkdata.retrieveBulkdata con una de las siguientes opciones:

  • Obtención directa: si conoce los identificadores del estudio, la serie, la instancia y la etiqueta específica que quiere obtener, puede crear la URL de solicitud y llamar a retrieveBulkdata directamente. La recuperación directa es el método más eficiente, ya que solo requiere una llamada a la API.

  • Recuperación mediante metadatos de instancias DICOM: cuando recuperas los metadatos de una instancia, la respuesta contiene un BulkDataURI por cada etiqueta de datos masivos admitida. Puedes usar este URI para hacer una solicitud retrieveBulkdata. Este método es útil para descubrir las etiquetas de datos en bloque disponibles de una instancia antes de recuperarlas.

En los siguientes ejemplos se muestra cómo obtener datos en bloque mediante la recuperación directa:

REST

Antes de usar los datos de la solicitud, haz las siguientes sustituciones:

  • PROJECT_ID: el ID de tu Google Cloud proyecto
  • LOCATION: la ubicación del conjunto de datos
  • DATASET_ID: el conjunto de datos superior del almacén DICOM
  • DICOM_STORE_ID: el ID del almacén DICOM
  • STUDY_INSTANCE_UID: identificador único de la instancia del estudio
  • SERIES_INSTANCE_UID: identificador único de la instancia de la serie
  • INSTANCE_UID: identificador único de la instancia
  • BULK_DATA_PATH: la etiqueta de datos en bloque, como 7FE00010 para PixelData. En el caso de una etiqueta (AAAA,AAAA) dentro de una secuencia (BBBB,BBBB) en el índice de elemento i, la ruta sería BBBBBBBB/i/AAAAAAAA
  • OUTPUT_FILE_PATH: una ruta de su máquina local en la que se almacenan los datos en bloque en un archivo DAT. Debes especificar la extensión .dat.

Para enviar tu solicitud, elige una de estas opciones:

curl

Ejecuta el comando siguiente:

curl -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
--output OUTPUT_FILE_PATH \
"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/bulkdata/BULK_DATA_PATH"

PowerShell

Ejecuta el comando siguiente:

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

Invoke-WebRequest `
-Method GET `
-Headers $headers `
-OutFile OUTPUT_FILE_PATH `
-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/bulkdata/BULK_DATA_PATH"
Si se completa correctamente, el archivo DAT se descargará en tu equipo local.

Usar la CLI de DICOMweb

En el siguiente ejemplo se muestra cómo usar la CLI de DICOMweb de la API Cloud Healthcare para obtener todas las instancias de un almacén DICOM y guardarlas en tu máquina en el directorio de trabajo actual. Hay más ejemplos disponibles en el repositorio de GitHub de la CLI de DICOMweb.

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

Si la solicitud se realiza correctamente, el servidor devuelve una respuesta similar a la siguiente y los archivos DICOM se escriben en tu máquina:

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

Eliminar un estudio, una serie o una instancia

La API Cloud Healthcare implementa un servicio web propio para eliminar estudios, series e instancias DICOM. Este servicio no forma parte de los servicios estándar de DICOMweb. Para obtener más información, consulta la sección sobre la eliminación de la declaración de conformidad de DICOM de la API Cloud Healthcare.

Las solicitudes de eliminación de estudios y series devuelven una operación de larga duración. Una vez completada la operación, se eliminan todas las instancias del estudio o de la serie.

Las solicitudes de eliminación de instancias no devuelven una operación de larga duración, sino un cuerpo de respuesta vacío como el siguiente:

{}

En los siguientes ejemplos se muestra cómo eliminar un estudio DICOM. Para obtener más información, consulta projects.locations.datasets.dicomStores.studies.delete.

REST

  1. Elimina el estudio.

    Antes de usar los datos de la solicitud, haz las siguientes sustituciones:

    • PROJECT_ID: el ID de tu Google Cloud proyecto
    • LOCATION: la ubicación del conjunto de datos
    • DATASET_ID: el conjunto de datos superior del almacén DICOM
    • DICOM_STORE_ID: el ID del almacén DICOM
    • STUDY_INSTANCE_UID: identificador único de la instancia del estudio

    Para enviar tu solicitud, elige una de estas opciones:

    curl

    Ejecuta el comando siguiente:

    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

    Ejecuta el comando siguiente:

    $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

    Explorador de APIs

    Abre la página de referencia del método. El panel Explorador de APIs se abre en la parte derecha de la página. Puedes interactuar con esta herramienta para enviar solicitudes. Rellena los campos obligatorios y haz clic en Ejecutar.

    Deberías recibir una respuesta JSON similar a la siguiente:

  2. Obtén el estado de la operación de larga duración.

    Antes de usar los datos de la solicitud, haz las siguientes sustituciones:

    • PROJECT_ID: el ID de tu Google Cloud proyecto
    • LOCATION: la ubicación del conjunto de datos
    • DATASET_ID: el conjunto de datos superior del almacén DICOM
    • OPERATION_ID: el ID devuelto por la operación de larga duración

    Para enviar tu solicitud, elige una de estas opciones:

    curl

    Ejecuta el comando siguiente:

    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

    Ejecuta el comando siguiente:

    $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

    Explorador de APIs

    Abre la página de referencia del método. El panel Explorador de APIs se abre en la parte derecha de la página. Puedes interactuar con esta herramienta para enviar solicitudes. Rellena los campos obligatorios y haz clic en Ejecutar.

    Deberías recibir una respuesta JSON similar a la siguiente:

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

Usar la CLI de DICOMweb

En el siguiente ejemplo se muestra cómo usar la CLI DICOMweb de la API Cloud Healthcare para eliminar un estudio:

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 solicitud se realiza correctamente, el servidor devuelve una operación que la herramienta de la CLI sondea hasta que se completa la operación de eliminación.

Actualizar o aplicar un parche a un estudio, una serie o una instancia

El estándar DICOMweb no especifica métodos para actualizar datos DICOM, pero la API Cloud Healthcare ofrece varios métodos para actualizar estos datos después de la ingestión. Consulta Actualizar y aplicar parches a estudios, series e instancias DICOM para ver los métodos y las guías disponibles.