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

area-detectors.mddocs/

0

# Area Detectors

1

2

Comprehensive support for 2D area detectors including cameras, plugins for data processing, file I/O, and triggering strategies for coordinated data acquisition. Area detectors form a modular system where cameras capture images and plugins process, display, and save data.

3

4

## Capabilities

5

6

### Base Area Detector Classes

7

8

Foundation classes that provide the core area detector functionality.

9

10

```python { .api }

11

class DetectorBase(Device):

12

"""

13

Base class for all area detectors.

14

15

Parameters:

16

- prefix (str): EPICS PV prefix for detector

17

- name (str): Detector name

18

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

19

- configuration_attrs (list): Configuration attributes

20

"""

21

def __init__(self, prefix, *, read_attrs=None, configuration_attrs=None, **kwargs): ...

22

23

def stage(self):

24

"""

25

Stage detector for data acquisition.

26

27

Returns:

28

list: Staged components

29

"""

30

31

def unstage(self):

32

"""

33

Unstage detector after acquisition.

34

35

Returns:

36

list: Unstaged components

37

"""

38

39

def trigger(self):

40

"""

41

Trigger detector acquisition.

42

43

Returns:

44

StatusBase: Trigger completion status

45

"""

46

47

class AreaDetector(DetectorBase):

48

"""

49

Generic area detector with camera and plugin support.

50

51

Provides a complete area detector system with camera control

52

and plugin chain for data processing and file writing.

53

"""

54

def __init__(self, prefix, *, name, **kwargs): ...

55

56

# Core components (automatically created)

57

cam = Component(AreaDetectorCam, 'cam1:')

58

image = Component(ImagePlugin, 'image1:')

59

60

def stage(self):

61

"""Stage detector and plugins for acquisition."""

62

63

def unstage(self):

64

"""Unstage detector and clean up."""

65

66

class SimDetector(DetectorBase):

67

"""

68

Simulated area detector for testing and development.

69

70

Provides all the functionality of a real detector but generates

71

synthetic data instead of requiring hardware.

72

"""

73

def __init__(self, prefix, *, name, **kwargs): ...

74

75

class ADBase(Device):

76

"""

77

Base class providing core area detector functionality.

78

79

Contains common PVs and methods used by all area detector components.

80

"""

81

def __init__(self, prefix='', **kwargs): ...

82

```

83

84

### Camera Classes

85

86

Camera interfaces for different detector hardware types.

87

88

```python { .api }

89

class CamBase(ADBase):

90

"""

91

Base camera class with common camera functionality.

92

93

Provides standard camera controls like acquire, trigger mode,

94

image size, and exposure time.

95

"""

96

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

97

98

# Standard camera controls

99

acquire = Component(EpicsSignal, 'Acquire', trigger_value=1)

100

acquire_time = Component(EpicsSignal, 'AcquireTime')

101

acquire_period = Component(EpicsSignal, 'AcquirePeriod')

102

103

# Image size and binning

104

size_x = Component(EpicsSignal, 'SizeX')

105

size_y = Component(EpicsSignal, 'SizeY')

106

bin_x = Component(EpicsSignal, 'BinX')

107

bin_y = Component(EpicsSignal, 'BinY')

108

109

# Trigger controls

110

trigger_mode = Component(EpicsSignal, 'TriggerMode')

111

image_mode = Component(EpicsSignal, 'ImageMode')

112

num_images = Component(EpicsSignal, 'NumImages')

113

114

class AreaDetectorCam(CamBase):

115

"""Generic area detector camera."""

116

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

117

118

class SimDetectorCam(CamBase):

119

"""Simulated detector camera with synthetic image generation."""

120

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

121

122

# Simulation-specific controls

123

sim_mode = Component(EpicsSignal, 'SimMode')

124

gain_x = Component(EpicsSignal, 'GainX')

125

gain_y = Component(EpicsSignal, 'GainY')

126

127

# Specific detector camera classes (30+ types available)

128

class AndorCam(CamBase):

129

"""Andor camera interface."""

130

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

131

132

class PerkinElmerCam(CamBase):

133

"""PerkinElmer detector camera."""

134

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

135

136

class PointGreyCam(CamBase):

137

"""Point Grey camera interface."""

138

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

139

140

class AdscCam(CamBase):

141

"""ADSC detector camera."""

142

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

143

144

class PilatusDetectorCam(CamBase):

145

"""Pilatus detector camera."""

146

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

147

```

