> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ionworks.com/llms.txt
> Use this file to discover all available pages before exploring further.

# データの読み取り

> Python API でセル仕様、インスタンス、測定を一覧表示・フィルタリング・ページング・取得する方法を説明します

データをアップロードしたら、`ionworks-api` Python クライアントで読み戻せます。このページではリソースの一覧とフィルタリング、完全な測定詳細の取得、ローカルキャッシング、Python 内でのプロット、エラー処理について説明します。

インストールと認証については[Python API クライアント](/ja/api-client)ページを参照してください。アップロードについては[データのアップロード](/ja/data/uploading)を参照してください。

<Tip>
  どのセル仕様、インスタンス、測定の ID も、Ionworks Studio のデータ可視化ページから確認できます。ID は URL と詳細パネルに表示されます。
</Tip>

## リソースの一覧

```python theme={null}
# List cell specifications (first page)
specs = client.cell_spec.list()
for spec in specs[:5]:
    print(f"  - {spec.name} (form_factor: {spec.form_factor})")

# Get a specific cell spec with full nested data
full_spec = client.cell_spec.get(spec_id)
print(f"Capacity: {full_spec.ratings['capacity']['value']} "
      f"{full_spec.ratings['capacity']['unit']}")

# List instances for a spec and pick the first
instances = client.cell_instance.list(spec_id)
instance = instances[0]

# List measurements for an instance
measurements = client.cell_measurement.list(instance.id)
```

## フィルタリングと並び替え

すべての `list()` メソッドはキーワード専用のフィルタパラメータを受け入れるため、すべてを取得してから Python でフィルタリングする代わりに、サーバー側で結果を絞り込めます。

```python theme={null}
# Search cell specs by name (case-insensitive substring match)
specs = client.cell_spec.list(name="graphite")

# Exact name match
specs = client.cell_spec.list(name_exact="NCM622/Graphite Coin Cell")

# Filter by form factor (cell specs only)
specs = client.cell_spec.list(form_factor="R2032")

# Filter by creator
specs = client.cell_spec.list(created_by_email="jane")

# Date range filters
specs = client.cell_spec.list(
    created_after="2026-01-01T00:00:00Z",
    created_before="2026-04-01T00:00:00Z",
)

# Sort results
specs = client.cell_spec.list(order_by="created_at", order="desc")
```

フィルタは 3 つのリソースタイプすべてで同じように動作し、1 回の呼び出しでページングや並び替えと組み合わせられます:

```python theme={null}
instances = client.cell_instance.list(
    spec_id,
    limit=50,
    offset=0,
    name="batch-A",
    order_by="updated_at",
    order="desc",
)

measurements = client.cell_measurement.list(
    instance_id,
    measurement_type="time_series",
    created_after="2026-03-01T00:00:00Z",
    order_by="created_at",
    order="asc",
)
```

セル測定では測定開始時刻に対する追加の日付フィルタがサポートされます:

```python theme={null}
measurements = client.cell_measurement.list(
    instance_id,
    started_after="2026-03-01T00:00:00Z",
    started_before="2026-03-31T23:59:59Z",
)
```

### フィルタパラメータ

