SCIENTIFIC INSTRUMENT
CONTROL WITH F#
Anton Tcholakov, Colin Stephen, Gavin Morley
Department of Physics, University of Warwick
@ant_pt
CUSTOM SPECTROMETER
CUSTOM SPECTROMETER
• Apply microwaves to a
sample in a magnetic field
• Measure the reflected
power
• Vary the magnetic field
• Changes in the signal help
to characterise the sample
REQUIREMENTS
REQUIREMENTS
• Concurrent control of multiple
instruments
• Real-time chart plotting
• Ability to save data and
experimental parameters
• Modularity
• Robust error handling
14.125 14.130 14.135 14.140
-6000
-4000
-2000
0
2000
4000
6000
8000
10000
EPRsignal(arb.units)
Magnetic field (T)
DOMAIN MODELLING
• Records, unions and units of measure let us model hardware
capabilities and experiment parameters clearly and concisely
• We get structural equality and serialisation for free
type Frequency = FrequencyInHz of float<Hz>
type Amplitude = PowerInDbm of float<dBm>
type StepSpacing = LinearSpacing | LogarithmicSpacing
type Range<'T> = { Start : ’T ; Stop : 'T }
type FrequencySweep =
| FrequencySweep of range : Range<Frequency>
| FixedFrequency of frequency : Frequency
type AmplitudeSweep =
| AmplitudeSweep of range : Range<Amplitude>
| FixedAmplitude of amplitude : Amplitude
type StepSweep =
{ Frequency : FrequencySweep
Amplitude : AmplitudeSweep
NumberOfPoints : int
Spacing : StepSpacing }
INSTRUMENT CONTROL
• Communication to hardware is inherently async
• async workflows are great metaphor for
experiments
• Use asyncChoice (available in ExtCore) and
railway-oriented programming to handle errors
DATA ACQUISITION
type StreamingAcquisition =
{ Parameters : StreamingParameters
Buffers : AcquisitionBuffers
StopCapability : CancellationCapability<StreamStopOptions>
StatusChanged : Event<StreamStatus>
SampleBlockObserved : Event<SampleBlock> }
let run scope acquisition = asyncChoice {
use acquisitionHandle =
PicoScope.Acquisition.allocateHandle digitiser acquisition.Buffers
do! prepare scope acquisition
do! startStreaming scope acquisition
do! pollUntilStopped scope acquisition }
• Acquisition emits samples via Event<‘T>, so we can feed this straight
into FSharp.Charting
• Use Rx transformations to implement signal processing
WHAT DO OTHERS USE?
C / C++
• Low level, manual memory and thread management
Python
• Global Interpreter Lock can cause problems
• Pay the price for dynamic typing in large projects
C# (… in industry?)
LabVIEW
• Looks and feels like it belongs in the 90s
• … but has a vast library of instrument drivers
SUMMARY
• F#’s type system allows us to model our problem
domain clearly and concisely
• Many of the tools we need are already available
(async, Rx, FSharp.Charting)
• F# is very well suited to the task but lacks
instrument libraries and user base

Scientific instrument control with F#

  • 1.
    SCIENTIFIC INSTRUMENT CONTROL WITHF# Anton Tcholakov, Colin Stephen, Gavin Morley Department of Physics, University of Warwick @ant_pt
  • 2.
  • 3.
    CUSTOM SPECTROMETER • Applymicrowaves to a sample in a magnetic field • Measure the reflected power • Vary the magnetic field • Changes in the signal help to characterise the sample
  • 4.
  • 5.
    REQUIREMENTS • Concurrent controlof multiple instruments • Real-time chart plotting • Ability to save data and experimental parameters • Modularity • Robust error handling 14.125 14.130 14.135 14.140 -6000 -4000 -2000 0 2000 4000 6000 8000 10000 EPRsignal(arb.units) Magnetic field (T)
  • 6.
    DOMAIN MODELLING • Records,unions and units of measure let us model hardware capabilities and experiment parameters clearly and concisely • We get structural equality and serialisation for free type Frequency = FrequencyInHz of float<Hz> type Amplitude = PowerInDbm of float<dBm> type StepSpacing = LinearSpacing | LogarithmicSpacing type Range<'T> = { Start : ’T ; Stop : 'T } type FrequencySweep = | FrequencySweep of range : Range<Frequency> | FixedFrequency of frequency : Frequency type AmplitudeSweep = | AmplitudeSweep of range : Range<Amplitude> | FixedAmplitude of amplitude : Amplitude type StepSweep = { Frequency : FrequencySweep Amplitude : AmplitudeSweep NumberOfPoints : int Spacing : StepSpacing }
  • 7.
    INSTRUMENT CONTROL • Communicationto hardware is inherently async • async workflows are great metaphor for experiments • Use asyncChoice (available in ExtCore) and railway-oriented programming to handle errors
  • 8.
    DATA ACQUISITION type StreamingAcquisition= { Parameters : StreamingParameters Buffers : AcquisitionBuffers StopCapability : CancellationCapability<StreamStopOptions> StatusChanged : Event<StreamStatus> SampleBlockObserved : Event<SampleBlock> } let run scope acquisition = asyncChoice { use acquisitionHandle = PicoScope.Acquisition.allocateHandle digitiser acquisition.Buffers do! prepare scope acquisition do! startStreaming scope acquisition do! pollUntilStopped scope acquisition } • Acquisition emits samples via Event<‘T>, so we can feed this straight into FSharp.Charting • Use Rx transformations to implement signal processing
  • 9.
    WHAT DO OTHERSUSE? C / C++ • Low level, manual memory and thread management Python • Global Interpreter Lock can cause problems • Pay the price for dynamic typing in large projects C# (… in industry?)
  • 10.
    LabVIEW • Looks andfeels like it belongs in the 90s • … but has a vast library of instrument drivers
  • 11.
    SUMMARY • F#’s typesystem allows us to model our problem domain clearly and concisely • Many of the tools we need are already available (async, Rx, FSharp.Charting) • F# is very well suited to the task but lacks instrument libraries and user base