148

149

### Plugin System

150

151

Plugins provide data processing, visualization, and file I/O capabilities.

152

153

```python { .api }

154

class PluginBase(ADBase):

155

"""

156

Base class for all area detector plugins.

157

158

Plugins process data from cameras or other plugins in a pipeline.

159

160

Parameters:

161

- suffix (str): Plugin PV suffix (e.g., 'image1:', 'HDF1:')

162

"""

163

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

164

165

# Plugin control

166

enable = Component(EpicsSignal, 'EnableCallbacks')

167

nd_array_port = Component(EpicsSignal, 'NDArrayPort', string=True)

168

169

def enable_on_stage(self):

170

"""Enable plugin when parent detector is staged."""

171

172

def disable_on_unstage(self):

173

"""Disable plugin when parent detector is unstaged."""

174

175

class ImagePlugin(PluginBase):

176

"""

177

Image display plugin for live viewing.

178

179

Provides image data for display systems and live feedback.

180

"""

181

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

182

183

class StatsPlugin(PluginBase):

184

"""

185

Statistics plugin for image analysis.

186

187

Calculates min, max, mean, sigma, and other statistics

188

on image data in real-time.

189

"""

190

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

191

192

# Statistics outputs

193

min_value = Component(EpicsSignalRO, 'MinValue_RBV')

194

max_value = Component(EpicsSignalRO, 'MaxValue_RBV')

195

mean_value = Component(EpicsSignalRO, 'MeanValue_RBV')

196

sigma_value = Component(EpicsSignalRO, 'SigmaValue_RBV')

197

total = Component(EpicsSignalRO, 'Total_RBV')

198

199

class ROIPlugin(PluginBase):

200

"""

201

Region of Interest plugin for extracting image sub-regions.

202

203

Defines rectangular regions for analysis and processing.

204

"""

205

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

206

207

# ROI definition

208

min_x = Component(EpicsSignal, 'MinX')

209

min_y = Component(EpicsSignal, 'MinY')

210

size_x = Component(EpicsSignal, 'SizeX')

211

size_y = Component(EpicsSignal, 'SizeY')

212

213

class TransformPlugin(PluginBase):

214

"""

215

Transform plugin for image rotation, mirroring, and scaling.

216

"""

217

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

218

219

# Transform controls

220

transform_type = Component(EpicsSignal, 'Type')

221

origin_location = Component(EpicsSignal, 'Origin')

222

```

223

224

### File Plugins

225

226

Plugins for saving detector data to various file formats.

227

228

```python { .api }

229

class FilePlugin(PluginBase):

230

"""

231

Base class for file writing plugins.

232

233

Provides common file writing functionality including

234

path management, file naming, and write control.

235

"""

236

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

237

238

# File path and naming

239

file_path = Component(EpicsSignal, 'FilePath', string=True)

240

file_name = Component(EpicsSignal, 'FileName', string=True)

241

file_template = Component(EpicsSignal, 'FileTemplate', string=True)

242

file_number = Component(EpicsSignal, 'FileNumber')

243

244

# File writing control

245

capture = Component(EpicsSignal, 'Capture')

246

num_capture = Component(EpicsSignal, 'NumCapture')

247

248

def stage(self):

249

"""Configure file plugin for acquisition."""

250

251

def unstage(self):

252

"""Clean up after acquisition."""

253

254

class HDF5Plugin(FilePlugin):

255

"""

256

HDF5 file writing plugin.

257

258

Saves detector data in HDF5 format with comprehensive metadata

259

and support for compression and chunking.

260

"""

261

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

262

263

# HDF5-specific controls

264

compression = Component(EpicsSignal, 'Compression')

265

store_attr = Component(EpicsSignal, 'StoreAttr')

266

store_perform = Component(EpicsSignal, 'StorePerform')

267

268

class TIFFPlugin(FilePlugin):

269

"""

270

TIFF file writing plugin.

271

272

Saves individual images as TIFF files with standard formatting.

273

"""

274

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

275

276

class NetCDFPlugin(FilePlugin):

277

"""

278

NetCDF file writing plugin for scientific data formats.

279

"""

280

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

281

282

class JPEGPlugin(FilePlugin):

283

"""

284

JPEG file writing plugin for compressed images.

285

"""

286

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

287

288

# JPEG-specific controls

289

quality = Component(EpicsSignal, 'Quality')

290

```

