Usa el estándar DICOMweb

En esta página, se explica cómo usar la implementación de DICOMweb de la API de Cloud Healthcare. Para obtener más información sobre cómo la API de Cloud Healthcare implementa varios servicios de REST de DICOM, consulta la declaración de conformidad de DICOM.

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

API de Cloud Healthcare de CLI de DICOMweb

Varias de las muestras de esta página usan la CLI web de la API de Cloud Healthcare, una herramienta de código abierto que simplifica la interacción con los servidores de DICOMweb. La herramienta proporciona funciones para almacenar, recuperar, borrar y buscar archivos de DICOM. La página de GitHub para la herramienta contiene más información, como los requisitos detallados de instalación y las maneras de personalizar la herramienta.

La herramienta se ejecuta con Python. Para obtener información sobre cómo configurar Python en Google Cloud, consulta Configura 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. Puedes hacerlo con cualquiera de los siguientes métodos:

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

Almacena datos DICOM

Antes de poder almacenar datos DICOM, debes crear un almacén de DICOM.

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

Existen dos métodos para almacenar datos de DICOM:

  • Almacenar una instancia de DICOM (generalmente un archivo .dcm)
  • Almacenar metadatos DICOM JSON con archivos JPEG

Cuando almacenas una instancia de DICOM directamente, solo se requiere el encabezado de aceptación application/dicom. Sin embargo, todas las solicitudes para almacenar metadatos JSON de DICOM con archivos JPEG son mensajes de varias partes, que se designan por la parte multipart/related de sus Content-Type. La parte multipart/related del Content-Type indica que la solicitud consta de varias partes de datos que se combinan después de que se completa la solicitud. Cada uno de estos conjuntos de datos debe estar separado mediante un límite, según lo designa la parte boundary de Content-Type.

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

Almacena una instancia de DICOM

En los siguientes ejemplos, se muestra cómo almacenar una instancia de DICOM.

curl

Para almacenar una instancia de DICOM, realiza una solicitud POST y especifica la siguiente información:

  • El nombre del conjunto de datos superior
  • El nombre del almacén de DICOM
  • El archivo de la instancia de DICOM
  • Un token de acceso

En el siguiente ejemplo, se muestra una solicitud POST mediante curl.

curl -X POST \
    -H "Content-Type: application/dicom" \
    -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 @DCM_FILE.dcm

Si la solicitud tiene éxito, el servidor mostrará 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_UID</Value>
  </DicomAttribute>
  <DicomAttribute tag="00081199" vr="SQ" keyword="ReferencedSOPSequence">
    <Item number="1">
      <DicomAttribute tag="00081150" vr="UI" keyword="ReferencedSOPClassUID">
        <Value number="1">SOPClassUID</Value>
      </DicomAttribute>
      <DicomAttribute tag="00081155" vr="UI" keyword="ReferencedSOPInstanceUID">
        <Value number="1">SOPInstanceUID</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_UID/series/SERIES_UID/instances/INSTANCE_UID</Value>
      </DicomAttribute>
    </Item>
  </DicomAttribute>
</NativeDicomModel>

PowerShell

Para almacenar una instancia de DICOM, realiza una solicitud POST y especifica la siguiente información:

  • El nombre del conjunto de datos superior
  • El nombre del almacén de DICOM
  • El archivo de la instancia de DICOM
  • Un token de acceso

En el siguiente ejemplo, se muestra una solicitud POST mediante Windows PowerShell.

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

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

Si la solicitud tiene éxito, el servidor mostrará 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_UID</Value>
  </DicomAttribute>
  <DicomAttribute tag="00081199" vr="SQ" keyword="ReferencedSOPSequence">
    <Item number="1">
      <DicomAttribute tag="00081150" vr="UI" keyword="ReferencedSOPClassUID">
        <Value number="1">SOPClassUID</Value>
      </DicomAttribute>
      <DicomAttribute tag="00081155" vr="UI" keyword="ReferencedSOPInstanceUID">
        <Value number="1">SOPInstanceUID</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_UID/series/SERIES_UID/instances/INSTANCE_UID</Value>
      </DicomAttribute>
    </Item>
  </DicomAttribute>
</NativeDicomModel>

