or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

area-detectors.mdcore-framework.mdepics-integration.mdflyers-continuous-scanning.mdindex.mdmotors-positioners.mdsimulation-testing.mdspecialized-devices.md

core-framework.mddocs/

0

# Core Framework

1

2

The foundational classes and interfaces that form the backbone of ophyd's device abstraction system. These components enable device composition, signal management, status tracking, and provide the base functionality that all other ophyd components build upon.

3

4

## Capabilities

5

6

### Device Class

7

8

The base class for all hardware devices in ophyd, providing a standardized interface for reading, configuring, and controlling hardware through a component-based architecture.

9

10

```python { .api }

11

class Device:

12

"""

13

Base class for all devices in ophyd.

14

15

Parameters:

16

- prefix (str): PV prefix for EPICS devices

17

- name (str): Device name for identification

18

- kind (Kind): Component kind classification

19

- read_attrs (list): Attributes to include in read()

20

- configuration_attrs (list): Attributes for configuration

21

- parent (Device): Parent device if nested

22

- child_name_separator (str): Separator for child component names (default: '_')

23

- connection_timeout (float): Timeout for signal connections

24

"""

25

def __init__(self, prefix='', *, name, kind=None, read_attrs=None, configuration_attrs=None, parent=None, child_name_separator='_', connection_timeout=None, **kwargs): ...

26

27

def read(self):

28

"""

29

Read current values from all readable components.

30

31

Returns:

32

dict: Mapping of component names to reading dictionaries

33

with 'value' and 'timestamp' keys

34

"""

35

36

def describe(self):

37

"""

38

Describe the data format for all readable components.

39

40

Returns:

41

dict: Mapping of component names to description dictionaries

42

with 'dtype', 'shape', and other metadata

43

"""

44

45

def configure(self, d):

46

"""

47

Configure device settings.

48

49

Parameters:

50

- d (dict): Configuration parameters mapping

51

52

Returns:

53

tuple: (old_config, new_config) dictionaries

54

"""

55

56

def read_configuration(self):

57

"""

58

Read current configuration values.

59

60

Returns:

61

dict: Current configuration state

62

"""

63

64

def describe_configuration(self):

65

"""

66

Describe configuration data format.

67

68

Returns:

69

dict: Configuration data descriptions

70

"""

71

72

def trigger(self):

73

"""

74

Trigger device acquisition or measurement.

75

76

Returns:

77

StatusBase: Status object tracking trigger completion

78

"""

79

80

def stage(self):

81

"""

82

Stage device for data acquisition (setup phase).

83

84

Returns:

85

list: List of staged components

86

"""

87

88

def unstage(self):

89

"""

90

Unstage device after data acquisition (cleanup phase).

91

92

Returns:

93

list: List of unstaged components

94

"""

95

96

def wait_for_connection(self, timeout=2.0):

97

"""

98

Wait for all device components to connect.

99

100

Parameters:

101

- timeout (float): Maximum wait time in seconds

102

"""

103

104

def connected(self):

105

"""

106

Check if device is fully connected.

107

108

Returns:

109

bool: True if all components are connected

110

"""

111

112

@property

113

def hints(self):

114

"""

115

Hints for plotting and analysis.

116

117

Returns:

118

dict: Plot hints with 'fields' key

119

"""

120

```

121

122

### Signal Classes

123

124

Fundamental classes for representing individual hardware channels and computed values, forming the building blocks of device components.

125

126

