Cloud Storage を使用した DICOM データのインポートとエクスポート

このページでは、Cloud Storage に DICOM インスタンスをエクスポートする方法と、Cloud Storage から DICOM オブジェクトをインポートする方法について説明します。通常、DICOM インスタンスは画像ですが、構造化レポートなどの別のタイプの永続データにすることもできます。Cloud Storage オブジェクトは、Cloud Storage に保存されている DICOM インスタンスです。

Cloud Storage バケットと DICOM ストアの間でバルクデータをインポートおよびエクスポートできます。たとえば、DICOM ストアにインポートする DICOM インスタンス ファイルが多数あるとします。 プログラムによってデータを直接保存するのではなく、Cloud Storage バケットにデータを保存し、単一のインポート オペレーションを使用して DICOM ストアにファイルをインポートしてください。詳細については、Cloud Storage をご覧ください。

ローカルマシンなどから DICOM インスタンスを直接保存するには、Cloud Healthcare API に実装されている Store Transaction RESTful ウェブサービスを使用して DICOM データを保存します。DICOM ストアから単一のインスタンスまたはスタディを取得するには、Cloud Healthcare API に実装されている Retrieve Transaction RESTful ウェブサービスを使用して DICOM データを取得します。

Cloud Storage 権限を設定する

Cloud Storage との間で DICOM データをエクスポートおよびインポートする前に、Cloud Healthcare サービス エージェントサービス アカウントに追加の権限を付与する必要があります。詳細については、DICOM ストアの Cloud Storage 権限をご覧ください。

DICOM オブジェクトをインポートする

以下のサンプルは、Cloud Storage バケットから DICOM オブジェクトをインポートする方法を示しています。

Console

Cloud Storage バケットから DICOM オブジェクトをインポートする手順は次のとおりです。

  1. Cloud Console で、[データセット] ページに移動します。
    [データセット] ページに移動
  2. DICOM オブジェクトをインポートする DICOM ストアを含むデータセットをクリックします。
  3. データストアのリストで、DICOM ストアの [アクション] リストから [インポート] を選択ます。

    DICOM ストアへのインポート ページが表示されます。
  4. [プロジェクト] リストで、Cloud Storage プロジェクトを選択します。
  5. [ロケーション] リストで、Cloud Storage バケットを選択します。
  6. ファイルをインポートする特定の場所を設定するには、次のようにします。
    1. [詳細オプション] を展開します。
    2. [Cloud Storage のパスをオーバーライド] を選択します。
    3. ファイルをインポートする特定のソースを設定するには、[ロケーション] テキスト ボックスで次の変数を使用してパスを定義します。
      • * - 区切り文字以外の文字に一致します。
      • ** - 区切り文字を含む文字に一致します。 これは、同じ種類のすべてのファイルに一致するファイル名拡張子とともに使用できます。
      • ? - 1 文字に一致します。
  7. 定義したソースから DICOM オブジェクトをインポートするには、[インポート] をクリックします。
  8. オペレーションのステータスを追跡するには、[オペレーション] タブをクリックします。オペレーションが完了すると、次の状況が表示されます。
    • [長時間実行オペレーションのステータス] セクションでは、[OK] の見出しの下に、緑色のチェックマークが表示されます。
    • [概要] セクションでは、オペレーション ID と同じ行に緑色のチェックマークと [OK] インジケーターが表示されます。
    エラーが発生した場合は、[アクション] をクリックしてから、[Cloud Logging で詳細を表示] をクリックします。

gcloud

Cloud Storage バケットから DICOM オブジェクトをインポートするには、gcloud healthcare dicom-stores import gcs コマンドを使用します。親データセットの名前、DICOM ストアの名前、Cloud Storage バケット内のオブジェクトの場所を指定します。

  • バケット内のファイルの場所は任意であり、次のサンプルで指定されている形式を厳密に遵守する必要はありません。
  • Cloud Storage 内の DICOM オブジェクトの場所を指定するときは、ワイルドカードを使用して 1 つ以上のディレクトリから複数のファイルをインポートできます。次のワイルドカードがサポートされています。
    • * は、0 個以上の区切り文字でない文字に一致します。たとえば、gs://BUCKET/DIRECTORY/Example*.dcmDIRECTORY の Example.dcm と Example22.dcm に一致します。
    • ** は 0 個以上の文字(区切り文字を含む)と一致します。パスの末尾で使用する必要があり、パスには他のワイルドカードを使用しないでください。ファイル名の拡張子(.dcm など)でも使用できます。この場合、指定したディレクトリとそのサブディレクトリに、このファイル名拡張子を持つすべてのファイルをインポートできます。 たとえば、gs://BUCKET/DIRECTORY/**.dcm では .dcm というファイル名拡張子を持つすべてのファイルを DIRECTORYとそのサブディレクトリにインポートします。
    • ? は 1 つの文字に一致します。たとえば、gs://BUCKET/DIRECTORY/Example?.dcm は Example1.dcm と一致しますが、Example.dcm や Example01.dcm とは一致しません。