Go

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

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

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

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

	healthcareService, err := healthcare.NewService(ctx)
	if err != nil {
		return fmt.Errorf("healthcare.NewService: %v", 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: %v", err)
	}
	defer resp.Body.Close()

	respBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("could not read response: %v", 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.jackson2.JacksonFactory;
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 JacksonFactory();
  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');
const healthcare = google.healthcare('v1');
const fs = require('fs');

const dicomWebStoreInstance = async () => {
  const auth = await google.auth.getClient({
    scopes: ['https://www.googleapis.com/auth/cloud-platform'],
  });
  google.options({
    auth,
    headers: {
      'Content-Type': 'application/dicom',
      Accept: 'application/dicom+json',
    },
  });

  // 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`;
  const binaryData = fs.createReadStream(dcmFile);
  const request = {
    parent,
    dicomWebPath,
    requestBody: binaryData,
  };

  const instance = await healthcare.projects.locations.datasets.dicomStores.storeInstances(
    request
  );
  console.log(`Stored DICOM instance:\n`, JSON.stringify(instance.data));
};

dicomWebStoreInstance();

Python

def dicomweb_store_instance(
    base_url, project_id, cloud_region, dataset_id, dicom_store_id, dcm_file
):
    """Handles the POST requests specified in the DICOMweb standard."""
    url = "{}/projects/{}/locations/{}".format(base_url, project_id, cloud_region)

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

    # Make an authenticated API request
    session = get_session()

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

    content_type = "application/dicom"
    headers = {"Content-Type": content_type}

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

Crea instancias de DICOM a partir de imágenes JPEG y metadatos JSON

La API de Cloud Healthcare puede crear instancias de DICOM mediante un archivo de metadatos JSON y una imagen JPEG. Crea instancias de DICOM a partir de metadatos JSON y imágenes JPEG si prefieres no realizar el análisis y la serialización de DICOM, ya que la API de Cloud Healthcare puede realizar estas tareas por ti.

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

  • El tipo de medio multipart/related
  • El tipo de MIME application/dicom+json
  • Un separador de 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 supone que tienes una imagen JPEG existente.

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

  1. Crea un archivo que contenga una representación JSON de una instancia de DICOM que contenga una imagen JPEG. A continuación, se proporciona un archivo de plantilla.
  2. Crea tres archivos de límite:

    • opening.file: Contiene el límite de apertura del archivo de metadatos JSON.
    • middle.file: Contiene el límite medio de la imagen JPEG.
    • closing.file: Contiene el límite de cierre para todas las partes del mensaje.
  3. Para crear un archivo llamado multipart-request.file, debes adjuntar el archivo de metadatos JSON y la imagen JPEG dentro de los archivos de límite.

Ten en cuenta los siguientes valores que se proporcionan de forma predeterminada en el archivo de la plantilla de metadatos JSON:

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

Los valores para SOPClassUID, SOPInstanceUID, StudyInstanceUID y SeriesInstanceUID pueden ser cualquier valor numérico separado por puntos. DICOM usa una jerarquía de identificadores para instancias, pacientes, estudios y series, por lo que debes elegir un conjunto lógico de identificadores para estas variables.

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

Reemplaza Rows por la altura vertical de la imagen JPEG en píxeles. Reemplaza Columns por el ancho horizontal de la imagen JPEG en píxeles.

Completa los siguientes pasos:

  1. Guarda el siguiente texto en un archivo llamado instance.json y reemplaza las variables cuando se especifique.

    [{
     "00020010":{"vr":"UI","Value":["1.2.840.10008.1.2.4.50"]},
     "00080005":{"vr":"CS","Value":["ISO_IR 192"]},
     "00080016":{"vr":"UI","Value":["SOPClassUID"]},
     "00080018":{"vr":"UI","Value":["SOPInstanceUID"]},
     "0020000D":{"vr":"UI","Value":["StudyInstanceUID"]},
     "0020000E":{"vr":"UI","Value":["SeriesInstanceUID"]},
     "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 la apertura (para los metadatos JSON), el medio (para la imagen JPEG) y los límites 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. Une la imagen JPEG dentro de los límites del medio y de cierre. El archivo de salida, que envías a la API de Cloud Healthcare, se llama multipart-request.file:

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

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

En el siguiente ejemplo, se muestra una solicitud POST mediante 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 tiene éxito, el servidor mostrará 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_UID</Value>
  </DicomAttribute>
  <DicomAttribute tag="00081199" vr="SQ" keyword="ReferencedSOPSequence">
    <Item number="1">
      <DicomAttribute tag="00081150" vr="UI" keyword="ReferencedSOPClassUID">
        <Value number="1">SOPClassUID</Value>
      </DicomAttribute>
      <DicomAttribute tag="00081155" vr="UI" keyword="ReferencedSOPInstanceUID">
        <Value number="1">SOPInstanceUID</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_UID/series/SERIES_UID/instances/INSTANCE_UID</Value>
      </DicomAttribute>
    </Item>
  </DicomAttribute>
</NativeDicomModel>

Usa la CLI de DICOMweb

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

Almacena una sola instancia de 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 tiene éxito, en el servidor se mostrará una respuesta similar a la siguiente muestra:

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_UID/series/SERIES_UID TIMESTAMP -- INSTANCE_UID
TIMESTAMP -- Transferred SIZE in COUNT files

Almacena varios archivos en paralelo con comodines:

En el siguiente ejemplo, se muestra cómo almacenar de manera recurrente varios archivos de DICOM en paralelo desde el directorio de trabajo actual. Para almacenar los archivos en paralelo, agrega 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 tiene éxito, en el servidor se mostrará una respuesta similar a la siguiente muestra:

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_UID/series/SERIES_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_UID/series/SERIES_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_UID/series/SERIES_UID TIMESTAMP -- INSTANCE_UID
...
TIMESTAMP -- Transferred SIZE in COUNT files

Busca estudios, series, instancias y marcos.

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

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

curl

Para buscar instancias en un almacén de DICOM, realiza una solicitud GET y especifica la siguiente información:

  • El nombre del conjunto de datos superior
  • El nombre del almacén de DICOM
  • Un token de acceso

En el siguiente ejemplo, se muestra una solicitud GET mediante curl.

curl -X GET \
     -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/instances"

Si la solicitud tiene éxito, se mostrará la respuesta en formato JSON en el servidor:

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

...

]

PowerShell

Para buscar instancias en un almacén de DICOM, realiza una solicitud GET y especifica la siguiente información:

  • El nombre del conjunto de datos superior
  • El nombre del almacén de DICOM
  • Un token de acceso

En el siguiente ejemplo, se muestra una solicitud GET mediante Windows PowerShell.

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

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/instances"

Si la solicitud tiene éxito, se mostrará la respuesta en formato JSON en el servidor:

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

...

]

Go

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

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

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

	healthcareService, err := healthcare.NewService(ctx)
	if err != nil {
		return fmt.Errorf("healthcare.NewService: %v", 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: %v", err)
	}

	defer resp.Body.Close()

	respBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("ioutil.ReadAll: %v", 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.jackson2.JacksonFactory;
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 JacksonFactory();
  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');
const healthcare = google.healthcare('v1');

const dicomWebSearchForInstances = async () => {
  const auth = await google.auth.getClient({
    scopes: ['https://www.googleapis.com/auth/cloud-platform'],
  });
  google.options({
    auth,
    headers: {Accept: 'application/dicom+json,multipart/related'},
  });

  // 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
  );
  console.log(`Found ${instances.data.length} instances:`);
  console.log(JSON.stringify(instances.data));
};

dicomWebSearchForInstances();

Python

def dicomweb_search_instance(
    base_url, project_id, cloud_region, dataset_id, dicom_store_id
):
    """Handles the GET requests specified in DICOMweb standard."""
    url = "{}/projects/{}/locations/{}".format(base_url, project_id, cloud_region)

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

    # Make an authenticated API request
    session = get_session()

    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

Busca mediante etiquetas de DICOM

Puedes definir mejor tus búsquedas agregando etiquetas DICOM a tus solicitudes en forma de parámetros de consulta. Por ejemplo, es posible que desees buscar estudios que contengan el nombre de un paciente.

Al igual que en los ejemplos anteriores, las siguientes muestras muestran una implementación de la transacción de búsqueda para buscar estudios en un almacén de DICOM. Sin embargo, estas muestras muestran 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 de DICOM en la que se muestra el nombre del paciente:

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

Para buscar estudios en un almacén DICOM que pertenezca al paciente, agrega un parámetro de búsqueda a tu solicitud en la que buscas con la etiqueta PatientName de DICOM. Para obtener una lista de los parámetros de búsqueda compatibles en la API de Cloud Healthcare, consulta la documentación sobre la transacción de búsqueda.

curl

Para usar etiquetas cuando se buscan estudios en un almacén DICOM, realiza una solicitud GET y especifica la siguiente información:

  • El nombre del conjunto de datos superior
  • El nombre del almacén de DICOM
  • El parámetro de búsqueda
  • Un token de acceso

En el siguiente ejemplo, se muestra una solicitud GET mediante curl.

curl -X GET \
     -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?PatientName=Sally%20Zhang"

Si la solicitud tiene éxito, se mostrará la respuesta en formato JSON en el servidor:

[
  {
    "00080005": {
      "vr": "CS",
      "Value": [
        "CODE_STRING"
      ]
    },
    "00080020": {
      "vr": "DA",
      "Value": [
        "DATE_TIME"
      ]
    },
    "00080030": {
      "vr": "TM",
      "Value": [
        "TIME"
      ]
    },
    "00080050": {
      "vr": "SH"
    },
    "00080090": {
      "vr": "PN",
      "Value": [
        {
          "Alphabetic": "VALUE"
        }
      ]
    },
    "00100010": {
      "vr": "PN",
      "Value": [
        {
          "Alphabetic": "Sally Zhang"
        }
      ]
    },
    "00100020": {
      "vr": "LO",
      "Value": [
        "VALUE"
      ]
    },
    "00100030": {
      "vr": "DA"
    },
    "00100040": {
      "vr": "CS",
      "Value": [
        "F"
      ]
    },
    "0020000D": {
      "vr": "UI",
      "Value": [
        "STUDY_INSTANCE_UID"
      ]
    },
    "00200010": {
      "vr": "SH"
    }
  }
]

PowerShell

Para usar etiquetas cuando se buscan estudios en un almacén DICOM, realiza una solicitud GET y especifica la siguiente información:

  • El nombre del conjunto de datos superior
  • El nombre del almacén de DICOM
  • El parámetro de búsqueda
  • Un token de acceso

En el siguiente ejemplo, se muestra una solicitud GET mediante Windows PowerShell.

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

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?PatientName=Sally%20Zhang"

Si la solicitud tiene éxito, se mostrará la respuesta en formato JSON en el servidor:

[
  {
    "00080005": {
      "vr": "CS",
      "Value": [
        "CODE_STRING"
      ]
    },
    "00080020": {
      "vr": "DA",
      "Value": [
        "DATE_TIME"
      ]
    },
    "00080030": {
      "vr": "TM",
      "Value": [
        "TIME"
      ]
    },
    "00080050": {
      "vr": "SH"
    },
    "00080090": {
      "vr": "PN",
      "Value": [
        {
          "Alphabetic": "VALUE"
        }
      ]
    },
    "00100010": {
      "vr": "PN",
      "Value": [
        {
          "Alphabetic": "Sally Zhang"
        }
      ]
    },
    "00100020": {
      "vr": "LO",
      "Value": [
        "VALUE"
      ]
    },
    "00100030": {
      "vr": "DA"
    },
    "00100040": {
      "vr": "CS",
      "Value": [
        "F"
      ]
    },
    "0020000D": {
      "vr": "UI",
      "Value": [
        "STUDY_INSTANCE_UID"
      ]
    },
    "00200010": {
      "vr": "SH"
    }
  }
]

Go

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

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

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

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

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

	healthcareService, err := healthcare.NewService(ctx)
	if err != nil {
		return fmt.Errorf("healthcare.NewService: %v", 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: %v", err)
	}

	defer resp.Body.Close()

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

	if resp.StatusCode > 299 {
		return fmt.Errorf("SearchForStudies: status %d %s: %s", resp.StatusCode, resp.Status, respBytes)
	}
	respString := string(respBytes)
	fmt.Fprintf(w, "Found studies: %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.jackson2.JacksonFactory;
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 JacksonFactory();
  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');
const healthcare = google.healthcare('v1');

const dicomWebSearchStudies = async () => {
  const auth = await google.auth.getClient({
    scopes: ['https://www.googleapis.com/auth/cloud-platform'],
  });

  google.options({
    auth,
    // 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'},
  });

  // 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
  );
  console.log(studies);

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

dicomWebSearchStudies();

Python

def dicomweb_search_studies(
    base_url, project_id, cloud_region, dataset_id, dicom_store_id
):
    """Handles the GET requests specified in the DICOMweb standard."""
    url = "{}/projects/{}/locations/{}".format(base_url, project_id, cloud_region)

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

    session = get_session()

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

    response.raise_for_status()

    print("Studies found: response is {}".format(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

Usa la CLI de DICOMweb

En el siguiente ejemplo, se muestra cómo usar la CLI de DICOMweb de la API de Cloud Healthcare para buscar instancias en un almacén de DICOM. Hay más muestras, incluido cómo filtrar tu 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 tiene éxito, se mostrará la respuesta en formato JSON en el servidor:

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

...

]

Recupera datos DICOM

La API de Cloud Healthcare implementa la transacción de recuperación para recuperar estudios, series, instancias y fotogramas en un almacén de DICOM.

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

Recupera un estudio

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

Cuando especifiques el archivo de salida, usa una extensión como .multipart. Luego, analice el archivo multiparte para obtener las series y instancias individuales en el estudio.

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

curl

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

  • El nombre del conjunto de datos superior
  • El nombre del almacén de DICOM
  • El identificador único del estudio (UID)
  • Un archivo de salida
  • Un token de acceso

En el siguiente ejemplo, se muestra una solicitud GET mediante curl.

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

Si la solicitud se realiza correctamente, el archivo DICOM se escribe en su máquina.

PowerShell

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

  • El nombre del conjunto de datos superior
  • El nombre del almacén de DICOM
  • El identificador único del estudio (UID)
  • Un archivo de salida
  • Un token de acceso

En el siguiente ejemplo, se muestra una solicitud GET mediante 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 `
  -OutFile FILENAME.multipart `
  -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_UID" | Select-Object -Expand Content

Si la solicitud se realiza correctamente, el archivo DICOM se escribe en su 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: %v", 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: %v", 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: %v", err)
	}
	defer file.Close()
	if _, err := io.Copy(file, resp.Body); err != nil {
		return fmt.Errorf("io.Copy: %v", 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.jackson2.JacksonFactory;
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 JacksonFactory();
  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');
const healthcare = google.healthcare('v1');
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 () => {
  const auth = await google.auth.getClient({
    scopes: ['https://www.googleapis.com/auth/cloud-platform'],
  });
  google.options({
    auth,
    headers: {
      Accept: 'multipart/related; type=application/dicom; transfer-syntax=*',
    },
    responseType: 'arraybuffer',
  });

  // 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
  );

  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(
    base_url, project_id, cloud_region, dataset_id, dicom_store_id, study_uid
):
    """Handles the GET requests specified in the DICOMweb standard."""
    url = "{}/projects/{}/locations/{}".format(base_url, project_id, cloud_region)

    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"

    # Make an authenticated API request
    session = get_session()

    response = session.get(dicomweb_path)

    response.raise_for_status()

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

    return response

Recupera una instancia

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

Si recuperas una instancia, puedes evitar tener que analizar límites de varias partes con el encabezado HTTP Accept: application/dicom. Agregar transfer-syntax=* evita la transcodificación mostrando el archivo 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, realiza una solicitud GET y especifica la siguiente información:

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

En el siguiente ejemplo, se muestra una solicitud GET mediante curl.

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

Si la solicitud se realiza correctamente, el archivo DICOM se escribe en su máquina.

PowerShell

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

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

En el siguiente ejemplo, se muestra una solicitud GET mediante 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 `
  -OutFile FILENAME.dcm `
  -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb/studies/STUDY_UID/series/SERIES_UID/instances/INSTANCE_UID"

Si la solicitud se realiza correctamente, el archivo DICOM se escribe en su 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: %v", 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: %v", 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: %v", err)
	}
	defer file.Close()
	if _, err := io.Copy(file, resp.Body); err != nil {
		return fmt.Errorf("io.Copy: %v", 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.jackson2.JacksonFactory;
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 JacksonFactory();
  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');
const healthcare = google.healthcare('v1');
const fs = require('fs');
const util = require('util');
const writeFile = util.promisify(fs.writeFile);
const fileName = 'instance_file.dcm';

const dicomWebRetrieveInstance = async () => {
  const auth = await google.auth.getClient({
    scopes: ['https://www.googleapis.com/auth/cloud-platform'],
  });
  google.options({
    auth,
    headers: {Accept: 'application/dicom; transfer-syntax=*'},
    responseType: 'arraybuffer',
  });

  // 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
  );
  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(
    base_url,
    project_id,
    cloud_region,
    dataset_id,
    dicom_store_id,
    study_uid,
    series_uid,
    instance_uid,
):
    """Handles the GET requests specified in the DICOMweb standard."""
    url = "{}/projects/{}/locations/{}".format(base_url, project_id, cloud_region)

    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"

    # Make an authenticated API request
    session = get_session()

    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

Recupera formatos de imagen de consumidor

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

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

curl

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

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

En el siguiente ejemplo, se muestra cómo recuperar una imagen PNG con una solicitud GET mediante curl.

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

Si la solicitud se realiza correctamente, el archivo PNG se escribe en la máquina.

PowerShell

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

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

En el siguiente ejemplo, se muestra cómo recuperar una imagen PNG con una solicitud GET mediante Windows PowerShell.

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

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

Si la solicitud se realiza correctamente, el archivo PNG se escribe en la 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: %v", 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: %v", 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: %v", err)
	}
	defer file.Close()
	if _, err := io.Copy(file, resp.Body); err != nil {
		return fmt.Errorf("io.Copy: %v", 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.jackson2.JacksonFactory;
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 JacksonFactory();
  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');
const healthcare = google.healthcare('v1');
const fs = require('fs');
const util = require('util');
const writeFile = util.promisify(fs.writeFile);
const fileName = 'rendered_image.png';

const dicomWebRetrieveRendered = async () => {
  const auth = await google.auth.getClient({
    scopes: ['https://www.googleapis.com/auth/cloud-platform'],
  });
  google.options({
    auth,
    headers: {Accept: 'image/png'},
    responseType: 'arraybuffer',
  });

  // 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
  );
  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(
    base_url,
    project_id,
    cloud_region,
    dataset_id,
    dicom_store_id,
    study_uid,
    series_uid,
    instance_uid,
):
    """Handles the GET requests specified in the DICOMweb standard."""
    url = "{}/projects/{}/locations/{}".format(base_url, project_id, cloud_region)

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

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

    dicomweb_path = "{}/rendered".format(instance_path)

    file_name = "rendered_image.png"

    # Make an authenticated API request
    session = get_session()

    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

Recupera metadatos

Puedes recuperar los metadatos de todas las instancias en 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 de Cloud Healthcare.

Para obtener más información, consulta projects.locations.datasets.dicomStores.studies.series.instances.retrieveMetadata. Cuando llamas a retrieveMetadata, el método muestra el mismo conjunto de campos que se muestran cuando buscas una instancia con el parámetro de búsqueda includefield=all. Si tu aplicación es sensible a la latencia y quieres recuperar los metadatos de un conjunto específico de campos (en lugar de todos los campos), no llames a retrieveMetadata. En su lugar, llama a uno de los métodos searchForInstances y especifica los campos. La respuesta será un conjunto de campos más pequeño, y un conjunto más pequeño de campos es útil para las aplicaciones sensibles a la latencia.

curl

Para recuperar los metadatos de una instancia en la que se quitaron datos masivos, realiza una solicitud GET y especifica la siguiente información:

  • El nombre del conjunto de datos superior
  • El nombre del almacén de DICOM
  • El identificador único del estudio (UID)
  • El UID de la serie
  • UID de instancia
  • Un token de acceso

En el siguiente ejemplo, se muestra una solicitud GET mediante curl.

curl -X GET \
     -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/STUDY_UID/series/SERIES_UID/instances/INSTANCE_UID/metadata"

Si la solicitud es exitosa, la respuesta contiene los metadatos de los atributos de DICOM en la instancia en formato JSON.

[
  {
    "00020002": {
      "vr": "UI",
      "Value": [
        "UNIQUE_IDENTIFIER"
      ]
    },
    "00020003": {
      "vr": "UI",
      "Value": [
        "UNIQUE_IDENTIFIER"
      ]
    },
    "00020010": {
      "vr": "UI",
      "Value": [
        "UNIQUE_IDENTIFIER"
      ]
    },
    "00020012": {
      "vr": "UI",
      "Value": [
        "UNIQUE_IDENTIFIER"
      ]
    },
    "00020013": {
      "vr": "SH",
      "Value": [
        "OFFIS_DCMTK_"
      ]
    },
    "00080016": {
      "vr": "UI",
      "Value": [
        "UNIQUE_IDENTIFIER"
      ]
    },
    ...
]

PowerShell

Para recuperar los metadatos de una instancia en la que se quitaron datos masivos, realiza una solicitud GET y especifica la siguiente información:

  • El nombre del conjunto de datos superior
  • El nombre del almacén de DICOM
  • El identificador único del estudio (UID)
  • El UID de la serie
  • UID de instancia
  • Un token de acceso

En el siguiente ejemplo, se muestra una solicitud GET mediante Windows PowerShell.

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

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_UID/series/SERIES_UID/instances/INSTANCE_UID/metadata"

Si la solicitud es exitosa, la respuesta contiene los metadatos de los atributos de DICOM en la instancia en formato JSON:

[
  {
    "00020002": {
      "vr": "UI",
      "Value": [
        "UNIQUE_IDENTIFIER"
      ]
    },
    "00020003": {
      "vr": "UI",
      "Value": [
        "UNIQUE_IDENTIFIER"
      ]
    },
    "00020010": {
      "vr": "UI",
      "Value": [
        "UNIQUE_IDENTIFIER"
      ]
    },
    "00020012": {
      "vr": "UI",
      "Value": [
        "UNIQUE_IDENTIFIER"
      ]
    },
    "00020013": {
      "vr": "SH",
      "Value": [
        "OFFIS_DCMTK_"
      ]
    },
    "00080016": {
      "vr": "UI",
      "Value": [
        "UNIQUE_IDENTIFIER"
      ]
    },
    ...
]

Usa la CLI de DICOMweb

En el siguiente ejemplo, se muestra cómo usar la CLI de DICOMweb de la API de Cloud Healthcare para recuperar todas las instancias en un almacén de DICOM y guardarlas en tu máquina en el directorio de trabajo actual. Hay más muestras 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 muestra 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

Borra un estudio, una serie o una instancia

La API de Cloud Healthcare implementa un servicio web propio para borrar las historias, las instancias y los estudios de DICOM. Este servicio no forma parte de los servicios estándar de DICOMweb. Para obtener más información, consulta Borra la transacción en la declaración de conformidad de DICOM de la API de Cloud Healthcare.

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

curl

Para borrar un estudio de DICOM, realiza una solicitud DELETE y especifica la siguiente información:

  • El nombre del conjunto de datos superior
  • El nombre del almacén de DICOM
  • El identificador único (UID) del estudio
  • Un token de acceso

En el siguiente ejemplo, se muestra cómo borrar un estudio con una solicitud DELETE mediante curl.

curl -X DELETE \
     -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/STUDY_UID"

Si la solicitud se realiza con éxito, el servidor muestra el cuerpo de la respuesta vacío en formato JSON:

{}

PowerShell

Para borrar un estudio de DICOM, realiza una solicitud DELETE y especifica la siguiente información:

  • El nombre del conjunto de datos superior
  • El nombre del almacén de DICOM
  • El identificador único (UID) del estudio
  • Un token de acceso

En el siguiente ejemplo, se muestra cómo borrar un estudio con una solicitud DELETE con Windows PowerShell.

$cred = gcloud auth application-default 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_UID" | Select-Object -Expand Content

Si la solicitud se realiza con éxito, el servidor muestra el cuerpo de la respuesta vacío en formato JSON:

{}

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: %v", 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: %v", 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.jackson2.JacksonFactory;
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 JacksonFactory();
  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');
const healthcare = google.healthcare('v1');

const dicomWebDeleteStudy = async () => {
  const auth = await google.auth.getClient({
    scopes: ['https://www.googleapis.com/auth/cloud-platform'],
  });
  google.options({auth});

  // 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(
    base_url, project_id, cloud_region, dataset_id, dicom_store_id, study_uid
):
    """Handles DELETE requests equivalent to the GET requests specified in
    the WADO-RS standard.
    """
    url = "{}/projects/{}/locations/{}".format(base_url, project_id, cloud_region)

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

    # Make an authenticated API request
    session = get_session()

    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

Usa la CLI de DICOMweb

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

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

Si la solicitud se realiza correctamente, el servidor borra el estudio y no muestra una respuesta.