```python { .api }

127

class Signal:

128

"""

129

Base class for readable and writable values.

130

131

Parameters:

132

- name (str): Signal name for identification

133

- value: Initial value (default: 0.0)

134

- dtype: Data type specification

135

- shape: Data shape specification

136

- timestamp (float): Initial timestamp

137

- parent (Device): Parent device

138

- labels (list): Additional signal labels

139

- kind (Kind): Signal classification (default: Kind.hinted)

140

- tolerance (float): Absolute tolerance for set operations

141

- rtolerance (float): Relative tolerance for set operations

142

- metadata (dict): Additional metadata

143

- cl: Control layer

144

- attr_name (str): Parent Device attribute name

145

"""

146

def __init__(self, *, name, value=0.0, dtype=None, shape=None, timestamp=None, parent=None, labels=None, kind=Kind.hinted, tolerance=None, rtolerance=None, metadata=None, cl=None, attr_name="", **kwargs): ...

147

148

def get(self, **kwargs):

149

"""

150

Get current signal value.

151

152

Returns:

153

Current value of the signal

154

"""

155

156

def put(self, value, **kwargs):

157

"""

158

Put value to signal (synchronous).

159

160

Parameters:

161

- value: Value to write

162

"""

163

164

def set(self, value, **kwargs):

165

"""

166

Set signal to value (asynchronous).

167

168

Parameters:

169

- value: Target value

170

171

Returns:

172

StatusBase: Status object tracking set completion

173

"""

174

175

def read(self):

176

"""

177

Read signal value and timestamp.

178

179

Returns:

180

dict: Reading dictionary with 'value' and 'timestamp'

181

"""

182

183

def describe(self):

184

"""

185

Describe signal data format.

186

187

Returns:

188

dict: Description with 'dtype', 'shape', 'source', etc.

189

"""

190

191

def subscribe(self, callback, event_type=None, run=True):

192

"""

193

Subscribe to signal changes.

194

195

Parameters:

196

- callback (callable): Function to call on changes

197

- event_type (str): Type of event to monitor

198

- run (bool): Whether to run callback immediately

199

200

Returns:

201

int: Subscription ID for unsubscribing

202

"""

203

204

def clear_sub(self, cb, event_type=None):

205

"""

206

Clear subscription.

207

208

Parameters:

209

- cb: Subscription ID or callback function

210

- event_type (str): Event type to clear

211

"""

212

213

class SignalRO(Signal):

214

"""

215

Read-only signal that cannot be written to.

216

"""

217

def __init__(self, *, name, value=0, **kwargs): ...

218

219

class DerivedSignal(Signal):

220

"""

221

Signal derived from other signals through a function.

222

223

Parameters:

224

- derived_from (dict): Mapping of signals to derive from

225

- derived_func (callable): Function to compute derived value

226

"""

227

def __init__(self, *, derived_from, derived_func=None, **kwargs): ...

228

```

229

230

### Component System

231

232

The component system enables composition of devices from reusable, declarative building blocks.

233

234

```python { .api }

235

class Component:

236

"""

237

Device component descriptor for building composite devices.

238

239

Parameters:

240

- cls: Component class to instantiate

241

- suffix (str): PV suffix to append to device prefix

242

- lazy (bool): Whether to delay instantiation

243

- trigger_value: Value to set during trigger()

244

- add_prefix (tuple): Additional prefix components

245

- doc (str): Documentation string

246

- kind (Kind): Component classification

247

"""

248

def __init__(self, cls, suffix='', *, lazy=False, trigger_value=None, add_prefix=None, doc=None, kind='normal', **kwargs): ...

249

250

class FormattedComponent(Component):

251

"""

252

Component with string formatting support for dynamic PV names.

253

254

Parameters:

255

- cls: Component class

256

- suffix (str): PV suffix with format strings

257

- **kwargs: Format arguments and component parameters

258

"""

259

def __init__(self, cls, suffix, **kwargs): ...

260

261

class DynamicDeviceComponent(Component):

262

"""

263

Component that creates devices dynamically based on available PVs.

264

"""

265

def __init__(self, defn, **kwargs): ...

266

267

# Component utility functions

268

def kind_context(kind):

269

"""

270

Context manager for setting default component kind.

271

272

Parameters:

273

- kind (Kind): Default kind for components created in context

274

"""

275

276

ALL_COMPONENTS = object() # Sentinel for selecting all components

277

```

278

279

### Status Management

280

281

Status objects track the progress and completion of asynchronous operations.

282

283