291

292

### Trigger Mixins

293

294

Classes that define different triggering strategies for coordinated data acquisition.

295

296

```python { .api }

297

class TriggerBase:

298

"""

299

Base trigger interface for area detectors.

300

301

Defines the trigger protocol that detectors must implement

302

for integration with data acquisition systems.

303

"""

304

def trigger(self):

305

"""

306

Trigger detector acquisition.

307

308

Returns:

309

StatusBase: Status tracking trigger completion

310

"""

311

raise NotImplementedError()

312

313

class SingleTrigger(TriggerBase):

314

"""

315

Single frame trigger strategy.

316

317

Configures detector for single image acquisition per trigger.

318

"""

319

def trigger(self):

320

"""Trigger single frame acquisition."""

321

# Set single image mode

322

# Start acquisition

323

# Return status

324

325

def stage(self):

326

"""Configure for single trigger mode."""

327

328

class MultiTrigger(TriggerBase):

329

"""

330

Multiple frame trigger strategy.

331

332

Configures detector for multiple image acquisition per trigger.

333

"""

334

def __init__(self, num_images=1, **kwargs):

335

self.num_images = num_images

336

super().__init__(**kwargs)

337

338

def trigger(self):

339

"""Trigger multi-frame acquisition."""

340

341

def stage(self):

342

"""Configure for multi-trigger mode."""

343

344

class ContinuousAcquisitionTrigger(TriggerBase):

345

"""

346

Continuous acquisition trigger for streaming data.

347

348

Starts continuous acquisition and manages data collection

349

over specified time periods.

350

"""

351

def trigger(self):

352

"""Start continuous acquisition."""

353

354

def stage(self):

355

"""Configure for continuous mode."""

356

```

357

358

### FileStore Integration

359

360

Mixins for integrating with data management systems and event-based data access.

361

362

```python { .api }

363

class FileStoreBase:

364

"""

365

Base class for FileStore integration.

366

367

Provides integration with document-based data systems

368

for tracking detector data files and metadata.

369

"""

370

def generate_datum(self, key, timestamp, uid):

371

"""

372

Generate datum document for data file.

373

374

Parameters:

375

- key (str): Data key identifier

376

- timestamp (float): Data timestamp

377

- uid (str): Unique identifier

378

379

Returns:

380

str: Datum ID for referencing data

381

"""

382

383

class FileStoreHDF5(FileStoreBase):

384

"""

385

FileStore integration for HDF5 files.

386

387

Manages HDF5 file metadata and provides data access

388

through the document model.

389

"""

390

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

391

392

class FileStoreTIFF(FileStoreBase):

393

"""

394

FileStore integration for TIFF files.

395

"""

396

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

397

```

398

399

## Usage Examples

400

401

### Basic Area Detector Usage

402

403

```python

404

from ophyd.areadetector import AreaDetector, SingleTrigger

405

406

# Create detector with single trigger capability

407

class MyDetector(SingleTrigger, AreaDetector):

408

pass

409

410

detector = MyDetector('XF:28IDC:DET:', name='detector')

411

detector.wait_for_connection()

412

413

# Configure camera

414

detector.cam.acquire_time.put(0.1) # 100ms exposure

415

detector.cam.image_mode.put('Single')

416

417

# Stage detector for acquisition

418

detector.stage()

419

420

# Trigger acquisition

421

status = detector.trigger()

422

wait(status)

423

424

# Read image data

425

reading = detector.read()

426

427

# Unstage when done

428

detector.unstage()

429

```

430

431

### Setting Up File Saving

432

433

```python

434

from ophyd.areadetector import AreaDetector, HDF5Plugin, TIFFPlugin

435

436

detector = AreaDetector('XF:28IDC:DET:', name='detector')

437

detector.wait_for_connection()

438

439

# Configure HDF5 plugin

440

hdf5 = detector.hdf5

441

hdf5.file_path.put('/data/detector/')

442

hdf5.file_name.put('scan')

443

hdf5.file_template.put('%s%s_%04d.h5')

444

hdf5.enable.put(1)

445

446

# Configure for 10 images

447

hdf5.num_capture.put(10)

448

detector.cam.num_images.put(10)

449

detector.cam.image_mode.put('Multiple')

450

451

# Start acquisition

452

detector.stage()

453

hdf5.capture.put(1) # Start file writing

454

455

status = detector.trigger()

456

wait(status) # Wait for all 10 images

457

458

detector.unstage()

459

print(f"Data saved to: {hdf5.full_file_name.get()}")

460

```