| パラメータ              | 型     | 説明                                                                  | 利用可能対象                |
| ------------------ | ----- | ------------------------------------------------------------------- | --------------------- |
| `name`             | `str` | 名前への大文字小文字を区別しない部分一致。                                               | すべて                   |
| `name_exact`       | `str` | 名前の完全一致。`name` より優先される。                                             | すべて                   |
| `form_factor`      | `str` | フォームファクターの完全一致。                                                     | `cell_spec` のみ        |
| `measurement_type` | `str` | 測定タイプ（`"time_series"`、`"properties"`、`"file"`）でフィルタ。                | `cell_measurement` のみ |
| `created_by_email` | `str` | 作成者メールへの大文字小文字を区別しない部分一致。                                           | すべて                   |
| `created_after`    | `str` | ISO datetime、この時刻以降に作成されたレコード。                                      | すべて                   |
| `created_before`   | `str` | ISO datetime、この時刻以前に作成されたレコード。                                      | すべて                   |
| `updated_after`    | `str` | ISO datetime、この時刻以降に更新されたレコード。                                      | すべて                   |
| `updated_before`   | `str` | ISO datetime、この時刻以前に更新されたレコード。                                      | すべて                   |
| `started_after`    | `str` | ISO datetime、この時刻以降に開始された測定。                                        | `cell_measurement` のみ |
| `started_before`   | `str` | ISO datetime、この時刻以前に開始された測定。                                        | `cell_measurement` のみ |
| `order_by`         | `str` | ソートする列（`"name"`、`"created_at"`、`"updated_at"`、測定では `"start_time"`）。 | すべて                   |
| `order`            | `str` | ソート方向: `"asc"` または `"desc"`。                                        | すべて                   |

<Note>
  フィルタパラメータは互いに自由に組み合わせられ、`limit`/`offset` ページングパラメータとも組み合わせられます。返される `PaginatedList` の `.total` プロパティは、フィルタ適用後の総数を反映します。
</Note>

## ページング

すべての `list()` 呼び出しは `PaginatedList` を返します。`limit` と `offset` パラメータでどのページを取得するか制御します。

```python theme={null}
page = client.cell_spec.list(limit=50, offset=0)
print(f"Showing {page.count} of {page.total} specs")

next_page = client.cell_spec.list(limit=50, offset=50)
```

| パラメータ    | 型     | デフォルト            | 説明                     |
| -------- | ----- | ---------------- | ---------------------- |
| `limit`  | `int` | サーバーデフォルト (1000) | 返すアイテムの最大数（1 から 1000）。 |
| `offset` | `int` | `0`              | 結果を返す前にスキップするアイテム数。    |

返される `PaginatedList` は通常の Python リストのように動作（反復、インデックス、長さチェック）し、さらに次のプロパティを公開します:

| プロパティ    | 説明                       |
| -------- | ------------------------ |
| `.items` | 現在のページの結果リスト。            |
| `.total` | すべてのページにわたるマッチするレコードの総数。 |
| `.count` | 現在のページのアイテム数。            |

すべての結果を反復するには:

```python theme={null}
all_specs = []
offset = 0
limit = 100
while True:
    page = client.cell_spec.list(limit=limit, offset=offset)
    all_specs.extend(page.items)
    if len(all_specs) >= page.total:
        break
    offset += limit
```

## 名前による測定の解決

測定とその親の人間可読な名前は分かっているが ID が分からない場合、spec → instance → measurement の階層を手作業でたどる代わりに `client.resolve_measurement()` を使えます:

```python theme={null}
measurement = client.resolve_measurement(
    cell_specification="NCM622/Graphite Coin Cell",
    cell_instance="Cell A #1",
    measurement="RPT 0",
)

# 解決された ID を以降の API 呼び出しに利用
detail = client.cell_measurement.detail(measurement.id)
```

このメソッドは各階層をサーバー側で名前完全一致でフィルタし、該当する `CellMeasurement` を返します。次の場合に `IonworksError` を送出します:

* `status_code=404`: いずれかの階層で一致が見つからなかった場合。
* `status_code=409`: 名前が親内で一意でない場合。この場合は ID で解決してください（例: Ionworks Studio のデータ可視化ページから）。

```python theme={null}
from ionworks import IonworksError

try:
    m = client.resolve_measurement("NCM622 Spec", "Cell A #1", "RPT 0")
except IonworksError as exc:
    if exc.status_code == 404:
        print("見つかりません — 名前を確認してください")
    elif exc.status_code == 409:
        print("名前が曖昧です — ID で解決してください")
    else:
        raise
```

## 測定詳細