次のサンプルは、Cloud Storage バケットから DICOM オブジェクトをインポートする方法を示しています。

gcloud healthcare dicom-stores import gcs DICOM_STORE_ID \
  --dataset=DATASET_ID \
  --location=LOCATION \
  --gcs-uri=gs://BUCKET/DIRECTORY/DICOM_INSTANCE.dcm

コマンドラインに次のオペレーション ID が表示されます。

name: projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID

オペレーションのステータスを表示するには、レスポンスの OPERATION_ID を指定して gcloud healthcare operations describe コマンドを実行します。

gcloud healthcare operations describe OPERATION_ID \
  --location=LOCATION \
  --dataset=DATASET_ID

コマンドが完了すると、レスポンスには done: true が含まれます。

done: true
metadata:
'@type': type.googleapis.com/google.cloud.healthcare.v1.OperationMetadata
apiMethodName: google.cloud.healthcare.v1.dicom.DicomService.ImportDicomData
counter:
  success: SUCCESSFUL_INSTANCES
  failure: FAILED_INSTANCES
createTime: "CREATE_TIME"
endTime: "END_TIME"
name: projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID
response:
'@type': "..."

API

Cloud Storage バケットから DICOM オブジェクトをインポートするには、projects.locations.datasets.dicomStores.import メソッドを使用します。

  • バケット内のファイルの場所は任意であり、次のサンプルで指定されている形式を厳密に遵守する必要はありません。
  • Cloud Storage 内の DICOM オブジェクトの場所を指定するときは、ワイルドカードを使用して 1 つ以上のディレクトリから複数のファイルをインポートします。次のワイルドカードがサポートされています。
    • * は、0 個以上の区切り文字でない文字に一致します。たとえば、gs://BUCKET/DIRECTORY/Example*.dcmDIRECTORY の Example.dcm と Example22.dcm に一致します。
    • ** は 0 個以上の文字(区切り文字を含む)と一致します。パスの末尾で使用する必要があり、パスには他のワイルドカードを使用しないでください。ファイル名の拡張子(.dcm など)でも使用できます。この場合、指定したディレクトリとそのサブディレクトリに、このファイル名拡張子を持つすべてのファイルをインポートできます。 たとえば、gs://BUCKET/DIRECTORY/**.dcm では .dcm というファイル名拡張子を持つすべてのファイルを DIRECTORYとそのサブディレクトリにインポートします。
    • ? は 1 つの文字に一致します。たとえば、gs://BUCKET/DIRECTORY/Example?.dcm は Example1.dcm と一致しますが、Example.dcm や Example01.dcm とは一致しません。

curl

DICOM オブジェクトをインポートするには、POST リクエストを行い、次の情報を指定します。

  • 親データセットの名前と場所
  • DICOM ストアの名前
  • Cloud Storage バケット内のオブジェクトの場所。

次のサンプルは、curl を使用した POST リクエストを示しています。

curl -X POST \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    -H "Content-Type: application/json; charset=utf-8" \
    --data "{
      'gcsSource': {
        'uri': 'gs://BUCKET/*.dcm'
      }
    }" "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID:import"

リクエストが成功すると、サーバーは JSON 形式のレスポンスを返します。

{
  "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"
}

レスポンスにはオペレーション名が含まれています。オペレーションのステータスを追跡するには、オペレーションの get メソッドを使用します。

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/operations/OPERATION_ID"

リクエストが成功すると、サーバーはオペレーションのステータスを含む JSON 形式のレスポンスを返します。

{
  "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.healthcare.v1.OperationMetadata",
    "apiMethodName": "google.cloud.healthcare.v1.dicom.DicomService.ImportDicomData",
    "createTime": "CREATE_TIME",
    "endTime": "END_TIME",
    "logsUrl": "https://console.cloud.google.com/logs/viewer/CLOUD_LOGGING_URL",
    "counter": {
       "success": SUCCESSFUL_INSTANCES
       "failure": FAILED_INSTANCES
    },
  },
  "done": true,
  "response": {
    "@type": "..."
  }
}

PowerShell

DICOM オブジェクトをインポートするには、POST リクエストを行い、次の情報を指定します。

  • 親データセットの名前と場所
  • DICOM ストアの名前
  • Cloud Storage バケット内のオブジェクトの場所。

次のサンプルは、Windows PowerShell を使用した POST リクエストを示しています。

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

Invoke-WebRequest `
  -Method Post `
  -Headers $headers `
  -ContentType: "application/json; charset=utf-8" `
  -Body "{
    'gcsSource': {
      'uri': 'gs://BUCKET/*.dcm'
    }
  }" `
  -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID:import" | Select-Object -Expand Content

