Models#
Pydantic models for API request and response validation.
Pydantic models for the Ionworks API client.
These models use extra=”allow” to accept any fields from the API response, letting the API handle validation. Required fields are kept minimal.
- class ionworks.models.PaginatedList(items, total)[source]#
Bases:
Generic[_T]A list-like container that also carries pagination metadata.
Returned by
list()methods whenlimitoroffsetis provided. Behaves like a regularlistfor iteration, indexing, truthiness, andlen()so callers can treat it interchangeably withlist[T].- Parameters:
- items#
- total#
- ionworks.models.create_or_get(*, create, get_by_id, find_by_name, name, resource_label)[source]#
Create a resource, or return the existing one on a name conflict.
Shared conflict-resolution used by the equipment sub-clients. Calls
create; on anIonworksErrorthat is a CONFLICT (error_code == "CONFLICT"or HTTP 409), resolves the existing resource — first by theexisting_idechoed in the error detail, then byfind_by_nameas a fallback. Any non-conflict error propagates unchanged.- Parameters:
create (Callable[[], _T]) – Zero-arg thunk that performs the create and returns the new resource.
get_by_id (Callable[[str], _T]) – Fetch a resource by id (used with the conflict’s
existing_id).find_by_name (Callable[[str], _T | None]) – Look up the existing resource by its (conflicting) name; returns
Noneif not found.name (str | None) – The name that was being created, used for the fallback lookup and the error message.
resource_label (str) – Human-readable resource name for the “duplicate but not found” error (e.g.
"Cycler").
- Returns:
The newly created resource, or the pre-existing one on conflict.
- Return type:
_T
- Raises:
ValueError – If the create reported a duplicate but the existing resource could not be resolved by id or name.
- class ionworks.models.CellSpecification(*, id, name, **extra_data)[source]#
Bases:
BaseModelCell specification model - accepts any fields from the API.
The API returns nested component/material data and ratings objects. This model is permissive to allow the API to define the schema.
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.Site(*, id, name, **extra_data)[source]#
Bases:
BaseModelSite model - accepts any fields from the API.
A site is an organization-scoped physical location that owns cyclers.
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.Cycler(*, id, name, site_id, project_id, manufacturer=None, model=None, version=None, serial_number=None, firmware_version=None, hostname=None, ip_address=None, port=None, last_calibrated_at=None, calibration_interval_days=None, calibration_due_at=None, **extra_data)[source]#
Bases:
BaseModelCycler model - accepts any fields from the API.
A cycler is battery test equipment that belongs to a site, is owned by one project, and owns channels.
- Parameters:
id (str)
name (str)
site_id (str)
project_id (str)
manufacturer (str | None)
model (str | None)
version (str | None)
serial_number (str | None)
firmware_version (str | None)
hostname (str | None)
ip_address (str | None)
port (int | None)
last_calibrated_at (datetime | None)
calibration_interval_days (int | None)
calibration_due_at (datetime | None)
extra_data (Any)
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- version: str | None#
Hardware/product version. Distinct from
firmware_version, which changes without the hardware changing. Nullable.
- last_calibrated_at: datetime | None#
When the cycler was last calibrated. Null means never calibrated or not tracked — read as unknown, not as overdue.
- class ionworks.models.CyclerServiceEvent(*, id, cycler_id, project_id, event_type, scheduled_for=None, scheduled_until=None, performed_at=None, notes=None, created_by=None, performed_by=None, **extra_data)[source]#
Bases:
BaseModelOne instrument-level service on a cycler.
Calibration and preventive maintenance are performed on the instrument, so a 40-channel cycler going in for its annual calibration is one event, not 40 unrelated channel outages. Opening an event takes every channel out of service together; completing it returns them together.
A cycler has at most one open event (
performed_atis None) at a time.- Parameters:
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.Channel(*, id, name, cycler_id, project_id, notes=None, out_of_commission=False, max_amps=None, min_volts=None, max_volts=None, **extra_data)[source]#
Bases:
BaseModelChannel model - accepts any fields from the API.
A channel is an individual test channel belonging to a cycler; it inherits its cycler’s project.
- Parameters:
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.ChannelIncident(*, id, channel_id, project_id, service_event_id=None, category='other', notes=None, service_scheduled_at=None, service_scheduled_until=None, started_at, resolved_at=None, resolution_notes=None, started_by=None, resolved_by=None, is_estimated=False, **extra_data)[source]#
Bases:
BaseModelOne span during which a channel was out of service.
Opened when a channel is marked out of commission and closed when it returns, so a channel’s downtime is a history of spans rather than just the current
out_of_commissionflag. A channel has at most one open incident (resolved_atis None) at a time.An outage is either instrument-level or channel-local, and
service_event_idis what tells them apart: it is set for every channel taken down by a cycler calibration or PM visit, and None for a fault the channel had on its own (a failed relay is not a cycler event).- Parameters:
id (str)
channel_id (str)
project_id (str)
service_event_id (str | None)
category (str)
notes (str | None)
service_scheduled_at (datetime | None)
service_scheduled_until (datetime | None)
started_at (datetime)
resolved_at (datetime | None)
resolution_notes (str | None)
started_by (str | None)
resolved_by (str | None)
is_estimated (bool)
extra_data (Any)
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- service_event_id: str | None#
The instrument-level service this outage belongs to, when it is one. None for a channel-local fault.
- service_scheduled_at: datetime | None#
When the booked service is due to happen. None on unplanned outages and on backfilled rows, whose service was never scheduled.
- service_scheduled_until: datetime | None#
When the booked service is expected to end, making the outage a span rather than a start instant. A plan, not a guarantee — an outage may run past it, which is what
is_overdue_to_returnreports.
- started_at: datetime#
When the channel went out of service.
- is_estimated: bool#
True for backfilled rows whose
started_atis derived from the channel’s last-modified time and is only an upper bound. Exclude these from mean-time-to-repair arithmetic.
- property is_overdue_to_return: bool#
Whether an open outage has run past the end its service was booked to.
Derived when you ask rather than stored, because overrunning a booked window is a plan being wrong, not a record being invalid — the platform deliberately accepts it. Only an open outage can be overdue: once the channel is back it is back, however late.
- Returns:
True when the outage is still open, has a booked end, and that end is in the past.
- Return type:
- class ionworks.models.ChannelState(*values)[source]#
Bases:
StrEnumDerived occupancy state of a channel in the lab view.
- free = 'free'#
- occupied = 'occupied'#
- stale = 'stale'#
- out_of_commission = 'out_of_commission'#
- class ionworks.models.LabMeasurementSummary(*, id, name, start_time=None, estimated_end_time=None, updated_at, cell_instance_id, cell_instance_name=None, cell_specification_name=None, protocol_name=None, watched=False, **extra_data)[source]#
Bases:
BaseModelThe measurement occupying a channel (slim view for the lab wall).
- Parameters:
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- estimated_end_time: str | None#
ISO forecast finish time, if an estimate has been computed. Nullable. Informational only – doesn’t affect the derived occupancy state or the staleness window. The note explaining the estimate and the timestamp it was computed at aren’t part of this slim summary; fetch the full measurement (
client.cell_measurement.get(measurement_id)) for those.
- class ionworks.models.LabChannel(*, id, name, state, measurement=None, notes=None, out_of_commission=False, max_amps=None, min_volts=None, max_volts=None, **extra_data)[source]#
Bases:
BaseModelA channel with its derived occupancy state.
- Parameters:
id (str)
name (str)
state (ChannelState)
measurement (LabMeasurementSummary | None)
notes (str | None)
out_of_commission (bool)
max_amps (float | None)
min_volts (float | None)
max_volts (float | None)
extra_data (Any)
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- state: ChannelState#
- measurement: LabMeasurementSummary | None#
The measurement driving the state (occupied/stale); None when free/OOC.
- class ionworks.models.LabCycler(*, id, name, manufacturer=None, model=None, channel_count, occupied, stale, free, out_of_commission=0, channels=[], **extra_data)[source]#
Bases:
BaseModelA cycler with its channels and per-cycler occupancy counts.
- Parameters:
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- channels: list[LabChannel]#
- class ionworks.models.LabSite(*, id, name, cyclers=[], **extra_data)[source]#
Bases:
BaseModelA site grouping its cyclers for the lab wall.
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.LabStatus(*, sites=[], occupied=0, stale=0, free=0, out_of_commission=0, **extra_data)[source]#
Bases:
BaseModelThe full lab-view tree for a project plus project-level counts.
- Parameters:
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.FlatChannel(*, channel, cycler_id, cycler_name, site_id, site_name)[source]#
Bases:
BaseModelA lab channel flattened with its parent cycler and site context.
Returned by
LabClient.free_channels/stale_channelsso an answer reads as “CH3 on Maccor-1 at Boston Lab” without re-walking the tree.- Parameters:
channel (LabChannel)
cycler_id (str)
cycler_name (str)
site_id (str)
site_name (str)
- channel: LabChannel#
- model_config = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.Utilization(*, percent, occupied, stale, free, out_of_commission, total)[source]#
Bases:
BaseModelProject lab utilization: the frontend headline percent plus raw counts.
percentis the busy (occupied + stale) share of all channels (out-of-commission included in the denominator), rounded to a whole number to match the lab wall.0when there are no channels.- model_config = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.CellInstance(*, id, name, cell_specification_id, **extra_data)[source]#
Bases:
BaseModelCell instance model - accepts any fields from the API.
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.MeasurementType(*values)[source]#
Bases:
StrEnumType of data stored in a cell measurement.
- time_series = 'time_series'#
- file = 'file'#
- properties = 'properties'#
- class ionworks.models.CellMeasurement(*, id, name, cell_instance_id, measurement_type=MeasurementType.time_series, channel_id=None, start_time=None, end_time=None, estimated_end_time=None, estimated_end_time_note=None, estimated_end_time_calculated_at=None, processing_status=None, processing_error=None, **extra_data)[source]#
Bases:
BaseModelCell measurement model - accepts any fields from the API.
- Parameters:
id (str)
name (str)
cell_instance_id (str)
measurement_type (MeasurementType)
channel_id (str | None)
start_time (str | None)
end_time (str | None)
estimated_end_time (str | None)
estimated_end_time_note (str | None)
estimated_end_time_calculated_at (str | None)
processing_status (str | None)
processing_error (str | None)
extra_data (Any)
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- measurement_type: MeasurementType#
- channel_id: str | None#
Optional channel the measurement was recorded on. Nullable. Only valid on
time_seriesmeasurements, and requiresstart_timeto be set.
- start_time: str | None#
ISO-formatted time the test started. Nullable, but required when
channel_idis set (it defines when the channel became occupied).
- end_time: str | None#
ISO-formatted time the test finished. Nullable — a null
end_timemeans the test is still running (e.g. in the lab equipment view). Set it once the measurement is complete. Must not precedestart_time.
- estimated_end_time: str | None#
ISO forecast finish time for a still-running test, if an estimate has been computed. Nullable. Distinct from
end_time(the actual finish); informational only.
- estimated_end_time_note: str | None#
Free-text explanation of how
estimated_end_timewas derived. Nullable.
- estimated_end_time_calculated_at: str | None#
ISO-formatted time
estimated_end_timewas last computed. Nullable.
- processing_status: str | None#
Lifecycle of server-side step processing for uploaded
time_seriesmeasurements:pendingorrunningwhile the steps are still being derived,readyonce they are available,failedif the upload could not be processed.fileandpropertiesmeasurements never process steps and are alwaysready.
- class ionworks.models.CellMeasurementBundleResponse(*, id, name, cell_instance_id, measurement_type=MeasurementType.time_series, channel_id=None, start_time=None, end_time=None, estimated_end_time=None, estimated_end_time_note=None, estimated_end_time_calculated_at=None, processing_status=None, processing_error=None, steps_created, **extra_data)[source]#
Bases:
CellMeasurementFlat response from creating a measurement bundle.
Measurement fields (id, name, measurement_type, etc.) are at the top level alongside upload metadata.
- Parameters:
id (str)
name (str)
cell_instance_id (str)
measurement_type (MeasurementType)
channel_id (str | None)
start_time (str | None)
end_time (str | None)
estimated_end_time (str | None)
estimated_end_time_note (str | None)
estimated_end_time_calculated_at (str | None)
processing_status (str | None)
processing_error (str | None)
steps_created (int)
extra_data (Any)
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.UploadInfo(*, filename=None, signed_url, token, path)[source]#
Bases:
BaseModelSigned URL info for a single upload target.
- model_config = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.InitiateUploadResponse(*, measurement_id, uploads)[source]#
Bases:
BaseModelResponse from the initiate-upload endpoint for signed URL uploads.
- Parameters:
measurement_id (str)
uploads (list[UploadInfo])
- uploads: list[UploadInfo]#
- model_config = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.InitiateRawDataUploadResponse(*, raw_data_id, uploads)[source]#
Bases:
BaseModelResponse from the raw-data initiate-upload endpoint.
- Parameters:
raw_data_id (str)
uploads (list[UploadInfo])
- uploads: list[UploadInfo]#
- model_config = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.CellMeasurementDetail(*, id, name, cell_instance_id, measurement_type=MeasurementType.time_series, channel_id=None, start_time=None, end_time=None, estimated_end_time=None, estimated_end_time_note=None, estimated_end_time_calculated_at=None, processing_status=None, processing_error=None, specification_id=None, instance_id=None, steps=None, time_series=None, cycles=None, files=None, **extra_data)[source]#
Bases:
CellMeasurementFlat detail model for a measurement with steps and time series.
Measurement fields (id, name, measurement_type, etc.) are at the top level alongside optional data payloads. Returns minimal data by default: foreign keys for parent objects rather than nested objects. Use the spec/instance clients to fetch parent objects if needed.
- Parameters:
id (str)
name (str)
cell_instance_id (str)
measurement_type (MeasurementType)
channel_id (str | None)
start_time (str | None)
end_time (str | None)
estimated_end_time (str | None)
estimated_end_time_note (str | None)
estimated_end_time_calculated_at (str | None)
processing_status (str | None)
processing_error (str | None)
specification_id (str | None)
instance_id (str | None)
steps (DataFrame | DataFrame | None)
time_series (DataFrame | DataFrame | None)
cycles (DataFrame | DataFrame | None)
extra_data (Any)
- model_config = {'arbitrary_types_allowed': True, 'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.CellInstanceDetail(*, instance, specification_id, measurements)[source]#
Bases:
BaseModelDetail model for a cell instance with all measurements.
Returns a foreign key for the parent specification rather than a nested object. Use
client.cell_spec.get(detail .specification_id)to fetch the full specification.- Parameters:
instance (CellInstance)
specification_id (str)
measurements (list[CellMeasurementDetail])
- instance: CellInstance#
- measurements: list[CellMeasurementDetail]#
- model_config = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.CyclerDetail(*, cycler, site_id, channels)[source]#
Bases:
BaseModelDetail model for a cycler with all its channels.
Returns a foreign key for the parent site rather than a nested object. Use
client.site.get(detail.site_id)to fetch the full site.- model_config = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.SiteDetail(*, site, cyclers)[source]#
Bases:
BaseModelDetail model for a site with all its cyclers.
Each cycler is expanded to a
CyclerDetail, so its channels are included too.- Parameters:
site (Site)
cyclers (list[CyclerDetail])
- cyclers: list[CyclerDetail]#
- model_config = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.ColumnSpec(*, name, unit='', source_column_index, **extra_data)[source]#
Bases:
BaseModelColumn descriptor for a material property dataset.
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.MaterialPropertyDataset(*, id, name, columns=[], data_version, nan_counts=None, created_at=None, source_pipeline_id=None, source_simple_pipeline_id=None, source_analysis_id=None, source_label=None, **extra_data)[source]#
Bases:
BaseModelMaterial property dataset record as returned by the API.
- Parameters:
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- columns: list[ColumnSpec]#
- class ionworks.models.AnalysisType(*values)[source]#
Bases:
StrEnumWell-known
analysis_typevalues.Members are plain strings (
StrEnum), so they can be passed directly wherever ananalysis_typestring is expected, e.g.client.analysis.create(..., analysis_type=AnalysisType.ECM_FROM_EIS).This set is advisory, not exhaustive: the API does not restrict
analysis_typeto these values — any non-empty string is accepted, so a new extractor can use a raw string without waiting for an SDK release.- ECM_FROM_EIS = 'ecm_from_eis'#
- LAM_LLI_FROM_RPT = 'lam_lli_from_rpt'#
- DCIR_FROM_HPPC = 'dcir_from_hppc'#
- ionworks.models.KNOWN_ANALYSIS_TYPES: list[str] = ['ecm_from_eis', 'lam_lli_from_rpt', 'dcir_from_hppc']#
The well-known analysis-type string values as a plain list, for iteration or display. Derived from
AnalysisType; prefer the enum for authoring.
- class ionworks.models.AnalysisColumnSpec(*, name, unit='', dtype=None, **extra_data)[source]#
Bases:
BaseModelColumn descriptor for an analysis parquet.
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.Analysis(*, id, measurement_id, project_id=None, name, analysis_type, columns=[], metadata={}, notes=None, source_pipeline_id=None, source_simple_pipeline_id=None, source_analysis_id=None, source_label=None, created_at=None, **extra_data)[source]#
Bases:
BaseModelAnalysis record as returned by the API.
An analysis holds features extracted from a single
cell_measurement(e.g. ECM parameters from EIS, LLI/LAM from RPT), stored as a parquet table plus loose metadata.- Parameters:
id (str)
measurement_id (str)
project_id (str | None)
name (str)
analysis_type (str)
columns (list[AnalysisColumnSpec])
metadata (dict)
notes (str | None)
source_pipeline_id (str | None)
source_simple_pipeline_id (str | None)
source_analysis_id (str | None)
source_label (str | None)
created_at (str | None)
extra_data (Any)
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- columns: list[AnalysisColumnSpec]#
- class ionworks.models.Material(*, id, name, manufacturer=None, product_id=None, **extra_data)[source]#
Bases:
BaseModelMaterial record as returned by the API.
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.Project(*, id, name, organization_id, **extra_data)[source]#
Bases:
BaseModelProject model - accepts any fields from the API.
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.SearchResult(*, id, entity_type, name, project_id=None, parent_id=None, **extra_data)[source]#
Bases:
BaseModelA single result from the global search endpoint.
Accepts any extra fields the API may add in future.
- Parameters:
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.SearchResponse(*, results, query, total, limit, offset, **extra_data)[source]#
Bases:
BaseModelPaginated response from the global search endpoint.
Iterates over
resultsso callers can treat it like a list ofSearchResult(for hit in response,response[0],len(response),if response:) while still reading the pagination metadata (total,limit,offset).Notes
Because
__iter__()yieldsSearchResultobjects (not Pydantic’s default(field_name, value)pairs),dict(response)does not work. Usemodel_dump()to get a plain dict of fields.- Parameters:
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- results: list[SearchResult]#
- class ionworks.models.Model(*, id, name, config=None, simulation_settings=None, **extra_data)[source]#
Bases:
BaseModelCustom model model - accepts any fields from the API.
- Parameters:
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.ParameterizedModel(*, id, name, simulation_settings=None, **extra_data)[source]#
Bases:
BaseModelParameterized model model - accepts any fields from the API.
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.RawData(*, id, project_id, name, filename, source=None, **extra_data)[source]#
Bases:
BaseModelA raw-data record.
Represents an original uploaded file stored as-is, scoped to an organization and project. The API defines the full schema; extra fields are accepted.
- Parameters:
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.Protocol(*, id, name, organization_id, project_id=None, description=None, protocol_config=None, parameters_schema=None, source_protocol=None, created_by_email=None, **extra_data)[source]#
Bases:
BaseModelA saved, project-scoped protocol.
Stored server-side as an
experiment_template: a named UCP protocol plus the schema of any parameters it leaves open. Simulations and planned measurements both reference a protocol by id rather than carrying the protocol text, so the same protocol runs identically everywhere.Heavy columns (
protocol_config,parameters_schema,source_protocol, …) are omitted from list responses unless requested viainclude; on a listed protocol they areNonerather than empty. Fetch the full record withget().- Parameters:
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- project_id: str | None#
Project that owns the protocol. Every protocol reachable through the API is project-scoped;
Noneonly appears on unmigrated legacy rows.
- protocol_config: dict[str, Any] | None#
The protocol itself, in UCP form.
Nonewhen not included in a list.
- class ionworks.models.ParsedProtocol(*, parsed_protocol_ucp, parsed_protocol_human='', raw_protocol='', cycler_type=None, required_drive_cycles=<factory>, available_drive_cycles=<factory>, required_subroutines=<factory>, available_subroutines=<factory>, error=None, **extra_data)[source]#
Bases:
BaseModelResult of parsing a vendor protocol file into UCP.
Returned by
parse_file(). A parsed protocol is not saved — passucptocreate()to store it.Drive cycles and subroutines referenced by the file may not be embedded in it. Those the parser recovered are listed in
available_drive_cycles/available_subroutines; those still needed are in therequired_lists and must be supplied before the protocol will simulate.- Parameters:
- model_config = {'extra': 'allow', 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.Study(*, id, name, **extra_data)[source]#
Bases:
BaseModelStudy model - accepts any fields from the API.
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.PlannedMeasurementStatus(*values)[source]#
Bases:
StrEnumLifecycle state of a planned measurement.
A measurement is first
requested, then a scheduler assigns it a channel and time window (scheduled). Once the real run starts it becomesin_progress, thencompleted; it may becancelledat any point before completion.- requested = 'requested'#
- scheduled = 'scheduled'#
- in_progress = 'in_progress'#
- completed = 'completed'#
- cancelled = 'cancelled'#
- class ionworks.models.PlannedMeasurement(*, id, name, project_id, status, protocol_id=None, cell_specification_id=None, cell_instance_id=None, channel_id=None, planned_start_time=None, planned_end_time=None, estimated_duration_seconds=None, requested_by_email=None, scheduled_by_email=None, **extra_data)[source]#
Bases:
BaseModelPlanned measurement model - accepts any fields from the API.
A planned measurement is a future, project-scoped test request. When
statusisscheduledit also reserveschannel_idover the[planned_start_time, planned_end_time)window; arequestedrow carries only anestimated_duration_secondsand no channel.- Parameters:
id (str)
name (str)
project_id (str)
status (PlannedMeasurementStatus)
protocol_id (str | None)
cell_specification_id (str | None)
cell_instance_id (str | None)
channel_id (str | None)
planned_start_time (datetime | None)
planned_end_time (datetime | None)
estimated_duration_seconds (int | None)
requested_by_email (str | None)
scheduled_by_email (str | None)
extra_data (Any)
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- status: PlannedMeasurementStatus#
- protocol_id: str | None#
Named protocol (experiment_template) the measurement will run. Required on create; resolve its display name via the linked protocol.
- cell_specification_id: str | None#
Cell specification the requester wants tested. Required on create.
- estimated_duration_seconds: int | None#
Expected run duration before scheduled times exist (requested rows).
- class ionworks.models.AutoScheduleAssignment(*, planned_measurement_id, planned_measurement_name, planned_measurement_updated_at, channel_id=None, channel_name=None, cycler_name=None, planned_start_time=None, planned_end_time=None, unscheduled_reason=None)[source]#
Bases:
BaseModelOne proposed planned-measurement reservation.
A proposal may include an unscheduled assignment when the project has no in-service channel able to take the test. Only assignments with
is_scheduledset should be passed toionworks.planned_measurement.PlannedMeasurementClient.apply_auto_schedule_proposal().- Parameters:
- planned_measurement_updated_at: datetime#
- cycler_name: str | None#
Owning cycler’s name. Channel names repeat across cyclers, so the pair identifies the hardware being reserved.
- model_config = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.AutoScheduleProposal(*, generated_at, assignments)[source]#
Bases:
BaseModelA transient earliest-gap proposal for selected requested tests.
- Parameters:
generated_at (datetime)
assignments (list[AutoScheduleAssignment])
- generated_at: datetime#
- assignments: list[AutoScheduleAssignment]#
- model_config = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.Optimization(*, id, name=None, job_id, project_id, **extra_data)[source]#
Bases:
BaseModelOptimization model - accepts any fields from the API.
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.SimulationUsage(*, usage=0, limit=None, **extra_data)[source]#
Bases:
BaseModelCurrent simulation usage and its configured limit, in hours.
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.ComputeUsage(*, usage=0, usage_by_type={}, limit=None, **extra_data)[source]#
Bases:
BaseModelCurrent compute usage and its configured limit, in hours.
usageis the total across all job types;usage_by_typebreaks it down by job type (informational — thelimitapplies to the total).- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks.models.OrganizationUsage(*, period_start, period_end, simulation=SimulationUsage(usage=0, limit=None), compute=ComputeUsage(usage=0, usage_by_type={}, limit=None), **extra_data)[source]#
Bases:
BaseModelAn organization’s usage and limits for the current billing period.
Returned by
usage(). Usage is aggregated across all members of the organization and resets on the first of each month. Simulation usage is a single figure; compute usage carries a per-job-type breakdown plus the total. All values are in hours. ANonelimit means that usage type is unconstrained.- Parameters:
period_start (datetime)
period_end (datetime)
simulation (SimulationUsage)
compute (ComputeUsage)
extra_data (Any)
- model_config = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- period_start: datetime#
Start of the current billing period (inclusive).
- period_end: datetime#
End of the current billing period (exclusive) — the next reset.
- simulation: SimulationUsage#
- compute: ComputeUsage#
- class ionworks.models.StepsAndCycles(*, steps, cycles)[source]#
Bases:
BaseModelSteps and cycle metrics for a measurement.
Returned by the
/steps_and_cyclesendpoint which fetches both in one call (cycles are derived from steps).- model_config = {'arbitrary_types_allowed': True}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- steps: DataFrame#
- cycles: DataFrame#