`client.cell_measurement.detail()` は完全な測定を取得し、測定タイプに基づいてレスポンスを適応させます。

```python theme={null}
measurement_detail = client.cell_measurement.detail(measurement_id)
```

<Tabs>
  <Tab title="Time series">
    時系列データ、ステップ統計、サイクルメトリクスを返します:

    | フィールド              | 説明                                                         |
    | ------------------ | ---------------------------------------------------------- |
    | `measurement`      | 測定メタデータ（名前、プロトコル、テストセットアップ、メモ）                             |
    | `time_series`      | DataFrame としての完全な時系列データ（デフォルトは polars）                     |
    | `steps`            | ステップレベル統計 DataFrame                                        |
    | `cycles`           | サイクルレベルメトリクス（容量、効率など） DataFrame                            |
    | `specification_id` | 親セル仕様の ID（`client.cell_spec.get(id)` で取得）                  |
    | `instance_id`      | 親セルインスタンスの ID（`client.cell_instance.get(spec_id, id)` で取得） |

    ```python theme={null}
    detail = client.cell_measurement.detail(measurement_id)
    print(f"Time series shape: {detail.time_series.shape}")
    print(detail.cycles.head())
    ```
  </Tab>

  <Tab title="Properties">
    プロパティを含む測定メタデータを返します。ファイルデータは取得されません。

    ```python theme={null}
    detail = client.cell_measurement.detail(measurement_id)
    props = detail.measurement.properties
    print(f"Thickness: {props['thickness']['value']} {props['thickness']['unit']}")
    ```
  </Tab>

  <Tab title="File">
    添付されたすべてのファイルをダウンロードし、ファイル名をバイト列にマップする `files` 辞書として返します:

    ```python theme={null}
    detail = client.cell_measurement.detail(measurement_id)
    for filename, content in detail.files.items():
        with open(filename, "wb") as f:
            f.write(content)
    ```
  </Tab>
</Tabs>

## Web アプリへのリンク

`client.urls.measurement()` を使用して、Ionworks Web アプリの測定詳細ページへのリンクを作成します。ノートブック、スクリプト、レポートからクリック可能なリンクを表示して、共同作業者が Ionworks Studio の測定に直接ジャンプできるようにする場合に便利です。

```python theme={null}
url = client.urls.measurement(measurement_id, project_id)
# https://app.ionworks.com/dashboard/projects/<project_id>/data/measurements/<measurement_id>
```