```python { .api }

284

class StatusBase:

285

"""

286

Base class for tracking operation status.

287

288

Parameters:

289

- timeout (float): Maximum time to wait for completion (None = wait forever)

290

- settle_time (float): Time to wait after completion before callbacks (default: 0)

291

- done (deprecated): Initial completion state

292

- success (deprecated): Initial success state

293

"""

294

def __init__(self, *, timeout=None, settle_time=0, done=None, success=None): ...

295

296

@property

297

def done(self):

298

"""

299

Whether operation is complete.

300

301

Returns:

302

bool: True if operation finished (success or failure)

303

"""

304

305

@property

306

def success(self):

307

"""

308

Whether operation completed successfully.

309

310

Returns:

311

bool: True if completed without errors

312

"""

313

314

def wait(self, timeout=None):

315

"""

316

Wait for operation completion.

317

318

Parameters:

319

- timeout (float): Maximum wait time

320

321

Raises:

322

StatusTimeoutError: If timeout is exceeded

323

"""

324

325

def add_callback(self, callback):

326

"""

327

Add callback for status completion.

328

329

Parameters:

330

- callback (callable): Function to call when complete

331

"""

332

333

class Status(StatusBase):

334

"""

335

Basic status implementation with manual completion control.

336

"""

337

def __init__(self, obj=None, **kwargs): ...

338

339

def set_finished(self):

340

"""Mark status as successfully completed."""

341

342

def set_exception(self, exc):

343

"""Mark status as failed with exception."""

344

345

class DeviceStatus(StatusBase):

346

"""

347

Status for device operations, can combine multiple sub-statuses.

348

"""

349

def __init__(self, device, **kwargs): ...

350

351

def add_status(self, status):

352

"""Add sub-status to track."""

353

354

class MoveStatus(StatusBase):

355

"""

356

Status specifically for positioner movements.

357

"""

358

def __init__(self, positioner, target, **kwargs): ...

359

360

def wait(status, timeout=None, poll_period=0.05):

361

"""

362

Wait for one or more status objects to complete.

363

364

Parameters:

365

- status (StatusBase or list): Status object(s) to wait for

366

- timeout (float): Maximum total wait time

367

- poll_period (float): Polling interval

368

369

Raises:

370

StatusTimeoutError: If any status times out

371

WaitTimeoutError: If overall timeout is exceeded

372

"""

373

```

374

375

### Object Registry and Utilities

376

377

Utilities for managing ophyd objects and their relationships.

378

379

```python { .api }

380

class OphydObject:

381

"""

382

Base class for all ophyd objects providing common functionality.

383

384

Parameters:

385

- name (str): Object name

386

- parent (OphydObject): Parent object

387

"""

388

def __init__(self, *, name=None, parent=None, **kwargs): ...

389

390

@property

391

def name(self):

392

"""Full dotted name including parent hierarchy."""

393

394

@property

395

def dotted_name(self):

396

"""Dotted name for hierarchical identification."""

397

398

def destroy(self):

399

"""Clean up object resources."""

400

401

# Registry functions

402

def register_instances_keyed_on_name(cls, registry=None):

403

"""

404

Register class instances in a dictionary keyed by name.

405

406

Parameters:

407

- cls: Class to register instances for

408

- registry (dict): Dictionary to store instances

409

"""

410

411

def register_instances_in_weakset(cls, registry=None):

412

"""

413

Register class instances in a weak set.

414

415

Parameters:

416

- cls: Class to register instances for

417

- registry (WeakSet): Set to store instances

418

"""

419

420

def select_version(obj, version):

421

"""

422

Select specific version of an object.

423

424

Parameters:

425

- obj: Object with version support

426

- version: Version identifier

427

"""

428

```

429

430

### Utility Functions

431

432

Helper functions for namespace management, string processing, and instance handling.

433

434