461

462

### Using Statistics Plugin

463

464

```python

465

detector = AreaDetector('XF:28IDC:DET:', name='detector')

466

detector.wait_for_connection()

467

468

# Enable statistics plugin

469

stats = detector.stats1

470

stats.enable.put(1)

471

472

# Configure region of interest for stats

473

stats.min_x.put(100)

474

stats.min_y.put(100)

475

stats.size_x.put(200)

476

stats.size_y.put(200)

477

478

# Take image and get statistics

479

detector.stage()

480

status = detector.trigger()

481

wait(status)

482

483

# Read statistics

484

print(f"Mean intensity: {stats.mean_value.get()}")

485

print(f"Max intensity: {stats.max_value.get()}")

486

print(f"Total counts: {stats.total.get()}")

487

488

detector.unstage()

489

```

490

491

### Multi-Trigger Acquisition

492

493

```python

494

from ophyd.areadetector import AreaDetector, MultiTrigger

495

496

class MultiImageDetector(MultiTrigger, AreaDetector):

497

def __init__(self, *args, num_images=5, **kwargs):

498

super().__init__(*args, num_images=num_images, **kwargs)

499

500

detector = MultiImageDetector('XF:28IDC:DET:', name='detector', num_images=10)

501

detector.wait_for_connection()

502

503

# Configure exposure

504

detector.cam.acquire_time.put(0.05) # 50ms per image

505

506

# Stage for multi-image acquisition

507

detector.stage()

508

509

# Trigger acquisition of 10 images

510

status = detector.trigger()

511

wait(status) # Wait for all 10 images

512

513

detector.unstage()

514

```

515

516

### Custom Detector with Plugins

517

518

```python

519

from ophyd import Component

520

from ophyd.areadetector import (AreaDetector, HDF5Plugin, TIFFPlugin,

521

StatsPlugin, ROIPlugin, ImagePlugin)

522

523

class MyAdvancedDetector(AreaDetector):

524

"""Custom detector with specific plugin configuration."""

525

526

# File plugins

527

hdf5 = Component(HDF5Plugin, 'HDF1:')

528

tiff = Component(TIFFPlugin, 'TIFF1:')

529

530

# Analysis plugins

531

stats1 = Component(StatsPlugin, 'Stats1:')

532

stats2 = Component(StatsPlugin, 'Stats2:')

533

roi1 = Component(ROIPlugin, 'ROI1:')

534

roi2 = Component(ROIPlugin, 'ROI2:')

535

536

# Display

537

image1 = Component(ImagePlugin, 'image1:')

538

539

detector = MyAdvancedDetector('XF:28IDC:DET:', name='detector')

540

detector.wait_for_connection()

541

542

# Configure multiple ROIs

543

detector.roi1.min_x.put(0)

544

detector.roi1.min_y.put(0)

545

detector.roi1.size_x.put(512)

546

detector.roi1.size_y.put(512)

547

548

detector.roi2.min_x.put(200)

549

detector.roi2.min_y.put(200)

550

detector.roi2.size_x.put(100)

551

detector.roi2.size_y.put(100)

552

553

# Connect stats plugins to ROIs

554

detector.stats1.nd_array_port.put('ROI1')

555

detector.stats2.nd_array_port.put('ROI2')

556

557

# Enable all plugins

558

for plugin in [detector.roi1, detector.roi2, detector.stats1, detector.stats2]:

559

plugin.enable.put(1)

560

```

561

562

### Simulation Detector

563

564

```python

565

from ophyd.areadetector import SimDetector, SingleTrigger

566

567

class MySimDetector(SingleTrigger, SimDetector):

568

pass

569

570

sim_detector = MySimDetector('XF:28IDC:SIM:', name='sim_detector')

571

sim_detector.wait_for_connection()

572

573

# Configure simulation parameters

574

sim_detector.cam.sim_mode.put(1) # Linear ramp

575

sim_detector.cam.acquire_time.put(0.1)

576

577

# Take simulated image

578

sim_detector.stage()

579

status = sim_detector.trigger()

580

wait(status)

581

582

# The detector generates synthetic data

583

reading = sim_detector.read()

584

sim_detector.unstage()

585

```