> ## 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.

# 装置

> ラボをサイト・サイクラー・チャンネルとしてモデル化し、各セル測定を実行されたチャンネルに紐付けます

Ionworks Studio では、測定データの出どころとなる物理的なラボ装置——**サイト**、
**サイクラー**、**チャンネル**——を管理でき、
[セル測定](/ja/data/measurements)を実行されたチャンネルに直接紐付けられます。
これによりデータ点から生成元のハードウェアまでを end-to-end で辿れるようになり、
[ラボビュー](/ja/operate/lab-view)の表示もこの情報に基づいています。

## 使い分け

装置の記録は任意です。`channel_id` がなくても測定は問題なく機能します。
次のようなことをしたい場合にサイト・サイクラー・チャンネルを設定してください：

* 複数のサイクラーやラボにまたがるデータを比較する。
* 一部の測定結果がおかしいときに、疑わしいチャンネルを切り分ける。
* 規制対象データや公開データの長期的なトレーサビリティを保つ。
* どのチャンネルが空いている / 使用中 / サービス外かを一目で把握する。

サイクラーが 1 台だけでこのレベルの詳細が不要な場合は、各測定の自由記述
[`test_setup`](/ja/data/measurements#common-fields) フィールドを使い続けてください。

## 装置階層

試験装置はセルデータ階層と同じ構造です:

```
Organization
└── Site           (ラボ / 施設 — 組織スコープ、共有)
    └── Cycler     (バッテリーサイクラー — 単一プロジェクトに所属)
        └── Channel  (サイクラー上の単一テストチャンネル — 親サイクラーのプロジェクトを継承)
             └── channel_id 経由でセル測定にリンク
```

| リソース      | スコープ         | 説明                                                                     |
| --------- | ------------ | ---------------------------------------------------------------------- |
| `site`    | Organization | 物理的なラボまたは施設。組織内で名前が一意です（大文字小文字を区別しません）。                                |
| `cycler`  | Project      | サイトに設置されたバッテリーサイクリング装置。作成時に指定した単一プロジェクトが所有します。                         |
| `channel` | Project (継承) | サイクラー上の単一テストチャンネル。親サイクラーのプロジェクトを継承します — `project_id` を自分で設定することはありません。 |

チャンネルと**同じプロジェクト**のセル測定のみをリンクできます。サイトを削除するとそのサイクラーもカスケード削除され、サイクラーを削除するとそのチャンネルもカスケード削除されます。

### サイト

**サイト**はサイクラーを保有するラボまたは施設です。サイトは**組織スコープ**です。

| フィールド      | 説明                 |
| ---------- | ------------------ |
| `name`     | サイトの名前（必須、組織内で一意）  |
| `location` | 物理的な所在地（例: 住所やラボ名） |
| `notes`    | 自由形式のメモ            |

### サイクラー

**サイクラー**は、ちょうど 1 つのサイトに設置されたサイクリング装置です。サイクラーは**プロジェクトスコープ**で、各サイクラーは作成時に指定した 1 つの[プロジェクト](/ja/core-concepts/projects-studies)によって所有されます。サイクラー名はプロジェクト内で一意（大文字小文字を区別しない）なので、異なる 2 つのプロジェクトがそれぞれ `"Maccor-1"` という名前のサイクラーを持つことができます。

所有プロジェクトは作成時に固定されます。同じ物理的な装置を 2 つのプロジェクトで使用する場合は、プロジェクトごとに 1 つのサイクラー行を作成してください。

| フィールド          | 説明                                   |
| -------------- | ------------------------------------ |
| `name`         | サイクラーの名前（必須、プロジェクト内で一意）              |
| `project_id`   | サイクラーを所有するプロジェクト（必須）                 |
| `manufacturer` | 例: `"Arbin"`、`"Maccor"`、`"Biologic"` |
| `model`        | 例: `"S4000"`                         |
| `notes`        | 自由形式のメモ                              |

### チャンネル

**チャンネル**はサイクラー上の物理チャンネルです。チャンネルはちょうど 1 つのサイクラーに属し、そのサイクラーのプロジェクトを継承します。チャンネル名はサイクラー内で一意（大文字小文字を区別しない）なので、異なる 2 つのサイクラーがそれぞれ `"CH1"` という名前のチャンネルを持つことができます。

| フィールド   | 説明                     |
| ------- | ---------------------- |
| `name`  | チャンネルの名前（必須、サイクラー内で一意） |
| `notes` | 自由形式のメモ                |

チャンネルには任意の電気的定格と `out_of_commission` フラグもあります — 下記の[チャンネル定格](#チャンネル定格)を参照してください。

## 装置ツリーの構築

サイト・サイクラー・チャンネルはラボごとに一度作成します。定常運用ではチャンネルのみを操作します — `out_of_commission` の切り替え、定格の調整、測定のリンクなどです。

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

client = Ionworks(project_id="your-project-id")

# 1. サイトを作成（またはフェッチ）— 組織スコープでプロジェクト間で共有。
site = client.site.create_or_get({
    "name": "Main lab",
    "location": "Building 3, Room 210",
})

# 2. サイトの下にサイクラーを作成。project_id は必須 — サイクラーは
#    そのプロジェクトが所有します。
cycler = client.cycler.create_or_get(
    site.id,
    {
        "name": "Cycler-01",
        "manufacturer": "Arbin",
        "model": "LBT-5V-6A",
        "project_id": client.project_id,
    },
)

# 3. サイクラー上にチャンネルを作成し、任意で電気的定格を設定します。
for i in range(1, 9):
    client.channel.create_or_get(
        cycler.id,
        {
            "name": f"Ch-{i:02d}",
            "max_amps": 6.0,
            "min_volts": 0.0,
            "max_volts": 5.0,
        },
    )
```

<Note>
  名前はサイトなら組織内、サイクラーならプロジェクト内、チャンネルならサイクラー内で、それぞれ大文字小文字を区別せず一意ですが、`create_or_get` は名前が完全に一致する場合にのみ既存レコードへの競合解決を行います。既に存在する名前と大文字小文字が異なる名前（例: `"Boston Lab"` が存在するときに `"boston lab"`）で呼び出すと、既存のレコードを返す代わりに `ValueError` が発生します。作成時と同じ完全な名前を再利用してください。
</Note>

更新と削除はいずれも同じ方法です:

```python theme={null}
# 更新（部分更新）。新しい site_id を渡すと、同じ組織内の別サイトに
# サイクラーを移動できます。所有プロジェクトは変更できません。新しい
# cycler_id を渡すとチャンネルの親を付け替えられますが、同じプロジェクト内の
# 別サイクラーに限ります。
client.cycler.update(cycler.id, {"model": "S4000M"})

# 削除 — 階層を下方向にカスケードします（サイト -> サイクラー -> チャンネル）。
# チャンネルを削除すると、それを参照していた測定の channel_id は NULL に戻ります。
# 測定自体は削除されません。
client.cycler.delete(cycler.id)
```

| 削除対象  | 影響                                               |
| ----- | ------------------------------------------------ |
| サイト   | 配下のすべてのサイクラーとそのチャンネルを削除                          |
| サイクラー | 配下のすべてのチャンネルを削除                                  |
| チャンネル | これを参照していた測定の `channel_id` を `NULL` に設定。測定は保持されます |

## 測定をチャンネルに紐付ける

すべての[セル測定](/ja/data/measurements)には、試験を実行した物理チャンネルを記録する null 許容の `channel_id` があります。測定を作成するときに設定するか、後から更新で付け替えられます。

チャンネルは測定と**同じプロジェクト**に属している必要があります（測定はそのセルインスタンスからプロジェクトを継承します）。別のプロジェクトのチャンネルを指定するとエラー（HTTP 400）になります。

このリンクは意図的にゆるく作られています: 後からチャンネルを削除すると `channel_id` は `NULL` に戻り、測定はそのまま残ります。

```python theme={null}
channels = client.channel.list(cycler.id)
ch01 = next(c for c in channels if c.name == "Ch-01")

bundle = client.cell_measurement.create(
    cell_instance.id,
    {
        "measurement": {
            "name": "Formation Cycle 1",
            "channel_id": ch01.id,
        },
        "time_series": time_series,
    },
)

# 既存の測定にチャンネルを付ける／付け替える
client.cell_measurement.update(bundle.id, {"channel_id": ch01.id})

# 測定を削除せずに切り離す
client.cell_measurement.update(bundle.id, {"channel_id": None})
```

テスト実行中は測定の `end_time` を未設定のままにし、鮮度の高いデータをアップロードし続けます — チャンネルは `occupied` として表示されます。テストが完了したら、測定を `end_time` でパッチすると、チャンネルは `free` に戻ります。

### チャンネルがいつ空くかを表示する

測定に `estimated_end_time` を設定すると、実行中のテストが終了する予定時刻を通知できます。チャンネルが `occupied` または `stale` の間、ラボビューはチャンネルカードにこの値を表示するため、測定を開かなくても次のテストを計画できます。

```python theme={null}
from datetime import datetime, timedelta, timezone

client.cell_measurement.update(
    measurement_id,
    {
        "estimated_end_time": (
            datetime.now(timezone.utc) + timedelta(hours=18)
        ).isoformat(),
    },
)
```

`estimated_end_time` はあくまで参考情報です — チャンネルの占有状態や 48 時間の鮮度ウィンドウには影響しません。部分更新は含めたフィールドのみを設定するため、`end_time` だけをパッチしても保存済みの推定値はそのまま残ります — クリアするには、同じ更新で `estimated_end_time` を明示的に `None` に設定してください。

## チャンネル定格

チャンネルには、ハードウェアの能力を記述する任意の電気的定格があります。ラボ UI は新規テスト用のチャンネルを選ぶ際にこれらでフィルタリングします。

| フィールド               | 型               | 説明                                                      |
| ------------------- | --------------- | ------------------------------------------------------- |
| `max_amps`          | `float \| null` | 最大定格電流 (A)。`null` は未指定を意味します。                           |
| `min_volts`         | `float \| null` | 最小定格電圧 (V)。`null` は未指定を意味します。                           |
| `max_volts`         | `float \| null` | 最大定格電圧 (V)。`null` は未指定を意味します。                           |
| `out_of_commission` | `bool`          | `true` はチャンネルをサービス外としてマークします。派生占有状態を上書きします。既定は `false`。 |

定格は UI ではなく API または SDK 経由で設定します。

## フィルタリング、ページング、名前による解決

サイト・サイクラー・チャンネルのリストエンドポイントは、API 全体で共通のフィルタ形式に従います — `name` に対する大文字小文字を区別しない部分一致、`name_exact` による完全一致、ISO 日時レンジフィルタ（`created_after` / `updated_before` / ...）、および `order_by` / `order` によるソートです。

```python theme={null}
# 現在のプロジェクトが所有するサイト内のすべてのサイクラー
cyclers = client.cycler.list(site.id, project_id=client.project_id)

# サイクラー上のすべてのチャンネルを 1 ページで取得
channels = client.channel.list(cycler.id, limit=100)
print(channels.total)
```

サイトとサイクラーについては、`client.site.detail(site_id)` および `client.cycler.detail(cycler_id)` がリソースとその子要素すべてを 1 レスポンスで返し、ページングも自動処理します。

`name_exact` は大文字小文字を区別するサーバー側の完全一致です — 人間が読めるサイト名からチャンネル ID までたどる最も簡単な方法です:

```python theme={null}
site = client.site.list(name_exact="Boston Lab")[0]
cycler = client.cycler.list(site.id, name_exact="Cycler-01")[0]
channel = client.channel.list(cycler.id, name_exact="Ch-01")[0]

print(site.id, cycler.id, channel.id)
```

`name_exact` を使った場合でも各 `list()` は `PaginatedList` を返すため、名前が存在しない可能性がある場合は空のケースを扱ってください。

## 次のステップ

<CardGroup cols={2}>
  <Card title="ラボビュー" icon="grid-2" href="/ja/operate/lab-view">
    ライブの占有状況を確認し、チャンネルを詳しく見て、実行中の内容を把握します。
  </Card>

  <Card title="チャンネルサービス" icon="wrench" href="/ja/operate/channel-service">
    チャンネルをサービス外にし、インシデント履歴を確認します。
  </Card>
</CardGroup>