```python { .api }

435

class OrderedDefaultDict(OrderedDict):

436

"""

437

Combination of defaultdict and OrderedDict.

438

439

Provides ordered dictionary functionality with automatic

440

default value creation for missing keys.

441

442

Parameters:

443

- default_factory (callable): Factory function for default values

444

"""

445

def __init__(self, default_factory=None, *a, **kw): ...

446

def __missing__(self, key): ...

447

def copy(self): ...

448

449

def instances_from_namespace(classes, *, ns=None):

450

"""

451

Get instances of specified classes from user namespace.

452

453

Searches the IPython user namespace (or provided namespace)

454

for instances of the specified class types.

455

456

Parameters:

457

- classes: Type or sequence of types to match with isinstance()

458

- ns (dict): Namespace to search (defaults to IPython user_ns)

459

460

Returns:

461

list: Instances matching the specified classes

462

"""

463

464

def ducks_from_namespace(attrs, *, ns=None):

465

"""

466

Get instances with specified attributes (duck typing).

467

468

Finds objects that have all specified attributes, implementing

469

"duck typing" - if it looks like a duck and quacks like a duck...

470

471

Parameters:

472

- attrs: Attribute name(s) to check for

473

- ns (dict): Namespace to search (defaults to IPython user_ns)

474

475

Returns:

476

list: Objects that have all specified attributes

477

"""

478

479

def underscores_to_camel_case(underscores):

480

"""

481

Convert underscore-separated strings to camelCase.

482

483

Parameters:

484

- underscores (str): String with underscores (e.g., "abc_def_ghi")

485

486

Returns:

487

str: CamelCase version (e.g., "abcDefGhi")

488

"""

489

490

def getattrs(obj, gen):

491

"""

492

Get multiple attributes from an object as generator.

493

494

Parameters:

495

- obj: Object to get attributes from

496

- gen: Iterable of attribute names

497

498

Yields:

499

tuple: (attribute_name, attribute_value) pairs

500

"""

501

502

def doc_annotation_forwarder(base_klass):

503

"""

504

Decorator that forwards documentation and annotations from base class.

505

506

Copies __doc__ and __annotations__ from base class method to wrapper.

507

Useful for maintaining documentation in method override patterns.

508

509

Parameters:

510

- base_klass: Base class to forward documentation from

511

512

Returns:

513

callable: Decorator function

514

"""

515

516

def adapt_old_callback_signature(callback):

517

"""

518

Adapt old callback signatures for backward compatibility.

519

520

Wraps callbacks with signature callback() to match expected

521

callback(status) signature for status objects.

522

523

Parameters:

524

- callback: Callable with signature callback() or callback(status)

525

526

Returns:

527

callable: Callback with signature callback(status)

528

"""

529

```

530

531

## Usage Examples

532

533

### Creating a Custom Device

534

535

```python

536

from ophyd import Device, Component, EpicsSignal

537

538

class MyTemperatureController(Device):

539

"""Temperature controller with setpoint and readback."""

540

setpoint = Component(EpicsSignal, 'SP', kind='config')

541

temperature = Component(EpicsSignal, 'RBV', kind='hinted')

542

status = Component(EpicsSignal, 'STAT', kind='omitted')

543

544

def heat_to(self, temperature):

545

"""Heat to target temperature."""

546

return self.setpoint.set(temperature)

547

548

# Create and use device

549

temp_controller = MyTemperatureController('TEMP:CTRL:', name='temp_ctrl')

550

temp_controller.wait_for_connection()

551

552

# Read all values

553

reading = temp_controller.read()

554

print(f"Current temperature: {reading['temp_ctrl_temperature']['value']}")

555

556

# Set temperature and wait

557

status = temp_controller.heat_to(25.0)

558

wait(status)

559

```

560

561

### Working with Signals

562

563

```python

564

from ophyd import Signal, DerivedSignal

565

566

# Create base signals

567

voltage = Signal(name='voltage', value=5.0)

568

current = Signal(name='current', value=2.0)

569

570

# Create derived signal for power

571

def calculate_power(voltage=None, current=None, **kwargs):

572

return voltage * current

573

574

power = DerivedSignal(

575

derived_from={'voltage': voltage, 'current': current},

576

derived_func=calculate_power,

577

name='power'

578

)

579

580

# Subscribe to changes

581

def power_changed(value=None, **kwargs):

582

print(f"Power changed to: {value} W")

583

584

power.subscribe(power_changed)

585

586

# Update base signals

587

voltage.put(6.0) # Triggers power calculation and callback

588

```