| パラメータ            | 型             | 説明                                                                                 |
| ---------------- | ------------- | ---------------------------------------------------------------------------------- |
| `measurement_id` | `str`         | リンク先の測定の ID。                                                                       |
| `project_id`     | `str \| None` | 測定が属するプロジェクトの ID。省略すると[クライアントに設定されたプロジェクト](/ja/api-client#デフォルトプロジェクト)にフォールバックします。 |

一般的なパターンは、測定を反復しながら各結果の隣にリンクをレンダリングすることです:

```python theme={null}
for m in client.cell_measurement.list(instance_id):
    print(f"{m.name}: {client.urls.measurement(m.id, project_id)}")
```

`client.urls` は、ルーティングされたすべてのリソース（study、simulation、parameterized model、pipeline、optimization、protocol、material、cell spec、cell instance）に対して同じヘルパーを公開しています。完全なリファレンスについては、[Web アプリ URL ヘルパー](/ja/api-client#web-アプリ-url-ヘルパー)を参照してください。

## Navigator: キャッシュ付きの階層走査

`Navigator` は、spec → instance → measurement の階層を走査し、すべての list / fetch 呼び出しをメモリ上にメモ化するオプトインのヘルパーです。1 つのスクリプトやノートブック内で複数の spec、instance、measurement を反復処理し、同じ API 呼び出しの繰り返しを避けたいときに使います。

`Navigator` を使うべきケース:

* 1 つ以上のセル仕様上のすべての測定をループする解析スクリプトを書いている。
* 反復順序を決定論的にしたい — 一覧は `name` でソートされて返されます。
* `limit` と `offset` を自分で管理せずに、ページングを自動で処理させたい。

基礎となるサブクライアント (`client.cell_spec`、`client.cell_instance`、`client.cell_measurement`) は引き続きメインの API です。`Navigator` はその上に乗る薄いレイヤーで、階層をキャッシュ済みの一貫したビューとして扱いたいときに使い、単発の読み取りや書き込みではサブクライアントを直接使ってください。

```python theme={null}
from ionworks import Ionworks, Navigator

nav = Navigator(Ionworks())

# すべての spec、instance、measurement を巡回する
for spec_name in nav.specs():
    for inst in nav.instances(spec_name):
        for m in nav.measurements(inst.id):
            ts = nav.time_series(m.id)
            steps = nav.steps(m.id)
            # ... 解析処理 ...
```

各エンティティは `Navigator` インスタンスごとに最大 1 回しか取得されません。`nav.instances("CellA")` を 2 回呼び出しても、2 回目の API 往復なしで同じリストが返されます。`measurements`、`steps`、`time_series` も同様です。

### 設定

```python theme={null}
nav = Navigator(client=Ionworks(), page_size=200)
```

| パラメータ       | 説明                                                                                   |
| ----------- | ------------------------------------------------------------------------------------ |
| `client`    | 既存の `Ionworks` クライアント。省略した場合はデフォルトのクライアントが作成されます (`IONWORKS_API_KEY` を環境変数から読み込みます)。 |
| `page_size` | `cell_instance.list` と `cell_measurement.list` のページング時の 1 ページあたりのアイテム数。デフォルトは `200`。 |

### 単一の spec を参照する

```python theme={null}
spec = nav.spec("CellA")
```

名前が一致しない場合、利用可能な spec 名のリストとともに `KeyError` を送出します — タイポの検出に便利です。

### キャッシュの無効化

電池データはアップロード後は不変なので、唯一の陳腐化要因は「プラットフォームに新しい兄弟エンティティが現れた」場合だけです。セッションの途中で新しいデータがアップロードされる可能性がある長時間動作のノートブックでは、キャッシュの一部または全体を破棄できます:

```python theme={null}
nav.clear()                                   # すべてを破棄
nav.invalidate(spec_name="CellA")             # CellA と、その instance および measurement を破棄
nav.invalidate(instance_id="inst_123")        # 1 つの instance と、その measurement を破棄
nav.invalidate(measurement_id="meas_456")     # 1 つの measurement の steps と time series を破棄
```

無効化は下方向にカスケードします: spec を破棄するとその instance と measurement も破棄され、instance を破棄するとその measurement も破棄されます。

<Note>
  `Navigator` はインスタンスの生存期間中、メモリ上にキャッシュします。プロセスをまたいだ、あるいはセッションをまたいだ測定データのディスクキャッシュについては、下記の [ローカルキャッシング](#ローカルキャッシング) を参照してください — 両レイヤーは組み合わせて利用できます。
</Note>

## ローカルキャッシング

`ionworks-api` クライアントは測定データをディスクに自動的にキャッシュし、繰り返しの読み取りを高速化し不要な API 呼び出しを回避します。キャッシングはデフォルトで有効で、`cell_measurement` の `steps`、`cycles`、`steps_and_cycles`、`time_series` メソッドに適用されます。

`client.cell_measurement.steps(measurement_id)` のようなメソッドを呼び出すと、クライアントは API リクエストを行う前にローカルキャッシュディレクトリを確認します。キャッシュされたコピーが存在し有効期限内であれば、それを直接返します。それ以外の場合、クライアントは API から取得し、結果をキャッシュして返します。

キャッシュされたデータはデフォルトで `~/.ionworksdata_cache` に Parquet ファイルとして保存され、1 時間で有効期限が切れます。

### キャッシュをスキップする

すべてのデータ取得メソッドは `use_cache` パラメータを受け入れます。`False` に設定すると、ローカルキャッシュからの読み取りも書き込みも行わずに新しい API 呼び出しを強制します:

```python theme={null}
steps = client.cell_measurement.steps(measurement_id, use_cache=False)
time_series = client.cell_measurement.time_series(measurement_id, use_cache=False)
```

### キャッシュの設定

```python theme={null}
import ionworks

ionworks.set_cache_directory("/path/to/custom/cache")
ionworks.set_cache_ttl(7200)              # 2 hours
ionworks.set_cache_ttl(None)              # never expire
ionworks.set_cache_enabled(False)
ionworks.set_cache_enabled(True)
deleted_count = ionworks.clear_cache()
```

| 関数                          | 説明                                                     |
| --------------------------- | ------------------------------------------------------ |
| `set_cache_enabled(bool)`   | キャッシングをグローバルに有効化・無効化します。                               |
| `get_cache_enabled()`       | キャッシングが現在有効かどうかを返します。                                  |
| `set_cache_directory(path)` | キャッシュファイルのディレクトリを設定します。デフォルト: `~/.ionworksdata_cache`。 |
| `set_cache_ttl(seconds)`    | TTL を秒単位で設定します。`None` で有効期限を無効化。デフォルト: `3600`。         |
| `get_cache_directory()`     | 現在のキャッシュディレクトリパスを返します。                                 |
| `get_cache_ttl()`           | 現在の TTL 値を返します。                                        |
| `clear_cache()`             | キャッシュされたすべてのファイルを削除し、削除した数を返します。                       |

<Note>
  キャッシュ設定はグローバルです。変更は同じ Python プロセス内のその後のすべての API 呼び出しに影響します。
</Note>

## Python からのプロット

`DataLoader` には、測定データを matplotlib ベースで素早く可視化する `plot_data()` メソッドが含まれています。プロットは電圧と電流の時間変化を表示し、温度データが利用可能な場合は追加の温度サブプロットを表示します。

```python theme={null}
from ionworksdata import DataLoader

loader = DataLoader.from_db("measurement-id-here")
fig, ax = loader.plot_data()
```

メソッドは matplotlib の `(Figure, Axes)` タプルを返すため、プロットをさらにカスタマイズできます。プロットを即座に表示するには `show=True` を渡します:

```python theme={null}
fig, ax = loader.plot_data(show=True)
```

<Note>
  `plot_data()` は時系列データがまだ取得されていない場合、サーバーから自動的に読み込みます。
</Note>

ブラウザ内のインタラクティブなビューア（フィルタ、ステップオーバーレイ、SQL 付き）については[データの可視化](/ja/data/visualizing)を参照してください。

## インライン時系列のサイズ制限

API 呼び出しに pandas または polars DataFrame を直接渡す場合（例: パイプライン設定の一部として）、クライアントはインライン時系列データに対して最大 **1,000 行** を強制します。同じ上限は `"file:..."` と `"folder:..."` 参照にも適用されます — これらはローカルマシンから読み取られ、送信時にクライアントによって内容がインライン化されるためです。より大きなデータセットは最初に測定としてアップロードし、ID で参照する必要があります。

```python theme={null}
from ionworks import MeasurementValidationError, IonworksError

try:
    client.pipeline.run(config_with_large_inline_df)
except MeasurementValidationError as e:
    # Specifically handle the size limit violation
    print(e)
    # "Time series has 5000 rows, which exceeds the maximum of 1000 rows
    #  for inline data. Upload the data as a measurement using
    #  client.cell_measurement.create() and reference it with
    #  'db:<measurement_id>' or iwdata.DataLoader.from_db(MEASUREMENT_ID)
    #  instead."
except IonworksError as e:
    print(e)
```

大きなデータセットを扱うには、まずアップロードして ID で参照します:

```python theme={null}
bundle = client.cell_measurement.create(instance_id, measurement_data)

from ionworksdata import DataLoader
loader = DataLoader.from_db(bundle.id)
```

### DataLoader 設定のエクスポート

データベース測定を参照する `DataLoader` があり、自己完結型の設定をエクスポートしたい場合（例: 同僚と共有するため）、`to_local()` でデータをインライン化します:

```python theme={null}
from ionworksdata import DataLoader

loader = DataLoader.from_db("measurement-id-here")
local_loader = loader.to_local()

# Now to_config() returns the full data instead of a DB reference
config = local_loader.to_config()
```

<Note>
  `to_local()` はすべての時系列とステップデータをサーバーから即座に取得します。非常に大きな測定では時間がかかることがあります。
</Note>

## エラー処理

クライアントは一般的なエラーケースに対して例外を発生させます:

* API 資格情報が欠落・無効
* API リクエストエラー（詳細付きで `IonworksError` を発生）
* 1,000 行を超えるインライン時系列（`IonworksError` のサブクラス `MeasurementValidationError` を発生）

```python theme={null}
from ionworks import IonworksError

try:
    client.cell_spec.list()
except IonworksError as e:
    print(f"API error: {e}")
```

`MeasurementValidationError` の処理パターンは上記の[インライン時系列のサイズ制限](#インライン時系列のサイズ制限)を参照してください。

### API エラー形式

すべての API エラーは一貫した JSON 構造を返します:

```json theme={null}
{
  "error_code": "CONFLICT",
  "message": "Cell specification with this name already exists",
  "detail": {
    "resource_type": "cell_specification",
    "resource_name": "My Cell Spec",
    "existing_id": "abc-123"
  }
}
```

| フィールド        | 型                | 説明                                                      |
| ------------ | ---------------- | ------------------------------------------------------- |
| `error_code` | `string`         | 機械可読のエラーコード（例: `NOT_FOUND`、`CONFLICT`、`BAD_REQUEST`）。   |
| `message`    | `string`         | 何が間違っているかの人間可読の説明。                                      |
| `detail`     | `object \| null` | エラーに関する追加コンテキスト（任意）。エラータイプによって異なり、エラーによっては存在しないことがあります。 |

一般的な HTTP ステータスコード:

| ステータス | エラーコード                | 説明                                                                     |
| ----- | --------------------- | ---------------------------------------------------------------------- |
| `400` | `BAD_REQUEST`         | リクエストが無効、または必須フィールドが欠落しています。                                           |
| `403` | `FORBIDDEN`           | このリソースにアクセスする権限がありません。API 資格情報が欠落または無効な場合にも返されます（API は `401` を使用しません）。 |
| `404` | `NOT_FOUND`           | リクエストされたリソースが存在しません。                                                   |
| `409` | `CONFLICT`            | 同じ名前または識別子のリソースがすでに存在します。`detail` フィールドに `existing_id` が含まれることがあります。   |
| `429` | `USAGE_LIMIT_REACHED` | この請求サイクルで組織の使用量クォータを超えました。                                             |

## 完全な API リファレンス

完全な Python API リファレンスは[ionworks-api ドキュメント](https://api.docs.ionworks.com/)を参照してください。

## 次のステップ

<CardGroup cols={2}>
  <Card title="データの可視化" icon="chart-line" href="/ja/data/visualizing">
    ブラウザ内のインタラクティブビューアでアップロードしたデータを探索します。
  </Card>

  <Card title="データのアップロード" icon="upload" href="/ja/data/uploading">
    仕様、インスタンス、測定のエンドツーエンドアップロードワークフロー。
  </Card>

  <Card title="測定" icon="flask" href="/ja/data/measurements">
    3 つの測定タイプの詳細。
  </Card>

  <Card title="シミュレーション API" icon="play" href="/ja/simulate/api">
    Python API でシミュレーションとパイプラインを実行します。
  </Card>
</CardGroup>