リクエストが成功すると、サーバーは JSON 形式のレスポンスを返します。

{
  "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"
}

レスポンスにはオペレーション名が含まれています。オペレーションのステータスを追跡するには、オペレーションの get メソッドを使用します。

$cred = gcloud auth application-default 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

リクエストが成功すると、サーバーはオペレーションのステータスを含む JSON 形式のレスポンスを返します。

{
  "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.healthcare.v1.OperationMetadata",
    "apiMethodName": "google.cloud.healthcare.v1.dicom.DicomService.ImportDicomData",
    "createTime": "CREATE_TIME",
    "endTime": "END_TIME",
    "logsUrl": "https://console.cloud.google.com/logs/viewer/CLOUD_LOGGING_URL",
    "counter":{
       "success": SUCCESSFUL_INSTANCES
       "failure": FAILED_INSTANCES
    }
  },
  "done": true,
  "response": {
    "@type": "..."
  }
}

Go

import (
	"context"
	"fmt"
	"io"

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

// importDICOMInstance imports DICOM objects from GCS.
func importDICOMInstance(w io.Writer, projectID, location, datasetID, dicomStoreID, contentURI 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

	req := &healthcare.ImportDicomDataRequest{
		GcsSource: &healthcare.GoogleCloudHealthcareV1DicomGcsSource{
			Uri: contentURI,
		},
	}
	name := fmt.Sprintf("projects/%s/locations/%s/datasets/%s/dicomStores/%s", projectID, location, datasetID, dicomStoreID)

	lro, err := storesService.Import(name, req).Do()
	if err != nil {
		return fmt.Errorf("Import: %v", err)
	}

	fmt.Fprintf(w, "Import to DICOM store started. Operation: %q\n", lro.Name)
	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;
import com.google.api.services.healthcare.v1.CloudHealthcareScopes;
import com.google.api.services.healthcare.v1.model.GoogleCloudHealthcareV1DicomGcsSource;
import com.google.api.services.healthcare.v1.model.ImportDicomDataRequest;
import com.google.api.services.healthcare.v1.model.Operation;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.IOException;
import java.util.Collections;

public class DicomStoreImport {
  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 dicomStoreImport(String dicomStoreName, String gcsUri) throws IOException {
    // String dicomStoreName =
    //    String.format(
    //        DICOM_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-dicom-id");
    // String gcsUri = "gs://your-bucket-id/path/to/destination/dir"

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

    // Configure where the store should be imported from.
    GoogleCloudHealthcareV1DicomGcsSource gcsSource =
        new GoogleCloudHealthcareV1DicomGcsSource().setUri(gcsUri);
    ImportDicomDataRequest importRequest = new ImportDicomDataRequest().setGcsSource(gcsSource);

    // Create request and configure any parameters.
    DicomStores.CloudHealthcareImport request =
        client
            .projects()
            .locations()
            .datasets()
            .dicomStores()
            .healthcareImport(dicomStoreName, importRequest);

    // Execute the request, wait for the operation to complete, and process the results.
    try {
      Operation operation = request.execute();
      while (operation.getDone() == null || !operation.getDone()) {
        // Update the status of the operation with another request.
        Thread.sleep(500); // Pause for 500ms between requests.
        operation =
            client
                .projects()
                .locations()
                .datasets()
                .operations()
                .get(operation.getName())
                .execute();
      }
      System.out.println("DICOM store import complete." + operation.getResponse());
    } catch (Exception ex) {
      System.out.printf("Error during request execution: %s", ex.toString());
      ex.printStackTrace(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();
  }
}

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 sleep = ms => {
  return new Promise(resolve => setTimeout(resolve, ms));
};

const importDicomInstance = 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 gcsUri = 'my-bucket/my-directory/*.dcm'
  const name = `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/dicomStores/${dicomStoreId}`;
  const request = {
    name,
    resource: {
      // The location of the DICOM instances in Cloud Storage
      gcsSource: {
        uri: `gs://${gcsUri}`,
      },
    },
  };

  const operation =
    await healthcare.projects.locations.datasets.dicomStores.import(request);
  const operationName = operation.data.name;

  const operationRequest = {name: operationName};

  // Wait fifteen seconds for the LRO to finish.
  await sleep(15000);

  // Check the LRO's status
  const operationStatus =
    await healthcare.projects.locations.datasets.operations.get(
      operationRequest
    );

  const {data} = operationStatus;

  if (data.error === undefined) {
    console.log('Successfully imported DICOM instances');
  } else {
    console.log('Encountered errors. Sample error:');
    console.log(
      'Resource on which error occured:',
      data.error.details[0]['sampleErrors'][0]['resource']
    );
    console.log(
      'Error code:',
      data.error.details[0]['sampleErrors'][0]['error']['code']
    );
    console.log(
      'Error message:',
      data.error.details[0]['sampleErrors'][0]['error']['message']
    );
  }
};

importDicomInstance();

Python

def import_dicom_instance(
    project_id, location, dataset_id, dicom_store_id, content_uri
):
    """Imports data into the DICOM store by copying it from the specified
    source.

    See https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/healthcare/api-client/v1/dicom
    before running the sample."""
    # Imports the Google API Discovery Service.
    from googleapiclient import discovery

    api_version = "v1"
    service_name = "healthcare"
    # Returns an authorized API client by discovering the Healthcare API
    # and using GOOGLE_APPLICATION_CREDENTIALS environment variable.
    client = discovery.build(service_name, api_version)

    # 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 DICOM store's parent dataset ID
    # dicom_store_id = 'my-dicom-store'  # replace with the DICOM store's ID
    # content_uri = 'my-bucket/*.dcm'  # replace with a Cloud Storage bucket and DCM files
    dicom_store_parent = "projects/{}/locations/{}/datasets/{}".format(
        project_id, location, dataset_id
    )
    dicom_store_name = "{}/dicomStores/{}".format(dicom_store_parent, dicom_store_id)

    body = {"gcsSource": {"uri": "gs://{}".format(content_uri)}}

    # Escape "import()" method keyword because "import"
    # is a reserved keyword in Python
    request = (
        client.projects()
        .locations()
        .datasets()
        .dicomStores()
        .import_(name=dicom_store_name, body=body)
    )

    response = request.execute()
    print("Imported DICOM instance: {}".format(content_uri))

    return response

DICOM インポート リクエストのトラブルシューティング

DICOM のインポート リクエスト中にエラーが発生した場合、エラーは Cloud Logging に記録されます。詳細については、Cloud Logging でのエラーログの表示をご覧ください。

DICOM インスタンスをエクスポートする

以下のサンプルは、DICOM インスタンスを Cloud Storage バケットにエクスポートする方法を示しています。DICOM ストアから DICOM インスタンスをエクスポートするときには、ストア内のすべてのインスタンスがエクスポートされます。

Console

DICOM インスタンスを Cloud Storage にエクスポートする手順は次のとおりです。

  1. Cloud Console で、[データセット] ページに移動します。
    [データセット] ページに移動
  2. DICOM インスタンスのエクスポート元の DICOM ストアを含むデータセットをクリックします。
  3. データストアのリストで、DICOM ストアの [アクション] リストから [エクスポート] を選択します。
  4. 表示される [DICOM ストアをエクスポート] ページで、[Google Cloud Storage バケット] を選択します。
  5. [プロジェクト] リストで、Cloud Storage プロジェクトを選択します。
  6. [ロケーション] リストで、Cloud Storage バケットを選択します。
  7. [DICOM エクスポート設定] で、DICOM インスタンスのエクスポートに使用するファイルの種類を選択します。以下の種類を選択できます。
    • DICOM ファイル(.dcm
    • オクテット ストリーム
    • 画像(.jpg.png
  8. 追加の転送構文を定義するには、[転送構文] リストから構文を選択します。
  9. [エクスポート] をクリックして、Cloud Storage の定義された場所に DICOM インスタンスをエクスポートします。
  10. オペレーションのステータスを追跡するには、[オペレーション] タブをクリックします。オペレーションが完了すると、次の状況が表示されます。
    • [長時間実行オペレーションのステータス] セクションでは、[OK] の見出しの下に、緑色のチェックマークが表示されます。
    • [概要] セクションでは、オペレーション ID と同じ行に緑色のチェックマークと [OK] インジケーターが表示されます。
    エラーが発生した場合は、[アクション] をクリックしてから、[Cloud Logging で詳細を表示] をクリックします。

gcloud

DICOM インスタンスを Cloud Storage バケットにエクスポートするには、gcloud healthcare dicom-stores export gcs コマンドを使用します。

  • 親データセットの名前、DICOM ストアの名前、宛先の Cloud Storage バケットを指定します。
  • Cloud Healthcare API はオブジェクトごとに 1 つの .dcm ファイルを作成するため、オブジェクトではなく Cloud Storage バケットまたはディレクトリに書き込みます。
  • コマンドに存在しないディレクトリが指定されている場合は、そのディレクトリが作成されます。

次のサンプルは、gcloud healthcare dicom-stores export gcs コマンドを示しています。

gcloud healthcare dicom-stores export gcs DICOM_STORE_ID \
  --dataset=DATASET_ID \
  --location=LOCATION \
  --gcs-uri-prefix=gs://BUCKET/DIRECTORY

コマンドラインに次のオペレーション ID が表示されます。

name: projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID

オペレーションのステータスを表示するには、レスポンスの OPERATION_ID を指定して gcloud healthcare operations describe コマンドを実行します。

gcloud healthcare operations describe OPERATION_ID \
  --location=LOCATION \
  --dataset=DATASET_ID

コマンドが完了すると、レスポンスには done: true が含まれます。

done: true
metadata:
'@type': type.googleapis.com/google.cloud.healthcare.v1.OperationMetadata
apiMethodName: google.cloud.healthcare.v1.dicom.DicomService.ExportDicomData
counter:
  success: SUCCESSFUL_INSTANCES
  failure: FAILED_INSTANCES
createTime: "CREATE_TIME"
endTime: "END_TIME"
name: projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID
response:
'@type': "..."

API

DICOM インスタンスを Cloud Storage バケットにエクスポートするには、projects.locations.datasets.dicomStores.export メソッドを使用します。

  • Cloud Healthcare API は DICOM オブジェクトごとに 1 つの .dcm ファイルを作成するため、オブジェクトではなく Cloud Storage バケットまたはディレクトリに書き込みます。
  • コマンドに存在しないディレクトリが指定されている場合は、そのディレクトリが作成されます。

curl

DICOM インスタンスをエクスポートするには、POST リクエストを行い、次の情報を指定します。

  • 親データセットの名前と場所
  • DICOM ストアの名前
  • 宛先の Cloud Storage バケット。

次のサンプルは、curl を使用した POST リクエストを示しています。

curl -X POST \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    -H "Content-Type: application/json; charset=utf-8" \
    --data "{
      'gcsDestination': {
        'uriPrefix': 'gs://BUCKET/DIRECTORY'
      }
    }" "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID:export"

リクエストが成功すると、サーバーは JSON 形式のレスポンスを返します。

{
  "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"
}

レスポンスにはオペレーション名が含まれています。オペレーションのステータスを追跡するには、オペレーションの get メソッドを使用します。

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/operations/OPERATION_ID"

リクエストが成功すると、サーバーはオペレーションのステータスを含む JSON 形式のレスポンスを返します。

{
  "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.healthcare.v1.OperationMetadata",
    "apiMethodName": "google.cloud.healthcare.v1.dicom.DicomService.ExportDicomData",
    "createTime": "CREATE_TIME",
    "endTime": "END_TIME",
    "logsUrl": "https://console.cloud.google.com/logs/viewer/CLOUD_LOGGING_URL",
    "counter":{
       "success": SUCCESSFUL_INSTANCES
       "failure": FAILED_INSTANCES
    }
  },
  "done": true,
  "response": {
    "@type": "..."
  }
}

PowerShell

DICOM インスタンスをエクスポートするには、POST リクエストを行い、次の情報を指定します。

  • 親データセットの名前と場所
  • DICOM ストアの名前
  • 宛先の Cloud Storage バケット。

次のサンプルは、Windows PowerShell を使用した POST リクエストを示しています。

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

Invoke-WebRequest `
  -Method Post `
  -Headers $headers `
  -ContentType: "application/json; charset=utf-8" `
  -Body "{
    'gcsDestination': {
      'uriPrefix': 'gs://BUCKET/DIRECTORY'
    }
  }" `
  -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID:export" | Select-Object -Expand Content

リクエストが成功すると、サーバーは JSON 形式のレスポンスを返します。

{
  "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"
}

レスポンスにはオペレーション名が含まれています。オペレーションのステータスを追跡するには、オペレーションの get メソッドを使用します。

$cred = gcloud auth application-default 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

リクエストが成功すると、サーバーはオペレーションのステータスを含む JSON 形式のレスポンスを返します。

{
  "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.healthcare.v1.OperationMetadata",
    "apiMethodName": "google.cloud.healthcare.v1.dicom.DicomService.ExportDicomData",
    "createTime": "CREATE_TIME",
    "endTime": "END_TIME",
    "logsUrl": "https://console.cloud.google.com/logs/viewer/CLOUD_LOGGING_URL",
    "counter":{
       "success": SUCCESSFUL_INSTANCES
       "failure": FAILED_INSTANCES
    },
  },
  "done": true,
  "response": {
    "@type": "..."
  }
}

Go

import (
	"context"
	"fmt"
	"io"

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

// exportDICOMInstance exports DICOM objects to GCS.
func exportDICOMInstance(w io.Writer, projectID, location, datasetID, dicomStoreID, destination 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

	req := &healthcare.ExportDicomDataRequest{
		GcsDestination: &healthcare.GoogleCloudHealthcareV1DicomGcsDestination{
			UriPrefix: destination, // "gs://my-bucket/path/to/prefix/"
		},
	}
	name := fmt.Sprintf("projects/%s/locations/%s/datasets/%s/dicomStores/%s", projectID, location, datasetID, dicomStoreID)

	lro, err := storesService.Export(name, req).Do()
	if err != nil {
		return fmt.Errorf("Export: %v", err)
	}

	fmt.Fprintf(w, "Export to DICOM store started. Operation: %q\n", lro.Name)
	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;
import com.google.api.services.healthcare.v1.CloudHealthcareScopes;
import com.google.api.services.healthcare.v1.model.ExportDicomDataRequest;
import com.google.api.services.healthcare.v1.model.GoogleCloudHealthcareV1DicomGcsDestination;
import com.google.api.services.healthcare.v1.model.Operation;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.IOException;
import java.util.Collections;

public class DicomStoreExport {
  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 dicomStoreExport(String dicomStoreName, String gcsUri) throws IOException {
    // String dicomStoreName =
    //    String.format(
    //        DICOM_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-dicom-id");
    // String gcsUri = "gs://your-bucket-id/path/to/destination/dir"

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

    // Configure where the store will be exported too.
    GoogleCloudHealthcareV1DicomGcsDestination gcsDestination =
        new GoogleCloudHealthcareV1DicomGcsDestination().setUriPrefix(gcsUri);
    ExportDicomDataRequest exportRequest =
        new ExportDicomDataRequest().setGcsDestination(gcsDestination);

    // Create request and configure any parameters.
    DicomStores.Export request =
        client
            .projects()
            .locations()
            .datasets()
            .dicomStores()
            .export(dicomStoreName, exportRequest);

    // Execute the request, wait for the operation to complete, and process the results.
    try {
      Operation operation = request.execute();
      while (operation.getDone() == null || !operation.getDone()) {
        // Update the status of the operation with another request.
        Thread.sleep(500); // Pause for 500ms between requests.
        operation =
            client
                .projects()
                .locations()
                .datasets()
                .operations()
                .get(operation.getName())
                .execute();
      }
      System.out.println("DICOM store export complete." + operation.getResponse());
    } catch (Exception ex) {
      System.out.printf("Error during request execution: %s", ex.toString());
      ex.printStackTrace(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();
  }
}

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 exportDicomInstanceGcs = 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 gcsUri = 'my-bucket/my-directory'
  const name = `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/dicomStores/${dicomStoreId}`;
  const request = {
    name,
    resource: {
      gcsDestination: {
        // The destination location of the DICOM instances in Cloud Storage
        uriPrefix: `gs://${gcsUri}`,
        // The format to use for the output files, per the MIME types supported in the DICOM spec
        mimeType: 'application/dicom',
      },
    },
  };

  await healthcare.projects.locations.datasets.dicomStores.export(request);
  console.log(`Exported DICOM instances to ${gcsUri}`);
};

exportDicomInstanceGcs();

Python

def export_dicom_instance(project_id, location, dataset_id, dicom_store_id, uri_prefix):
    """Export data to a Google Cloud Storage bucket by copying
    it from the DICOM store.

    See https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/healthcare/api-client/v1/dicom
    before running the sample."""
    # Imports the Google API Discovery Service.
    from googleapiclient import discovery

    api_version = "v1"
    service_name = "healthcare"
    # Returns an authorized API client by discovering the Healthcare API
    # and using GOOGLE_APPLICATION_CREDENTIALS environment variable.
    client = discovery.build(service_name, api_version)

    # 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 DICOM store's parent dataset ID
    # dicom_store_id = 'my-dicom-store'  # replace with the DICOM store's ID
    # uri_prefix = 'my-bucket'  # replace with a Cloud Storage bucket
    dicom_store_parent = "projects/{}/locations/{}/datasets/{}".format(
        project_id, location, dataset_id
    )
    dicom_store_name = "{}/dicomStores/{}".format(dicom_store_parent, dicom_store_id)

    body = {"gcsDestination": {"uriPrefix": "gs://{}".format(uri_prefix)}}

    request = (
        client.projects()
        .locations()
        .datasets()
        .dicomStores()
        .export(name=dicom_store_name, body=body)
    )

    response = request.execute()
    print("Exported DICOM instances to bucket: gs://{}".format(uri_prefix))

    return response

フィルタを使用した DICOM インスタンスのエクスポート

デフォルトでは、DICOM ファイルを Cloud Storage にエクスポートする際は、指定した DICOM ストア内のすべての DICOM ファイルがエクスポートされます。同様に、DICOM メタデータを BigQuery にエクスポートする際は、指定した DICOM ストア内のすべての DICOM データのメタデータがエクスポートされます。

フィルタを使用して、DICOM データまたはメタデータのサブセットをエクスポートできます。フィルタはフィルタ ファイルで定義します。

フィルタ ファイルを構成する

フィルタ ファイルでは、Cloud Storage または BigQuery にどの DICOM ファイルをエクスポートするかを定義します。フィルタ ファイルは次のレベルで構成できます。

  • スタディレベル
  • シリーズ レベル
  • インスタンス レベル

フィルタ ファイルは、エクスポートするスタディ、シリーズ、インスタンスをそれぞれ定義する行を含む、複数の行で構成されます。各行には /studies/STUDY_UID[/series/SERIES_UID[/instances/INSTANCE_UID]] 形式を使用します。

フィルタ ファイルで渡す際に、フィルタ ファイルにスタディ、シリーズ、またはインスタンスが指定されていない場合、そのスタディ、シリーズ、インスタンスはエクスポートされません。

パスの /studies/STUDY_UID の部分のみが必須です。/studies/STUDY_UID を指定してスタディ全体をエクスポートするか、/studies/STUDY_UID/series/SERIES_UID を指定してシリーズ全体をエクスポートすることが可能です。

次のフィルタ ファイルについて考えてみましょう。このフィルタ ファイルを使用すると、1 つのスタディ、2 つのシリーズ、3 つの個別のインスタンスがエクスポートされます。

/studies/1.123.456.789
/studies/1.666.333.111/series/123.456
/studies/1.666.333.111/series/567.890
/studies/1.888.999.222/series/123.456/instances/111
/studies/1.888.999.222/series/123.456/instances/222
/studies/1.888.999.222/series/123.456/instances/333

BigQuery を使用したフィルタ ファイルの作成

通常、フィルタ ファイルを作成するには、まず DICOM ストアから BigQuery にメタデータをエクスポートします。これにより、BigQuery を使用して、DICOM ストア内の DICOM データのスタディ UID、シリーズ UID、インスタンス UID を表示できます。次に、以下の手順を行います。

  1. 目的のスタディ UID、シリーズ UID、インスタンス UID にクエリを実行します。たとえば、DICOM メタデータを BigQuery にエクスポートした後、次のクエリを実行してスタディ UID、シリーズ UID、インスタンス UID をフィルタ ファイル要件と互換性のある形式に連結できます。
    SELECT CONCAT
        ('/studies/', StudyInstanceUID, '/series/', SeriesInstanceUID, '/instances/', SOPInstanceUID)
    FROM
        [PROJECT_ID:BIGQUERY_DATASET.BIGQUERY_TABLE]
    
  2. クエリが大規模な結果セットを返す場合、クエリ結果を BigQuery の宛先テーブルに保存することで、新しいテーブルを実体化できます。
  3. クエリ結果を宛先テーブルに保存する場合は、宛先テーブルの内容をファイルに保存し、Cloud Storage にエクスポートできます。この手順については、テーブルデータのエクスポートをご覧ください。エクスポートされるファイルはフィルタ ファイルです。エクスポート オペレーションでフィルタを指定するときは、Cloud Storage 内のフィルタ ファイルの場所を使用します。

フィルタ ファイルを手動で作成する

カスタム コンテンツを含むフィルタ ファイルを作成し、Cloud Storage バケットにアップロードできます。エクスポート オペレーションでフィルタを指定するときは、Cloud Storage 内のフィルタ ファイルの場所を使用します。次のサンプルは、gsutil cp コマンドを使用してフィルタ ファイルを Cloud Storage バケットにアップロードする方法を示しています。
gsutil cp PATH/TO/FILTER_FILE gs://BUCKET/DIRECTORY

フィルタ ファイルで渡す

フィルタ ファイルを作成したら、DICOM エクスポート オペレーションを呼び出し、REST API を使用してフィルタ ファイルに渡します。以下のサンプルでは、フィルタを使用して DICOM データをエクスポートする方法が示されます。

gcloud

フィルタを使用して DICOM メタデータを Cloud Storage にエクスポートするには、gcloud beta healthcare dicom-stores export gcs コマンドを使用します。

gcloud beta healthcare dicom-stores export gcs DICOM_STORE_ID \
  --dataset=DATASET_ID \
  --location=LOCATION \
  --gcs-uri-prefix=gs://DESTINATION_BUCKET/DIRECTORY \
  --filter-config-gcs-uri=gs://BUCKET/DIRECTORY/FILTER_FILE

以下を置き換えます。

  • DICOM_STORE_ID: DICOM ストアの ID
  • DATASET_ID: DICOM ストアの親データセットの名前
  • LOCATION: DICOM ストアの親データセットの場所
  • DESTINATION_BUCKET/DIRECTORY: 転送先の Cloud Storage バケット
  • BUCKET/DIRECTORY/FILTER_FILE: Cloud Storage バケット内のフィルタ ファイルの場所

次のような出力が表示されます。

Request issued for: [DICOM_STORE_ID]
Waiting for operation [projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID] to complete...done.
name: projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID

オペレーションのステータスを表示するには、レスポンスの OPERATION_ID を指定して gcloud healthcare operations describe コマンドを実行します。

gcloud healthcare operations describe OPERATION_ID \
  --location=LOCATION \
  --dataset=DATASET_ID

以下を置き換えます。

  • OPERATION_ID: 前のレスポンスから返された ID 番号
  • DATASET_ID: DICOM ストアの親データセットの名前
  • LOCATION: DICOM ストアの親データセットの場所

次のような出力が表示されます。

done: true
metadata:
'@type': type.googleapis.com/google.cloud.healthcare.v1beta1.OperationMetadata
apiMethodName: google.cloud.healthcare.v1beta1.dicom.DicomService.ExportDicomData
counter:
  success: SUCCESSFUL_INSTANCES
  failure: FAILED_INSTANCES
createTime: 'CREATE_TIME'
endTime: 'END_TIME'
logsUrl: 'https://console.cloud.google.com/logs/viewer/CLOUD_LOGGING_URL'
name: projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID
response:
'@type': '...'

API

フィルタを使用して DICOM データをエクスポートするには、projects.locations.datasets.dicomStores.export メソッドを使用します。

curl

フィルタ ファイルを使用して DICOM データをエクスポートするには、POST リクエストを行い、次の情報を指定します。

  • 親データセットの名前と場所
  • DICOM ストアの名前
  • 宛先の Cloud Storage バケット。
  • Cloud Storage バケット内のフィルタ ファイルの場所

次のサンプルは、curl を使用した POST リクエストを示しています。

curl -X POST \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    -H "Content-Type: application/json; charset=utf-8" \
    --data "{
      'gcsDestination': {
        'uriPrefix': 'gs://BUCKET/DIRECTORY'
      },
      'filterConfig': {
        'resourcePathsGcsUri': 'gs://BUCKET/DIRECTORY/FILTER_FILE'
      }
    }" "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/REGION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID:export"

リクエストが成功すると、サーバーは JSON 形式の次のレスポンスを返します。

{
  "name": "projects/PROJECT_ID/locations/REGION/datasets/DATASET_ID/operations/OPERATION_ID"
}

レスポンスにはオペレーション名が含まれています。オペレーション get メソッドを使用して、オペレーションのステータスを追跡します。

curl -X GET \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/REGION/datasets/DATASET_ID/operations/OPERATION_NAME"

リクエストが成功すると、サーバーは JSON 形式で次のレスポンスを返します。

{
  "name": "projects/PROJECT_ID/locations/REGION/datasets/DATASET_ID/operations/OPERATION_ID",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.healthcare.v1beta1.OperationMetadata",
    "apiMethodName": "google.cloud.healthcare.v1beta1.dicom.DicomService.ExportDicomData",
    "createTime": "CREATE_TIME",
    "endTime": "END_TIME"
  },
  "done": true,
  "response": {
    "@type": "..."
  }
}

PowerShell

フィルタ ファイルを使用して DICOM データをエクスポートするには、POST リクエストを行い、次の情報を指定します。

  • 親データセットの名前と場所
  • DICOM ストアの名前
  • 宛先の Cloud Storage バケット。
  • Cloud Storage バケット内のフィルタ ファイルの場所

次のサンプルは、Windows PowerShell を使用した POST リクエストを示しています。

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

Invoke-WebRequest `
  -Method Post `
  -Headers $headers `
  -ContentType: "application/json; charset=utf-8" `
  -Body "{
    'gcsDestination': {
      'uriPrefix': 'gs://BUCKET/DIRECTORY'
    },
    'filterConfig': {
      'resourcePathsGcsUri': 'gs://BUCKET/DIRECTORY/FILTER_FILE'
  }" `
  -Uri "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/REGION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID:export" | Select-Object -Expand Content

リクエストが成功すると、サーバーは JSON 形式の次のレスポンスを返します。

{
  "name": "projects/PROJECT_ID/locations/REGION/datasets/DATASET_ID/operations/OPERATION_ID"
}

レスポンスにはオペレーション名が含まれています。オペレーション get メソッドを使用して、オペレーションのステータスを追跡します。

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

Invoke-WebRequest `
  -Method Get `
  -Headers $headers `
  -Uri "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/REGION/datasets/DATASET_ID/operations/OPERATION_NAME" | Select-Object -Expand Content

リクエストが成功すると、サーバーはオペレーションのステータスを JSON 形式で返します。

{
  "name": "projects/PROJECT_ID/locations/REGION/datasets/DATASET_ID/operations/OPERATION_ID",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.healthcare.v1beta1.OperationMetadata",
    "apiMethodName": "google.cloud.healthcare.v1beta1.dicom.DicomService.ExportDicomData",
    "createTime": "CREATE_TIME",
    "endTime": "END_TIME"
  },
  "done": true,
  "response": {
    "@type": "..."
  }
}

DICOM エクスポート リクエストのトラブルシューティング

DICOM のエクスポート リクエスト中にエラーが発生した場合、エラーは Cloud Logging に記録されます。詳細については、Cloud Logging でのエラーログの表示をご覧ください。