SlideShare a Scribd company logo
1 of 66
Download to read offline
The world leader in serving scienceLua Workshop 2016, San Francisco, CA
Mass spectrometry assay optimization using
functional programming patterns in Lua
Bennett Kalafut
2
Outline
1. Mass Spectrometry and Lua
a) Mass spectrometry basics (what, why, and how?)
b) Lua as a control language
2. Iterator pipelines and higher-order table functions
a) Core functionals: Map, filter, and reduce
b) Lua-specific patterns
c) Warm-up 1: Tuning up an ion source
d) Warm-up 2: Check some electronics
3. Automated assay optimization
a) Why per-assay optimization?
b) Optimizations as composable functions
c) How to hide/handle state
d) Putting it all together
3
Separation and quantification of ions in a mixture, by mass.
• An electrical or electromagnetic technique. Separation by m/z, not m.
What is mass spectrometry?
4
Separation and quantification of ions in a mixture, by mass.
• An electrical or electromagnetic technique. Separation by m/z, not m.
• Applications: Chemical/pharmaceutical manufacture,
chemical/pharmaceutical R&D, process monitoring, food safety,
toxicology, forensics, materials science, environmental monitoring,
athletics (anti-doping), histology (medical),…
What is mass spectrometry?
5
Separation and quantification of ions in a mixture, by mass.
• An electrical or electromagnetic technique. Separation by m/z, not m.
• Applications: Chemical/pharmaceutical manufacture,
chemical/pharmaceutical R&D, process monitoring, food safety,
toxicology, forensics, materials science, environmental monitoring,
athletics (anti-doping), histology (medical),…
• Proteomics, metabolomics, glycomics, cell biology, genomics,…
What is mass spectrometry?
6
Separation and quantification of ions in a mixture, by mass.
• An electrical or electromagnetic technique. Separation by m/z, not m.
• Applications: Chemical/pharmaceutical manufacture,
chemical/pharmaceutical R&D, process monitoring, food safety,
toxicology, forensics, materials science, environmental monitoring,
athletics (anti-doping), histology (medical),…
• Proteomics, metabolomics, glycomics, cell biology, genomics,…
• Future: Surgery, personalized medicine.
What is mass spectrometry?
7
• MS/MS: Separate, fragment,
separate again
The modern standard technique: Tandem MS
8
• MS/MS: Separate, fragment,
separate again
The modern standard technique: Tandem MS
9
• MS/MS: Separate, fragment,
separate again
The modern standard technique: Tandem MS
10
• MS/MS: Separate, fragment,
separate again
• a.k.a. MS2. MSn is possible with
ion traps.
The modern standard technique: Tandem MS
11
• MS/MS: Separate, fragment,
separate again
• a.k.a. MS2. MSn is possible with
ion traps.
• Greater specificity than single-
stage MS
The modern standard technique: Tandem MS
12
• MS/MS: Separate, fragment,
separate again
• a.k.a. MS2. MSn is possible with
ion traps.
• Greater specificity than single-
stage MS
• Excitation by collision, electron
transfer, or laser pulse
The modern standard technique: Tandem MS
13
• MS/MS: Separate, fragment,
separate again
• a.k.a. MS2. MSn is possible with
ion traps.
• Greater specificity than single-
stage MS
• Excitation by collision, electron
transfer, or laser pulse
The modern standard technique: Tandem MS
14
• MS/MS: Separate, fragment,
separate again
• a.k.a. MS2. MSn is possible with
ion traps.
• Greater specificity than single-
stage MS
• Excitation by collision, electron
transfer, or laser pulse
• Often coupled with other
separation techniques:
• Liquid chromatography
• Gas chromatography
• Ion mobility
• FAIMS
The modern standard technique: Tandem MS
15
Orbitrap Fusion™,
Orbitrap Fusion Lumos™
hybrid mass spectrometers
TSQ Endura™, TSQ Quantiva™,
Endura MD™ triple-stage
quadrupole mass spectrometers
Thermo Fisher Scientific Lua-Controlled Mass Spectrometers
• Unit mass to 0.2 amu resolution
• Triple quadrupole, high throughput
• Quantitation or search for known targets
• Resolving power (m/Δm): 500,000
• Quadrupole filter, ion trap, and Orbitrap
(Tribrid™ architecture)
• De novo discovery and identification
16
Orbitrap Fusion™,
Orbitrap Fusion Lumos™
hybrid mass spectrometers
TSQ Endura™, TSQ Quantiva™,
Endura MD™ triple-stage
quadrupole mass spectrometers
Thermo Fisher Scientific Lua-Controlled Mass Spectrometers
• Unit mass to 0.2 amu resolution
• Triple quadrupole, high throughput
• Quantitation or search for known targets
• Resolving power (m/Δm): 500,000
• Quadrupole filter, ion trap, and Orbitrap
(Tribrid™ architecture)
• De novo discovery and identification
17
Orbitrap Fusion™,
Orbitrap Fusion Lumos™
hybrid mass spectrometers
TSQ Endura™, TSQ Quantiva™,
Endura MD™ triple-stage
quadrupole mass spectrometers
Thermo Fisher Scientific Lua-Controlled Mass Spectrometers
• Unit mass to 0.2 amu resolution
• Triple quadrupole, high throughput
• Quantitation or search for known targets
• Resolving power (m/Δm): 500,000
• Quadrupole filter, ion trap, and Orbitrap
(Tribrid™ architecture)
• De novo discovery and identification
18
1. Control device (on/off, system voltage,
controller target) getters/setters and
readback device getters implemented in
device objects. Device objects are
lightweight userdatas.
Lua for instrument control: how Thermo does it.
19
1. Control device (on/off, system voltage,
controller target) getters/setters and
readback device getters implemented in
device objects. Device objects are
lightweight userdatas.
2. Table of voltage settings appropriate for
scans are held in a (virtual) calibration file.
Lua for instrument control: how Thermo does it.
20
1. Control device (on/off, system voltage,
controller target) getters/setters and
readback device getters implemented in
device objects. Device objects are
lightweight userdatas.
2. Table of voltage settings appropriate for
scans are held in a (virtual) calibration file.
3. Voltages during scan are stored in a “scan
matrix” run at high speed by the DSP.
Interface provided by dedicated matrix
builder functions.
Lua for instrument control: how Thermo does it.
21
1. Control device (on/off, system voltage,
controller target) getters/setters and
readback device getters implemented in
device objects. Device objects are
lightweight userdatas.
2. Table of voltage settings appropriate for
scans are held in a (virtual) calibration file.
3. Voltages during scan are stored in a “scan
matrix” run at high speed by the DSP.
Interface provided by dedicated matrix
builder functions.
4. Scan matrix is defined by a smaller set of
scan state variables. Scan setup functions
provided in Lua. Experiment loops and scan
execution function insulate most tasks from
scan matrix manipulation and DSP control.
Lua for instrument control: how Thermo does it.
22
1. Control device (on/off, system voltage,
controller target) getters/setters and
readback device getters implemented in
device objects. Device objects are
lightweight userdatas.
2. Table of voltage settings appropriate for
scans are held in a (virtual) calibration file.
3. Voltages during scan are stored in a “scan
matrix” run at high speed by the DSP.
Interface provided by dedicated matrix
builder functions.
4. Scan matrix is defined by a smaller set of
scan state variables. Scan setup functions
provided in Lua. Experiment loops and scan
execution function insulate most tasks from
scan matrix manipulation and DSP control.
5. Data query primitives provide information
about the buffered spectrum to Lua.
Lua for instrument control: how Thermo does it.
23
for i = 1, totalScans do
-- acquire TIC for DRAG_1 = 100V DRAG_2 = 0V
if Sys.Abort()==true then
RestoreDragCellVoltages()
print("Aborted by user.")
error(Diag.exceptions.ABORT)
end
xvalues[i]=i
CF2:SetAndUpdate(100, DRAG_1)
CF2:SetAndUpdate(0, DRAG_2)
Sys.TakeAScan() -- take one scan to warm up the MS
Sys.TakeAveragedScan(5)
arrayTICforDRAG_1at100V[i] = DQ:TIC();
addedTICforDRAG_1at100V = addedTICforDRAG_1at100V + arrayTICforDRAG_1at100V[i];
-- acquire TIC for DRAG_1 = 0V DRAG_2 = 100V
CF2:SetAndUpdate(0, DRAG_1)
CF2:SetAndUpdate(100, DRAG_2)
Sys.TakeAScan() -- take one scan to warm up the MS
Sys.TakeAveragedScan(5);
arrayTICforDRAG_2at100V[i] = DQ:TIC();
addedTICforDRAG_2at100V = addedTICforDRAG_2at100V + arrayTICforDRAG_2at100V[i];
end
Lua in the mass spectrometer: first example
24
for i = 1, totalScans do
-- acquire TIC for DRAG_1 = 100V DRAG_2 = 0V
if Sys.Abort()==true then
RestoreDragCellVoltages()
print("Aborted by user.")
error(Diag.exceptions.ABORT)
end
xvalues[i]=i
CF2:SetAndUpdate(100, DRAG_1)
CF2:SetAndUpdate(0, DRAG_2)
Sys.TakeAScan() -- take one scan to warm up the MS
Sys.TakeAveragedScan(5)
arrayTICforDRAG_1at100V[i] = DQ:TIC();
addedTICforDRAG_1at100V = addedTICforDRAG_1at100V + arrayTICforDRAG_1at100V[i];
-- acquire TIC for DRAG_1 = 0V DRAG_2 = 100V
CF2:SetAndUpdate(0, DRAG_1)
CF2:SetAndUpdate(100, DRAG_2)
Sys.TakeAScan() -- take one scan to warm up the MS
Sys.TakeAveragedScan(5);
arrayTICforDRAG_2at100V[i] = DQ:TIC();
addedTICforDRAG_2at100V = addedTICforDRAG_2at100V + arrayTICforDRAG_2at100V[i];
end
Lua in the mass spectrometer: first example
Imperative control is
possible. Easy for casual
programmers, but
inefficient.
25
for i = 1, totalScans do
-- acquire TIC for DRAG_1 = 100V DRAG_2 = 0V
if Sys.Abort()==true then
RestoreDragCellVoltages()
print("Aborted by user.")
error(Diag.exceptions.ABORT)
end
xvalues[i]=i
CF2:SetAndUpdate(100, DRAG_1)
CF2:SetAndUpdate(0, DRAG_2)
Sys.TakeAScan() -- take one scan to warm up the MS
Sys.TakeAveragedScan(5)
arrayTICforDRAG_1at100V[i] = DQ:TIC();
addedTICforDRAG_1at100V = addedTICforDRAG_1at100V + arrayTICforDRAG_1at100V[i];
-- acquire TIC for DRAG_1 = 0V DRAG_2 = 100V
CF2:SetAndUpdate(0, DRAG_1)
CF2:SetAndUpdate(100, DRAG_2)
Sys.TakeAScan() -- take one scan to warm up the MS
Sys.TakeAveragedScan(5);
arrayTICforDRAG_2at100V[i] = DQ:TIC();
addedTICforDRAG_2at100V = addedTICforDRAG_2at100V + arrayTICforDRAG_2at100V[i];
end
Lua in the mass spectrometer: first example
Imperative control is
possible. Easy for casual
programmers, but
inefficient.
Components here:
• System voltage table
manipulation
26
for i = 1, totalScans do
-- acquire TIC for DRAG_1 = 100V DRAG_2 = 0V
if Sys.Abort()==true then
RestoreDragCellVoltages()
print("Aborted by user.")
error(Diag.exceptions.ABORT)
end
xvalues[i]=i
CF2:SetAndUpdate(100, DRAG_1)
CF2:SetAndUpdate(0, DRAG_2)
Sys.TakeAScan() -- take one scan to warm up the MS
Sys.TakeAveragedScan(5)
arrayTICforDRAG_1at100V[i] = DQ:TIC();
addedTICforDRAG_1at100V = addedTICforDRAG_1at100V + arrayTICforDRAG_1at100V[i];
-- acquire TIC for DRAG_1 = 0V DRAG_2 = 100V
CF2:SetAndUpdate(0, DRAG_1)
CF2:SetAndUpdate(100, DRAG_2)
Sys.TakeAScan() -- take one scan to warm up the MS
Sys.TakeAveragedScan(5);
arrayTICforDRAG_2at100V[i] = DQ:TIC();
addedTICforDRAG_2at100V = addedTICforDRAG_2at100V + arrayTICforDRAG_2at100V[i];
end
Lua in the mass spectrometer: first example
Imperative control is
possible. Easy for casual
programmers, but
inefficient.
Components here:
• System voltage table
manipulation
• Scan dispatch
27
for i = 1, totalScans do
-- acquire TIC for DRAG_1 = 100V DRAG_2 = 0V
if Sys.Abort()==true then
RestoreDragCellVoltages()
print("Aborted by user.")
error(Diag.exceptions.ABORT)
end
xvalues[i]=i
CF2:SetAndUpdate(100, DRAG_1)
CF2:SetAndUpdate(0, DRAG_2)
Sys.TakeAScan() -- take one scan to warm up the MS
Sys.TakeAveragedScan(5)
arrayTICforDRAG_1at100V[i] = DQ:TIC();
addedTICforDRAG_1at100V = addedTICforDRAG_1at100V + arrayTICforDRAG_1at100V[i];
-- acquire TIC for DRAG_1 = 0V DRAG_2 = 100V
CF2:SetAndUpdate(0, DRAG_1)
CF2:SetAndUpdate(100, DRAG_2)
Sys.TakeAScan() -- take one scan to warm up the MS
Sys.TakeAveragedScan(5);
arrayTICforDRAG_2at100V[i] = DQ:TIC();
addedTICforDRAG_2at100V = addedTICforDRAG_2at100V + arrayTICforDRAG_2at100V[i];
end
Lua in the mass spectrometer: first example
Imperative control is
possible. Easy for casual
programmers, but
inefficient.
Components here:
• System voltage table
manipulation
• Scan dispatch
• Data query
28
for i = 1, totalScans do
-- acquire TIC for DRAG_1 = 100V DRAG_2 = 0V
if Sys.Abort()==true then
RestoreDragCellVoltages()
print("Aborted by user.")
error(Diag.exceptions.ABORT)
end
xvalues[i]=i
CF2:SetAndUpdate(100, DRAG_1)
CF2:SetAndUpdate(0, DRAG_2)
Sys.TakeAScan() -- take one scan to warm up the MS
Sys.TakeAveragedScan(5)
arrayTICforDRAG_1at100V[i] = DQ:TIC();
addedTICforDRAG_1at100V = addedTICforDRAG_1at100V + arrayTICforDRAG_1at100V[i];
-- acquire TIC for DRAG_1 = 0V DRAG_2 = 100V
CF2:SetAndUpdate(0, DRAG_1)
CF2:SetAndUpdate(100, DRAG_2)
Sys.TakeAScan() -- take one scan to warm up the MS
Sys.TakeAveragedScan(5);
arrayTICforDRAG_2at100V[i] = DQ:TIC();
addedTICforDRAG_2at100V = addedTICforDRAG_2at100V + arrayTICforDRAG_2at100V[i];
end
Lua in the mass spectrometer: first example
Imperative control is
possible. Easy for casual
programmers, but
inefficient.
Components here:
• System voltage table
manipulation
• Scan dispatch
• Data query
Not shown:
• Scan matrix builder
• Direct voltage control
29
• The goal: Operate on data, don’t explicitly control execution.
(More declarative, less imperative.)
• Build a program by composing operations.
Core higher-order functions: map, filter, and reduce
30
• The goal: Operate on data, don’t explicitly control execution.
(More declarative, less imperative.)
• Build a program by composing operations.
• Core tools:
• Map
Applies a function to each element of the input. (Maps domain points to range points.)
Map(f,{a,b,c,…})→{f(a),f(b),f(c),…}
Core higher-order functions: map, filter, and reduce
31
• The goal: Operate on data, don’t explicitly control execution.
(More declarative, less imperative.)
• Build a program by composing operations.
• Core tools:
• Map
Applies a function to each element of the input. (Maps domain points to range points.)
Map(f,{a,b,c,…})→{f(a),f(b),f(c),…}
• Filter
Removes input elements from the output if they do not satisfy a provided predicate.
Filter(f,{a,b,c,…})→{f(a) and a or nil,f(b)and b or nil,…}
Core higher-order functions: map, filter, and reduce
32
• The goal: Operate on data, don’t explicitly control execution.
(More declarative, less imperative.)
• Build a program by composing operations.
• Core tools:
• Map
Applies a function to each element of the input. (Maps domain points to range points.)
Map(f,{a,b,c,…})→{f(a),f(b),f(c),…}
• Filter
Removes input elements from the output if they do not satisfy a provided predicate.
Filter(f,{a,b,c,…})→{f(a) and a or nil,f(b)and b or nil,…}
• Reduce (left fold)
Applies a function pairwise from left to right, reducing the set to a single value.
Sums, products, projections, and multi-function composition are some
examples.
Reduce(f,{a,b,c,…})→f(…(f(f(a,b),c),…)
Core higher-order functions: map, filter, and reduce
33
Iterator pipelines allow the series of operations to be applied one element at a time.
• Map:
function Map(fun,first,second,third)
local itercoroutine=function ()
for value in (function () return first,second,third end)() do
coroutine.yield(fun(value))
end
end
return coroutine.wrap(itercoroutine),nil,nil
end
Composable iterators (iterator pipelines)
34
Iterator pipelines allow the series of operations to be applied one element at a time.
• Map:
function Map(fun,first,second,third)
local itercoroutine=function ()
for value in (function () return first,second,third end)() do
coroutine.yield(fun(value))
end
end
return coroutine.wrap(itercoroutine),nil,nil
end
• Filter:
function Filter(condition,first,second,third)
local itercoroutine=function ()
for value in (function () return first,second,third end)() do
if condition(value) then coroutine.yield(value) end
end
end
return coroutine.wrap(itercoroutine),nil,nil
end
Composable iterators (iterator pipelines)
35
Iterator pipelines allow the series of operations to be applied one element at a time.
• Map:
function Map(fun,first,second,third)
local itercoroutine=function ()
for value in (function () return first,second,third end)() do
coroutine.yield(fun(value))
end
end
return coroutine.wrap(itercoroutine),nil,nil
end
• Filter:
function Filter(condition,first,second,third)
local itercoroutine=function ()
for value in (function () return first,second,third end)() do
if condition(value) then coroutine.yield(value) end
end
end
return coroutine.wrap(itercoroutine),nil,nil
end
• Reduce:
function Reduce(func,first,second,third)
local initialized=false
local accumulator
for value in (function () return first,second,third end)() do
if not initialized then
accumulator=value
initialized=true
else
accumulator=func(accumulator,value)
end
return accumulator
end
Composable iterators (iterator pipelines)
36
• Operations should support unordered hashtables, where applicable.
• Map and Filter iterate using pairs, keeping input table keys:
Map(f,{[foo]=a,[bar]=b,[baz]=c})
→ {[foo]=f(a),[bar]=f(b),[baz]=f(c)}
Lua-specific considerations (or: Lua is not Lisp.)
37
• Operations should support unordered hashtables, where applicable.
• Map and Filter iterate using pairs, keeping input table keys:
Map(f,{[foo]=a,[bar]=b,[baz]=c})
→ {[foo]=f(a),[bar]=f(b),[baz]=f(c)}
• KeyValueMapping operation is very useful: define a table as a function of
the keys. E.g:
KeyValueMapping(OddOrEven,{2,10,11})
→ {[2]=“even”, [10]=“even”, [11]=“odd”}
Lua-specific considerations (or: Lua is not Lisp.)
38
• Operations should support unordered hashtables, where applicable.
• Map and Filter iterate using pairs, keeping input table keys:
Map(f,{[foo]=a,[bar]=b,[baz]=c})
→ {[foo]=f(a),[bar]=f(b),[baz]=f(c)}
• KeyValueMapping operation is very useful: define a table as a function of
the keys. E.g:
KeyValueMapping(OddOrEven,{2,10,11})
→ {[2]=“even”, [10]=“even”, [11]=“odd”}
• Keyed Zip and Unzip: Zip into keyed tables, unzip from keyed tables:
KeyedZip({“pants”,”size”},{“corduroy”,”gabardine”},{32,36})
→ {{pants=“corduroy”,size=32},{pants=“gabardine”,size=36}
Lua-specific considerations (or: Lua is not Lisp.)
39
• Operations should support unordered hashtables, where applicable.
• Map and Filter iterate using pairs, keeping input table keys:
Map(f,{[foo]=a,[bar]=b,[baz]=c})
→ {[foo]=f(a),[bar]=f(b),[baz]=f(c)}
• KeyValueMapping operation is very useful: define a table as a function of
the keys. E.g:
KeyValueMapping(OddOrEven,{2,10,11})
→ {[2]=“even”, [10]=“even”, [11]=“odd”}
• Keyed Zip and Unzip: Zip into keyed tables, unzip from keyed tables:
KeyedZip({“pants”,”size”},{“corduroy”,”gabardine”},{32,36})
→ {{pants=“corduroy”,size=32},{pants=“gabardine”,size=36}
Lua-specific considerations (or: Lua is not Lisp.)
(Keyedunzip is inverse of keyed zip)
40
local setpoints,sprayCurrents,intensities=
table.KeyedUnzip(
fun.IteratorToArray(
fun.Map(AcquireResponse,
fun.TerminateIf(APCIIsOutOfControl,
fun.Map(SetAndReadback,
fun.Values(grid))))),
{"setting","readback","ionIntensity"})
• Motivation: current is limited by
spray chemistry, and true value
can lag setpoint
Example 1: Ion source tuning (with complications)
41
local setpoints,sprayCurrents,intensities=
table.KeyedUnzip(
fun.IteratorToArray(
fun.Map(AcquireResponse,
fun.TerminateIf(APCIIsOutOfControl,
fun.Map(SetAndReadback,
fun.Values(grid))))),
{"setting","readback","ionIntensity"})
• Motivation: current is limited by
spray chemistry, and true value
can lag setpoint
• From the inside out:
1. Values makes an iterator from a table
Example 1: Ion source tuning (with complications)
42
local setpoints,sprayCurrents,intensities=
table.KeyedUnzip(
fun.IteratorToArray(
fun.Map(AcquireResponse,
fun.TerminateIf(APCIIsOutOfControl,
fun.Map(SetAndReadback,
fun.Values(grid))))),
{"setting","readback","ionIntensity"})
• Motivation: current is limited by
spray chemistry, and true value
can lag setpoint
• From the inside out:
1. Values makes an iterator from a table
2. SetAndReadback sets the current
target, waits, and takes a
measurement
Example 1: Ion source tuning (with complications)
43
local setpoints,sprayCurrents,intensities=
table.KeyedUnzip(
fun.IteratorToArray(
fun.Map(AcquireResponse,
fun.TerminateIf(APCIIsOutOfControl,
fun.Map(SetAndReadback,
fun.Values(grid))))),
{"setting","readback","ionIntensity"})
• Motivation: current is limited by
spray chemistry, and true value
can lag setpoint
• From the inside out:
1. Values makes an iterator from a table
2. SetAndReadback sets the current
target, waits, and takes a
measurement
3. TerminateIf is an iterator
controller/passthrough, breaking
iteration if the current iterand satisfies
a predicate
Example 1: Ion source tuning (with complications)
44
local setpoints,sprayCurrents,intensities=
table.KeyedUnzip(
fun.IteratorToArray(
fun.Map(AcquireResponse,
fun.TerminateIf(APCIIsOutOfControl,
fun.Map(SetAndReadback,
fun.Values(grid))))),
{"setting","readback","ionIntensity"})
• Motivation: current is limited by
spray chemistry, and true value
can lag setpoint
• From the inside out:
1. Values makes an iterator from a table
2. SetAndReadback sets the current
target, waits, and takes a
measurement
3. TerminateIf is an iterator
controller/passthrough, breaking
iteration if the current iterand satisfies
a predicate
4. AcquireResponse is at left
Example 1: Ion source tuning (with complications)
local AcquireResponse=
function (sourceStatus)
Sys.TakeAveragedScan(nScans)
return {setting=sourceStatus.setting,
readback=sourceStatus.readback,
ionIntensity=DQ:TIC()}
end
45
local setpoints,sprayCurrents,intensities=
table.KeyedUnzip(
fun.IteratorToArray(
fun.Map(AcquireResponse,
fun.TerminateIf(APCIIsOutOfControl,
fun.Map(SetAndReadback,
fun.Values(grid))))),
{"setting","readback","ionIntensity"})
• Motivation: current is limited by
spray chemistry, and true value
can lag setpoint
• From the inside out:
1. Values makes an iterator from a table
2. SetAndReadback sets the current
target, waits, and takes a
measurement
3. TerminateIf is an iterator
controller/passthrough, breaking
iteration if the current iterand satisfies
a predicate
4. AcquireResponse is at left
5. We pack it all into an array, then
unzip for further processing.
Example 1: Ion source tuning (with complications)
local AcquireResponse=
function (sourceStatus)
Sys.TakeAveragedScan(nScans)
return {setting=sourceStatus.setting,
readback=sourceStatus.readback,
ionIntensity=DQ:TIC()}
end
46
local setpoints,sprayCurrents,intensities=
table.KeyedUnzip(
fun.IteratorToArray(
fun.Map(AcquireResponse,
fun.TerminateIf(APCIIsOutOfControl,
fun.Map(SetAndReadback,
fun.Values(grid))))),
{"setting","readback","ionIntensity"})
• Motivation: current is limited by
spray chemistry, and true value
can lag setpoint
• From the inside out:
1. Values makes an iterator from a table
2. SetAndReadback sets the current
target, waits, and takes a
measurement
3. TerminateIf is an iterator
controller/passthrough, breaking
iteration if the current iterand satisfies
a predicate
4. AcquireResponse is at left
5. We pack it all into an array, then
unzip for further processing.
Example 1: Ion source tuning (with complications)
local AcquireResponse=
function (sourceStatus)
Sys.TakeAveragedScan(nScans)
return {setting=sourceStatus.setting,
readback=sourceStatus.readback,
ionIntensity=DQ:TIC()}
end
47
function
utils.AutoPlotOneParameterFunction(f,Plotter)
return function(x)
local y=f(x)
Plotter(x,y)
return y
end
end
Example 1 continued: Function decoration for output and more.
48
function
utils.AutoPlotOneParameterFunction(f,Plotter)
return function(x)
local y=f(x)
Plotter(x,y)
return y
end
end
Example 1 continued: Function decoration for output and more.
AcquireResponse=
utils.AutoPlotOneParameterFunction(
AcquireResponse,
function (x,y)
graph:Plot(x.readback,y.ionIntensity,2)
end)
49
function
utils.AutoPlotOneParameterFunction(f,Plotter)
return function(x)
local y=f(x)
Plotter(x,y)
return y
end
end
Example 1 continued: Function decoration for output and more.
AcquireResponse=
utils.AutoPlotOneParameterFunction(
AcquireResponse,
function (x,y)
graph:Plot(x.readback,y.ionIntensity,2)
end)
AcquireResponse=
CO.ErrorHandlerDecorator(
AcquireResponse,
Cal.CommonErrorHandler())
50
local pCallStatus,result=
pcall(function ()
return fun.IteratorToArray(
fun.Map(utils.AutoPlotOneParameterFunction(ReadDevices(readbackDevices),Plotter),
fun.Map(SetDeviceAndSleep(rampDevice,sleepTime),
fun.iValues(table.Range(rampStart,rampStop,stepSize)))))
end)
Example 2: Electronics ramp test
51
local pCallStatus,result=
pcall(function ()
return fun.IteratorToArray(
fun.Map(utils.AutoPlotOneParameterFunction(ReadDevices(readbackDevices),Plotter),
fun.Map(SetDeviceAndSleep(rampDevice,sleepTime),
fun.iValues(table.Range(rampStart,rampStop,stepSize)))))
end)
Example 2: Electronics ramp test
Creates a function of setpoint that returns a table:
{setpoint=setpoint,
responses=a table of device readbacks, keyed by device)}
52
local pCallStatus,result=
pcall(function ()
return fun.IteratorToArray(
fun.Map(utils.AutoPlotOneParameterFunction(ReadDevices(readbackDevices),Plotter),
fun.Map(SetDeviceAndSleep(rampDevice,sleepTime),
fun.iValues(table.Range(rampStart,rampStop,stepSize)))))
end)
Example 2: Electronics ramp test
53
local pCallStatus,result=
pcall(function ()
return fun.IteratorToArray(
fun.Map(utils.AutoPlotOneParameterFunction(ReadDevices(readbackDevices),Plotter),
fun.Map(SetDeviceAndSleep(rampDevice,sleepTime),
fun.iValues(table.Range(rampStart,rampStop,stepSize)))))
end)
(Restore system state, process pcall, omitted from example)
local setpoints,responses=table.KeyedUnzip(result,{"setpoint","readbacks"})
local selfResponse,crossResponses=table.KeyedUnzip(responses,{selfReadback}),
table.KeyedTranspose(responses,otherReadDevices)
responses=table.KeyedTranspose(responses,readbackDevices)
Example 2: Electronics ramp test
54
local pCallStatus,result=
pcall(function ()
return fun.IteratorToArray(
fun.Map(utils.AutoPlotOneParameterFunction(ReadDevices(readbackDevices),Plotter),
fun.Map(SetDeviceAndSleep(rampDevice,sleepTime),
fun.iValues(table.Range(rampStart,rampStop,stepSize)))))
end)
(Restore system state, process pcall, omitted from example)
local setpoints,responses=table.KeyedUnzip(result,{"setpoint","readbacks"})
local selfResponse,crossResponses=table.KeyedUnzip(responses,{selfReadback}),
table.KeyedTranspose(responses,otherReadDevices)
responses=table.KeyedTranspose(responses,readbackDevices)
(Evaluate device setpoint-readback correspondence, omitted from example)
--Now check the cross responses:
local impedances=
table.KeyValueMapping(function (dev) return MutualImpedance(selfResponse,crossResponses[dev]) end,
otherReadDevices)
local shortedDevices=
fun.Filter(function (dev) return impedances[dev]<minMutualImpedance end,otherReadDevices)
(Plotting of suspected shorts, return table formatting omitted)
Example 2: Electronics ramp test
55
Compound-dependent tuning of a TSQ mass spectrometer
56
Compound-dependent tuning of a TSQ mass spectrometer
More ions==greater sensitivity.
Greater precision, lower LLOD and LLOQ,
or Higher throughput,
or lower assay cost
57
Compound-dependent tuning of a TSQ mass spectrometer
Ion source parameters (voltages, gas flows)
are dependent on chemistry and sample
delivery rate.
58
Compound-dependent tuning of a TSQ mass spectrometer
Ion funnel: RF tuning trades off several
effects; DC offset used for declustering
or fragmentation.
59
Compound-dependent tuning of a TSQ mass spectrometer
Ion funnel: RF tuning trades off several
effects; DC offset used for declustering
or fragmentation.
60
Compound-dependent tuning of a TSQ mass spectrometer
Fragment ions to select in Q3
for are often unknown.
61
Compound-dependent tuning of a TSQ mass spectrometer
Collision energy optimizing any
CID transition must be
determined empirically.
62
• We want to be able to insert or remove optimizations at (customer) will.
• Future compatibility is also desired.
• Optimizations should use previous results in a clean way.
• Design:
• Precursor and product data structures: attributes name, mass, tunings, etc.
• Precursor ion optimizations take a precursor as input and yield a precursor as
output, with updated tunings or updated mass.
• Product ion optimizations are similar
• Optimizations are composed/put into sequence by function composition.
• Optimization internals may be procedural code, but no persistent side effects or
communication at a distance through instrument state allowed. (Either clean up
state changes or be indifferent.)
Optimizations as pure and composable functions
63
Assay optimization: Handling state using decorators
• Decorator sets system according to previous tunings; optimizer functions concerned
only with their proper optimization operation:
local function PrecursorStateSetter(precursor)
local doWait=false
if Sys.Polarity()~=precursor.polarity then
DS:SetSystemPolarity(precursor.polarity)
doWait=true
end
--Set ion source devices
for _,dev in pairs(Sys.IonSourceDevices()) do
if precursor.tunings[dev.name] and (precursor.tunings[dev.name]~=dev.value) then
CF2:SetAndUpdate(precursor.tunings[dev.name],dev)
doWait=true
end
end
--Now set everything else:
(…)
if doWait then SleepSec(SOURCE_WAIT) end
return
end
function CO.StateManipulationDecoratorPrecursor(f)
return function (precursor)
if precursor then PrecursorStateSetter(precursor) end
return f(precursor)
end
end
64
Assay optimization: Handling state using decorators
Sample delivery request and detection by sample delivery decorator:
function CO.GetSampleDecorator(f,timeout)
return function (ion)
local monitoredMZ= ion.precursor and ion.precursor.mz or ion.mz
--This construction makes this precursor or product compatible
local monitoredPolarity=ion.precursor and ion.precursor.polarity or ion.polarity
if firstInjectionReceived then --Don't do this for first injection of a series.
Signal(DS.SIG_REQUEST_SAMPLE)
if not MethodControl.WaitCC()
error(CO.exceptions.ABORTED_WAITING)
end
end
local result=Sys.GetSample({mass parameters: omitted details},timeout,false)
if result==0 then
Signal(DS.SIG_SAMPLE_NOT_RECEIVED)
(…)
error(CO.exceptions.SAMPLE_NOT_RECEIVED)
elseif result==1 then
Signal(DS.SIG_RECEIVED_SAMPLE)
(…)
end
SleepSec(0.5)
return f(ion)
end
end
65
Composite spectrum generated by
fun.Reduce(function (a,b) return CO.MergeSpectra(a,b,false) end,
fun.Map(SingleRampScan,fun.Values(CEs)))
where MergeSpectra is a pointwise max intensity selector
function CO.MergeSpectra(a,b)
local retstructure=a
(…)
for index=1,#a.y do
retstructure.y[index]=math.max(a.y[index],b.y[index])
end
return retstructure
end
Assay optimization: Use of Reduce() in product search
66
Optimize precursor list:
local runSucceeded, result=
pcall(function ()
return ProductOptimization(
PrecursorOptimization(
fun.Map(SourceOptimization,
GetInjection(experiment.precursors)))) end)
Optimize product list:
ProductOptimization=
function (precursor)
if precursor then
precursor.products=
fun.IteratorToArray(
fun.Map(function (x) return GraphProductPoint(x) end,
fun.TakeFirstN(experiment.nProducts,
CheckProductExistencesAndCountFailures(
fun.Filter(ProductMassFilterCondition,
fun.Map(OptimizeProduct,
GetProducts(precursor).ProductsIterator))))))
(…)
end
return precursor
end
OptimizeProduct is a composition of optimizer functions (tuning mass, collision energy). A binary compose
operation is reduced across a list to make it.
Assay optimization: putting it all together

More Related Content

Similar to Mass spectrometry assay optimization using functional programming patterns in Lua

Automated Generation of High-accuracy Interatomic Potentials Using Quantum Data
Automated Generation of High-accuracy Interatomic Potentials Using Quantum DataAutomated Generation of High-accuracy Interatomic Potentials Using Quantum Data
Automated Generation of High-accuracy Interatomic Potentials Using Quantum Dataaimsnist
 
Body sensor networks: challenges & applications
Body sensor networks: challenges & applicationsBody sensor networks: challenges & applications
Body sensor networks: challenges & applicationsVasily Ryzhonkov
 
Nuc chemsummerschool 072106-v2
Nuc chemsummerschool 072106-v2Nuc chemsummerschool 072106-v2
Nuc chemsummerschool 072106-v2Dean Quezon
 
Joshua Beckerman, MAE 315 Lab 2 Final Report
Joshua Beckerman, MAE 315 Lab 2 Final ReportJoshua Beckerman, MAE 315 Lab 2 Final Report
Joshua Beckerman, MAE 315 Lab 2 Final ReportJoshua Beckerman
 
Long durationspaceflightoct01
Long durationspaceflightoct01Long durationspaceflightoct01
Long durationspaceflightoct01Clifford Stone
 
2023Dec ASU Wang NETR Group Research Focus and Facility Overview.pptx
2023Dec ASU Wang NETR Group Research Focus and Facility Overview.pptx2023Dec ASU Wang NETR Group Research Focus and Facility Overview.pptx
2023Dec ASU Wang NETR Group Research Focus and Facility Overview.pptxlwang78
 
Presentation on the basic Maldi-Imaging workflow with some information on how...
Presentation on the basic Maldi-Imaging workflow with some information on how...Presentation on the basic Maldi-Imaging workflow with some information on how...
Presentation on the basic Maldi-Imaging workflow with some information on how...Diane Hatziioanou
 
MS (and NMR) data standards in Metabolomics why, how and some caveats
MS (and NMR) data standards in Metabolomics why, how and some caveatsMS (and NMR) data standards in Metabolomics why, how and some caveats
MS (and NMR) data standards in Metabolomics why, how and some caveatsSteffen Neumann
 
Getting started with chemometric classification
Getting started with chemometric classificationGetting started with chemometric classification
Getting started with chemometric classificationAlex Henderson
 
Distributed Data Processing using Spark by Panos Labropoulos_and Sarod Yataw...
Distributed Data Processing using Spark by  Panos Labropoulos_and Sarod Yataw...Distributed Data Processing using Spark by  Panos Labropoulos_and Sarod Yataw...
Distributed Data Processing using Spark by Panos Labropoulos_and Sarod Yataw...Spark Summit
 

Similar to Mass spectrometry assay optimization using functional programming patterns in Lua (20)

Uncompromised Simplicity in a Workflow-Oriented Approach for Routine Gas Chro...
Uncompromised Simplicity in a Workflow-Oriented Approach for Routine Gas Chro...Uncompromised Simplicity in a Workflow-Oriented Approach for Routine Gas Chro...
Uncompromised Simplicity in a Workflow-Oriented Approach for Routine Gas Chro...
 
Syllabus
SyllabusSyllabus
Syllabus
 
G017513945
G017513945G017513945
G017513945
 
Automated Generation of High-accuracy Interatomic Potentials Using Quantum Data
Automated Generation of High-accuracy Interatomic Potentials Using Quantum DataAutomated Generation of High-accuracy Interatomic Potentials Using Quantum Data
Automated Generation of High-accuracy Interatomic Potentials Using Quantum Data
 
TEAMCD_SDR_Briefing
TEAMCD_SDR_BriefingTEAMCD_SDR_Briefing
TEAMCD_SDR_Briefing
 
842 manobianco
842 manobianco842 manobianco
842 manobianco
 
Body sensor networks: challenges & applications
Body sensor networks: challenges & applicationsBody sensor networks: challenges & applications
Body sensor networks: challenges & applications
 
Nuc chemsummerschool 072106-v2
Nuc chemsummerschool 072106-v2Nuc chemsummerschool 072106-v2
Nuc chemsummerschool 072106-v2
 
Triple Quadrupole Gas Chromatography-Mass Spectrometry/Mass Spectrometry Re-i...
Triple Quadrupole Gas Chromatography-Mass Spectrometry/Mass Spectrometry Re-i...Triple Quadrupole Gas Chromatography-Mass Spectrometry/Mass Spectrometry Re-i...
Triple Quadrupole Gas Chromatography-Mass Spectrometry/Mass Spectrometry Re-i...
 
Smartdust
SmartdustSmartdust
Smartdust
 
Cheminformatics and the Structure Elucidation of Natural Products
Cheminformatics and the Structure Elucidation of Natural ProductsCheminformatics and the Structure Elucidation of Natural Products
Cheminformatics and the Structure Elucidation of Natural Products
 
Joshua Beckerman, MAE 315 Lab 2 Final Report
Joshua Beckerman, MAE 315 Lab 2 Final ReportJoshua Beckerman, MAE 315 Lab 2 Final Report
Joshua Beckerman, MAE 315 Lab 2 Final Report
 
Long durationspaceflightoct01
Long durationspaceflightoct01Long durationspaceflightoct01
Long durationspaceflightoct01
 
914 mavroidis[2]
914 mavroidis[2]914 mavroidis[2]
914 mavroidis[2]
 
625i spec-sheet
625i spec-sheet625i spec-sheet
625i spec-sheet
 
2023Dec ASU Wang NETR Group Research Focus and Facility Overview.pptx
2023Dec ASU Wang NETR Group Research Focus and Facility Overview.pptx2023Dec ASU Wang NETR Group Research Focus and Facility Overview.pptx
2023Dec ASU Wang NETR Group Research Focus and Facility Overview.pptx
 
Presentation on the basic Maldi-Imaging workflow with some information on how...
Presentation on the basic Maldi-Imaging workflow with some information on how...Presentation on the basic Maldi-Imaging workflow with some information on how...
Presentation on the basic Maldi-Imaging workflow with some information on how...
 
MS (and NMR) data standards in Metabolomics why, how and some caveats
MS (and NMR) data standards in Metabolomics why, how and some caveatsMS (and NMR) data standards in Metabolomics why, how and some caveats
MS (and NMR) data standards in Metabolomics why, how and some caveats
 
Getting started with chemometric classification
Getting started with chemometric classificationGetting started with chemometric classification
Getting started with chemometric classification
 
Distributed Data Processing using Spark by Panos Labropoulos_and Sarod Yataw...
Distributed Data Processing using Spark by  Panos Labropoulos_and Sarod Yataw...Distributed Data Processing using Spark by  Panos Labropoulos_and Sarod Yataw...
Distributed Data Processing using Spark by Panos Labropoulos_and Sarod Yataw...
 

Recently uploaded

Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptxDecoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptxJoão Esperancinha
 
Gfe Mayur Vihar Call Girls Service WhatsApp -> 9999965857 Available 24x7 ^ De...
Gfe Mayur Vihar Call Girls Service WhatsApp -> 9999965857 Available 24x7 ^ De...Gfe Mayur Vihar Call Girls Service WhatsApp -> 9999965857 Available 24x7 ^ De...
Gfe Mayur Vihar Call Girls Service WhatsApp -> 9999965857 Available 24x7 ^ De...srsj9000
 
OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...
OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...
OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...Soham Mondal
 
Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...
Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...
Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...Dr.Costas Sachpazis
 
Analog to Digital and Digital to Analog Converter
Analog to Digital and Digital to Analog ConverterAnalog to Digital and Digital to Analog Converter
Analog to Digital and Digital to Analog ConverterAbhinavSharma374939
 
HARDNESS, FRACTURE TOUGHNESS AND STRENGTH OF CERAMICS
HARDNESS, FRACTURE TOUGHNESS AND STRENGTH OF CERAMICSHARDNESS, FRACTURE TOUGHNESS AND STRENGTH OF CERAMICS
HARDNESS, FRACTURE TOUGHNESS AND STRENGTH OF CERAMICSRajkumarAkumalla
 
Architect Hassan Khalil Portfolio for 2024
Architect Hassan Khalil Portfolio for 2024Architect Hassan Khalil Portfolio for 2024
Architect Hassan Khalil Portfolio for 2024hassan khalil
 
Introduction to Multiple Access Protocol.pptx
Introduction to Multiple Access Protocol.pptxIntroduction to Multiple Access Protocol.pptx
Introduction to Multiple Access Protocol.pptxupamatechverse
 
Porous Ceramics seminar and technical writing
Porous Ceramics seminar and technical writingPorous Ceramics seminar and technical writing
Porous Ceramics seminar and technical writingrakeshbaidya232001
 
College Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
College Call Girls Nashik Nehal 7001305949 Independent Escort Service NashikCollege Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
College Call Girls Nashik Nehal 7001305949 Independent Escort Service NashikCall Girls in Nagpur High Profile
 
(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...ranjana rawat
 
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur EscortsCall Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur EscortsCall Girls in Nagpur High Profile
 
(RIA) Call Girls Bhosari ( 7001035870 ) HI-Fi Pune Escorts Service
(RIA) Call Girls Bhosari ( 7001035870 ) HI-Fi Pune Escorts Service(RIA) Call Girls Bhosari ( 7001035870 ) HI-Fi Pune Escorts Service
(RIA) Call Girls Bhosari ( 7001035870 ) HI-Fi Pune Escorts Serviceranjana rawat
 
VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130
VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130
VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130Suhani Kapoor
 
the ladakh protest in leh ladakh 2024 sonam wangchuk.pptx
the ladakh protest in leh ladakh 2024 sonam wangchuk.pptxthe ladakh protest in leh ladakh 2024 sonam wangchuk.pptx
the ladakh protest in leh ladakh 2024 sonam wangchuk.pptxhumanexperienceaaa
 
Extrusion Processes and Their Limitations
Extrusion Processes and Their LimitationsExtrusion Processes and Their Limitations
Extrusion Processes and Their Limitations120cr0395
 
SPICE PARK APR2024 ( 6,793 SPICE Models )
SPICE PARK APR2024 ( 6,793 SPICE Models )SPICE PARK APR2024 ( 6,793 SPICE Models )
SPICE PARK APR2024 ( 6,793 SPICE Models )Tsuyoshi Horigome
 

Recently uploaded (20)

Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptxDecoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
 
Gfe Mayur Vihar Call Girls Service WhatsApp -> 9999965857 Available 24x7 ^ De...
Gfe Mayur Vihar Call Girls Service WhatsApp -> 9999965857 Available 24x7 ^ De...Gfe Mayur Vihar Call Girls Service WhatsApp -> 9999965857 Available 24x7 ^ De...
Gfe Mayur Vihar Call Girls Service WhatsApp -> 9999965857 Available 24x7 ^ De...
 
9953056974 Call Girls In South Ex, Escorts (Delhi) NCR.pdf
9953056974 Call Girls In South Ex, Escorts (Delhi) NCR.pdf9953056974 Call Girls In South Ex, Escorts (Delhi) NCR.pdf
9953056974 Call Girls In South Ex, Escorts (Delhi) NCR.pdf
 
OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...
OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...
OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...
 
Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...
Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...
Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...
 
Analog to Digital and Digital to Analog Converter
Analog to Digital and Digital to Analog ConverterAnalog to Digital and Digital to Analog Converter
Analog to Digital and Digital to Analog Converter
 
HARDNESS, FRACTURE TOUGHNESS AND STRENGTH OF CERAMICS
HARDNESS, FRACTURE TOUGHNESS AND STRENGTH OF CERAMICSHARDNESS, FRACTURE TOUGHNESS AND STRENGTH OF CERAMICS
HARDNESS, FRACTURE TOUGHNESS AND STRENGTH OF CERAMICS
 
Architect Hassan Khalil Portfolio for 2024
Architect Hassan Khalil Portfolio for 2024Architect Hassan Khalil Portfolio for 2024
Architect Hassan Khalil Portfolio for 2024
 
Introduction to Multiple Access Protocol.pptx
Introduction to Multiple Access Protocol.pptxIntroduction to Multiple Access Protocol.pptx
Introduction to Multiple Access Protocol.pptx
 
Porous Ceramics seminar and technical writing
Porous Ceramics seminar and technical writingPorous Ceramics seminar and technical writing
Porous Ceramics seminar and technical writing
 
College Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
College Call Girls Nashik Nehal 7001305949 Independent Escort Service NashikCollege Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
College Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
 
(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
 
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur EscortsCall Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
 
(RIA) Call Girls Bhosari ( 7001035870 ) HI-Fi Pune Escorts Service
(RIA) Call Girls Bhosari ( 7001035870 ) HI-Fi Pune Escorts Service(RIA) Call Girls Bhosari ( 7001035870 ) HI-Fi Pune Escorts Service
(RIA) Call Girls Bhosari ( 7001035870 ) HI-Fi Pune Escorts Service
 
VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130
VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130
VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130
 
the ladakh protest in leh ladakh 2024 sonam wangchuk.pptx
the ladakh protest in leh ladakh 2024 sonam wangchuk.pptxthe ladakh protest in leh ladakh 2024 sonam wangchuk.pptx
the ladakh protest in leh ladakh 2024 sonam wangchuk.pptx
 
Extrusion Processes and Their Limitations
Extrusion Processes and Their LimitationsExtrusion Processes and Their Limitations
Extrusion Processes and Their Limitations
 
SPICE PARK APR2024 ( 6,793 SPICE Models )
SPICE PARK APR2024 ( 6,793 SPICE Models )SPICE PARK APR2024 ( 6,793 SPICE Models )
SPICE PARK APR2024 ( 6,793 SPICE Models )
 
Call Us -/9953056974- Call Girls In Vikaspuri-/- Delhi NCR
Call Us -/9953056974- Call Girls In Vikaspuri-/- Delhi NCRCall Us -/9953056974- Call Girls In Vikaspuri-/- Delhi NCR
Call Us -/9953056974- Call Girls In Vikaspuri-/- Delhi NCR
 
Roadmap to Membership of RICS - Pathways and Routes
Roadmap to Membership of RICS - Pathways and RoutesRoadmap to Membership of RICS - Pathways and Routes
Roadmap to Membership of RICS - Pathways and Routes
 

Mass spectrometry assay optimization using functional programming patterns in Lua

  • 1. The world leader in serving scienceLua Workshop 2016, San Francisco, CA Mass spectrometry assay optimization using functional programming patterns in Lua Bennett Kalafut
  • 2. 2 Outline 1. Mass Spectrometry and Lua a) Mass spectrometry basics (what, why, and how?) b) Lua as a control language 2. Iterator pipelines and higher-order table functions a) Core functionals: Map, filter, and reduce b) Lua-specific patterns c) Warm-up 1: Tuning up an ion source d) Warm-up 2: Check some electronics 3. Automated assay optimization a) Why per-assay optimization? b) Optimizations as composable functions c) How to hide/handle state d) Putting it all together
  • 3. 3 Separation and quantification of ions in a mixture, by mass. • An electrical or electromagnetic technique. Separation by m/z, not m. What is mass spectrometry?
  • 4. 4 Separation and quantification of ions in a mixture, by mass. • An electrical or electromagnetic technique. Separation by m/z, not m. • Applications: Chemical/pharmaceutical manufacture, chemical/pharmaceutical R&D, process monitoring, food safety, toxicology, forensics, materials science, environmental monitoring, athletics (anti-doping), histology (medical),… What is mass spectrometry?
  • 5. 5 Separation and quantification of ions in a mixture, by mass. • An electrical or electromagnetic technique. Separation by m/z, not m. • Applications: Chemical/pharmaceutical manufacture, chemical/pharmaceutical R&D, process monitoring, food safety, toxicology, forensics, materials science, environmental monitoring, athletics (anti-doping), histology (medical),… • Proteomics, metabolomics, glycomics, cell biology, genomics,… What is mass spectrometry?
  • 6. 6 Separation and quantification of ions in a mixture, by mass. • An electrical or electromagnetic technique. Separation by m/z, not m. • Applications: Chemical/pharmaceutical manufacture, chemical/pharmaceutical R&D, process monitoring, food safety, toxicology, forensics, materials science, environmental monitoring, athletics (anti-doping), histology (medical),… • Proteomics, metabolomics, glycomics, cell biology, genomics,… • Future: Surgery, personalized medicine. What is mass spectrometry?
  • 7. 7 • MS/MS: Separate, fragment, separate again The modern standard technique: Tandem MS
  • 8. 8 • MS/MS: Separate, fragment, separate again The modern standard technique: Tandem MS
  • 9. 9 • MS/MS: Separate, fragment, separate again The modern standard technique: Tandem MS
  • 10. 10 • MS/MS: Separate, fragment, separate again • a.k.a. MS2. MSn is possible with ion traps. The modern standard technique: Tandem MS
  • 11. 11 • MS/MS: Separate, fragment, separate again • a.k.a. MS2. MSn is possible with ion traps. • Greater specificity than single- stage MS The modern standard technique: Tandem MS
  • 12. 12 • MS/MS: Separate, fragment, separate again • a.k.a. MS2. MSn is possible with ion traps. • Greater specificity than single- stage MS • Excitation by collision, electron transfer, or laser pulse The modern standard technique: Tandem MS
  • 13. 13 • MS/MS: Separate, fragment, separate again • a.k.a. MS2. MSn is possible with ion traps. • Greater specificity than single- stage MS • Excitation by collision, electron transfer, or laser pulse The modern standard technique: Tandem MS
  • 14. 14 • MS/MS: Separate, fragment, separate again • a.k.a. MS2. MSn is possible with ion traps. • Greater specificity than single- stage MS • Excitation by collision, electron transfer, or laser pulse • Often coupled with other separation techniques: • Liquid chromatography • Gas chromatography • Ion mobility • FAIMS The modern standard technique: Tandem MS
  • 15. 15 Orbitrap Fusion™, Orbitrap Fusion Lumos™ hybrid mass spectrometers TSQ Endura™, TSQ Quantiva™, Endura MD™ triple-stage quadrupole mass spectrometers Thermo Fisher Scientific Lua-Controlled Mass Spectrometers • Unit mass to 0.2 amu resolution • Triple quadrupole, high throughput • Quantitation or search for known targets • Resolving power (m/Δm): 500,000 • Quadrupole filter, ion trap, and Orbitrap (Tribrid™ architecture) • De novo discovery and identification
  • 16. 16 Orbitrap Fusion™, Orbitrap Fusion Lumos™ hybrid mass spectrometers TSQ Endura™, TSQ Quantiva™, Endura MD™ triple-stage quadrupole mass spectrometers Thermo Fisher Scientific Lua-Controlled Mass Spectrometers • Unit mass to 0.2 amu resolution • Triple quadrupole, high throughput • Quantitation or search for known targets • Resolving power (m/Δm): 500,000 • Quadrupole filter, ion trap, and Orbitrap (Tribrid™ architecture) • De novo discovery and identification
  • 17. 17 Orbitrap Fusion™, Orbitrap Fusion Lumos™ hybrid mass spectrometers TSQ Endura™, TSQ Quantiva™, Endura MD™ triple-stage quadrupole mass spectrometers Thermo Fisher Scientific Lua-Controlled Mass Spectrometers • Unit mass to 0.2 amu resolution • Triple quadrupole, high throughput • Quantitation or search for known targets • Resolving power (m/Δm): 500,000 • Quadrupole filter, ion trap, and Orbitrap (Tribrid™ architecture) • De novo discovery and identification
  • 18. 18 1. Control device (on/off, system voltage, controller target) getters/setters and readback device getters implemented in device objects. Device objects are lightweight userdatas. Lua for instrument control: how Thermo does it.
  • 19. 19 1. Control device (on/off, system voltage, controller target) getters/setters and readback device getters implemented in device objects. Device objects are lightweight userdatas. 2. Table of voltage settings appropriate for scans are held in a (virtual) calibration file. Lua for instrument control: how Thermo does it.
  • 20. 20 1. Control device (on/off, system voltage, controller target) getters/setters and readback device getters implemented in device objects. Device objects are lightweight userdatas. 2. Table of voltage settings appropriate for scans are held in a (virtual) calibration file. 3. Voltages during scan are stored in a “scan matrix” run at high speed by the DSP. Interface provided by dedicated matrix builder functions. Lua for instrument control: how Thermo does it.
  • 21. 21 1. Control device (on/off, system voltage, controller target) getters/setters and readback device getters implemented in device objects. Device objects are lightweight userdatas. 2. Table of voltage settings appropriate for scans are held in a (virtual) calibration file. 3. Voltages during scan are stored in a “scan matrix” run at high speed by the DSP. Interface provided by dedicated matrix builder functions. 4. Scan matrix is defined by a smaller set of scan state variables. Scan setup functions provided in Lua. Experiment loops and scan execution function insulate most tasks from scan matrix manipulation and DSP control. Lua for instrument control: how Thermo does it.
  • 22. 22 1. Control device (on/off, system voltage, controller target) getters/setters and readback device getters implemented in device objects. Device objects are lightweight userdatas. 2. Table of voltage settings appropriate for scans are held in a (virtual) calibration file. 3. Voltages during scan are stored in a “scan matrix” run at high speed by the DSP. Interface provided by dedicated matrix builder functions. 4. Scan matrix is defined by a smaller set of scan state variables. Scan setup functions provided in Lua. Experiment loops and scan execution function insulate most tasks from scan matrix manipulation and DSP control. 5. Data query primitives provide information about the buffered spectrum to Lua. Lua for instrument control: how Thermo does it.
  • 23. 23 for i = 1, totalScans do -- acquire TIC for DRAG_1 = 100V DRAG_2 = 0V if Sys.Abort()==true then RestoreDragCellVoltages() print("Aborted by user.") error(Diag.exceptions.ABORT) end xvalues[i]=i CF2:SetAndUpdate(100, DRAG_1) CF2:SetAndUpdate(0, DRAG_2) Sys.TakeAScan() -- take one scan to warm up the MS Sys.TakeAveragedScan(5) arrayTICforDRAG_1at100V[i] = DQ:TIC(); addedTICforDRAG_1at100V = addedTICforDRAG_1at100V + arrayTICforDRAG_1at100V[i]; -- acquire TIC for DRAG_1 = 0V DRAG_2 = 100V CF2:SetAndUpdate(0, DRAG_1) CF2:SetAndUpdate(100, DRAG_2) Sys.TakeAScan() -- take one scan to warm up the MS Sys.TakeAveragedScan(5); arrayTICforDRAG_2at100V[i] = DQ:TIC(); addedTICforDRAG_2at100V = addedTICforDRAG_2at100V + arrayTICforDRAG_2at100V[i]; end Lua in the mass spectrometer: first example
  • 24. 24 for i = 1, totalScans do -- acquire TIC for DRAG_1 = 100V DRAG_2 = 0V if Sys.Abort()==true then RestoreDragCellVoltages() print("Aborted by user.") error(Diag.exceptions.ABORT) end xvalues[i]=i CF2:SetAndUpdate(100, DRAG_1) CF2:SetAndUpdate(0, DRAG_2) Sys.TakeAScan() -- take one scan to warm up the MS Sys.TakeAveragedScan(5) arrayTICforDRAG_1at100V[i] = DQ:TIC(); addedTICforDRAG_1at100V = addedTICforDRAG_1at100V + arrayTICforDRAG_1at100V[i]; -- acquire TIC for DRAG_1 = 0V DRAG_2 = 100V CF2:SetAndUpdate(0, DRAG_1) CF2:SetAndUpdate(100, DRAG_2) Sys.TakeAScan() -- take one scan to warm up the MS Sys.TakeAveragedScan(5); arrayTICforDRAG_2at100V[i] = DQ:TIC(); addedTICforDRAG_2at100V = addedTICforDRAG_2at100V + arrayTICforDRAG_2at100V[i]; end Lua in the mass spectrometer: first example Imperative control is possible. Easy for casual programmers, but inefficient.
  • 25. 25 for i = 1, totalScans do -- acquire TIC for DRAG_1 = 100V DRAG_2 = 0V if Sys.Abort()==true then RestoreDragCellVoltages() print("Aborted by user.") error(Diag.exceptions.ABORT) end xvalues[i]=i CF2:SetAndUpdate(100, DRAG_1) CF2:SetAndUpdate(0, DRAG_2) Sys.TakeAScan() -- take one scan to warm up the MS Sys.TakeAveragedScan(5) arrayTICforDRAG_1at100V[i] = DQ:TIC(); addedTICforDRAG_1at100V = addedTICforDRAG_1at100V + arrayTICforDRAG_1at100V[i]; -- acquire TIC for DRAG_1 = 0V DRAG_2 = 100V CF2:SetAndUpdate(0, DRAG_1) CF2:SetAndUpdate(100, DRAG_2) Sys.TakeAScan() -- take one scan to warm up the MS Sys.TakeAveragedScan(5); arrayTICforDRAG_2at100V[i] = DQ:TIC(); addedTICforDRAG_2at100V = addedTICforDRAG_2at100V + arrayTICforDRAG_2at100V[i]; end Lua in the mass spectrometer: first example Imperative control is possible. Easy for casual programmers, but inefficient. Components here: • System voltage table manipulation
  • 26. 26 for i = 1, totalScans do -- acquire TIC for DRAG_1 = 100V DRAG_2 = 0V if Sys.Abort()==true then RestoreDragCellVoltages() print("Aborted by user.") error(Diag.exceptions.ABORT) end xvalues[i]=i CF2:SetAndUpdate(100, DRAG_1) CF2:SetAndUpdate(0, DRAG_2) Sys.TakeAScan() -- take one scan to warm up the MS Sys.TakeAveragedScan(5) arrayTICforDRAG_1at100V[i] = DQ:TIC(); addedTICforDRAG_1at100V = addedTICforDRAG_1at100V + arrayTICforDRAG_1at100V[i]; -- acquire TIC for DRAG_1 = 0V DRAG_2 = 100V CF2:SetAndUpdate(0, DRAG_1) CF2:SetAndUpdate(100, DRAG_2) Sys.TakeAScan() -- take one scan to warm up the MS Sys.TakeAveragedScan(5); arrayTICforDRAG_2at100V[i] = DQ:TIC(); addedTICforDRAG_2at100V = addedTICforDRAG_2at100V + arrayTICforDRAG_2at100V[i]; end Lua in the mass spectrometer: first example Imperative control is possible. Easy for casual programmers, but inefficient. Components here: • System voltage table manipulation • Scan dispatch
  • 27. 27 for i = 1, totalScans do -- acquire TIC for DRAG_1 = 100V DRAG_2 = 0V if Sys.Abort()==true then RestoreDragCellVoltages() print("Aborted by user.") error(Diag.exceptions.ABORT) end xvalues[i]=i CF2:SetAndUpdate(100, DRAG_1) CF2:SetAndUpdate(0, DRAG_2) Sys.TakeAScan() -- take one scan to warm up the MS Sys.TakeAveragedScan(5) arrayTICforDRAG_1at100V[i] = DQ:TIC(); addedTICforDRAG_1at100V = addedTICforDRAG_1at100V + arrayTICforDRAG_1at100V[i]; -- acquire TIC for DRAG_1 = 0V DRAG_2 = 100V CF2:SetAndUpdate(0, DRAG_1) CF2:SetAndUpdate(100, DRAG_2) Sys.TakeAScan() -- take one scan to warm up the MS Sys.TakeAveragedScan(5); arrayTICforDRAG_2at100V[i] = DQ:TIC(); addedTICforDRAG_2at100V = addedTICforDRAG_2at100V + arrayTICforDRAG_2at100V[i]; end Lua in the mass spectrometer: first example Imperative control is possible. Easy for casual programmers, but inefficient. Components here: • System voltage table manipulation • Scan dispatch • Data query
  • 28. 28 for i = 1, totalScans do -- acquire TIC for DRAG_1 = 100V DRAG_2 = 0V if Sys.Abort()==true then RestoreDragCellVoltages() print("Aborted by user.") error(Diag.exceptions.ABORT) end xvalues[i]=i CF2:SetAndUpdate(100, DRAG_1) CF2:SetAndUpdate(0, DRAG_2) Sys.TakeAScan() -- take one scan to warm up the MS Sys.TakeAveragedScan(5) arrayTICforDRAG_1at100V[i] = DQ:TIC(); addedTICforDRAG_1at100V = addedTICforDRAG_1at100V + arrayTICforDRAG_1at100V[i]; -- acquire TIC for DRAG_1 = 0V DRAG_2 = 100V CF2:SetAndUpdate(0, DRAG_1) CF2:SetAndUpdate(100, DRAG_2) Sys.TakeAScan() -- take one scan to warm up the MS Sys.TakeAveragedScan(5); arrayTICforDRAG_2at100V[i] = DQ:TIC(); addedTICforDRAG_2at100V = addedTICforDRAG_2at100V + arrayTICforDRAG_2at100V[i]; end Lua in the mass spectrometer: first example Imperative control is possible. Easy for casual programmers, but inefficient. Components here: • System voltage table manipulation • Scan dispatch • Data query Not shown: • Scan matrix builder • Direct voltage control
  • 29. 29 • The goal: Operate on data, don’t explicitly control execution. (More declarative, less imperative.) • Build a program by composing operations. Core higher-order functions: map, filter, and reduce
  • 30. 30 • The goal: Operate on data, don’t explicitly control execution. (More declarative, less imperative.) • Build a program by composing operations. • Core tools: • Map Applies a function to each element of the input. (Maps domain points to range points.) Map(f,{a,b,c,…})→{f(a),f(b),f(c),…} Core higher-order functions: map, filter, and reduce
  • 31. 31 • The goal: Operate on data, don’t explicitly control execution. (More declarative, less imperative.) • Build a program by composing operations. • Core tools: • Map Applies a function to each element of the input. (Maps domain points to range points.) Map(f,{a,b,c,…})→{f(a),f(b),f(c),…} • Filter Removes input elements from the output if they do not satisfy a provided predicate. Filter(f,{a,b,c,…})→{f(a) and a or nil,f(b)and b or nil,…} Core higher-order functions: map, filter, and reduce
  • 32. 32 • The goal: Operate on data, don’t explicitly control execution. (More declarative, less imperative.) • Build a program by composing operations. • Core tools: • Map Applies a function to each element of the input. (Maps domain points to range points.) Map(f,{a,b,c,…})→{f(a),f(b),f(c),…} • Filter Removes input elements from the output if they do not satisfy a provided predicate. Filter(f,{a,b,c,…})→{f(a) and a or nil,f(b)and b or nil,…} • Reduce (left fold) Applies a function pairwise from left to right, reducing the set to a single value. Sums, products, projections, and multi-function composition are some examples. Reduce(f,{a,b,c,…})→f(…(f(f(a,b),c),…) Core higher-order functions: map, filter, and reduce
  • 33. 33 Iterator pipelines allow the series of operations to be applied one element at a time. • Map: function Map(fun,first,second,third) local itercoroutine=function () for value in (function () return first,second,third end)() do coroutine.yield(fun(value)) end end return coroutine.wrap(itercoroutine),nil,nil end Composable iterators (iterator pipelines)
  • 34. 34 Iterator pipelines allow the series of operations to be applied one element at a time. • Map: function Map(fun,first,second,third) local itercoroutine=function () for value in (function () return first,second,third end)() do coroutine.yield(fun(value)) end end return coroutine.wrap(itercoroutine),nil,nil end • Filter: function Filter(condition,first,second,third) local itercoroutine=function () for value in (function () return first,second,third end)() do if condition(value) then coroutine.yield(value) end end end return coroutine.wrap(itercoroutine),nil,nil end Composable iterators (iterator pipelines)
  • 35. 35 Iterator pipelines allow the series of operations to be applied one element at a time. • Map: function Map(fun,first,second,third) local itercoroutine=function () for value in (function () return first,second,third end)() do coroutine.yield(fun(value)) end end return coroutine.wrap(itercoroutine),nil,nil end • Filter: function Filter(condition,first,second,third) local itercoroutine=function () for value in (function () return first,second,third end)() do if condition(value) then coroutine.yield(value) end end end return coroutine.wrap(itercoroutine),nil,nil end • Reduce: function Reduce(func,first,second,third) local initialized=false local accumulator for value in (function () return first,second,third end)() do if not initialized then accumulator=value initialized=true else accumulator=func(accumulator,value) end return accumulator end Composable iterators (iterator pipelines)
  • 36. 36 • Operations should support unordered hashtables, where applicable. • Map and Filter iterate using pairs, keeping input table keys: Map(f,{[foo]=a,[bar]=b,[baz]=c}) → {[foo]=f(a),[bar]=f(b),[baz]=f(c)} Lua-specific considerations (or: Lua is not Lisp.)
  • 37. 37 • Operations should support unordered hashtables, where applicable. • Map and Filter iterate using pairs, keeping input table keys: Map(f,{[foo]=a,[bar]=b,[baz]=c}) → {[foo]=f(a),[bar]=f(b),[baz]=f(c)} • KeyValueMapping operation is very useful: define a table as a function of the keys. E.g: KeyValueMapping(OddOrEven,{2,10,11}) → {[2]=“even”, [10]=“even”, [11]=“odd”} Lua-specific considerations (or: Lua is not Lisp.)
  • 38. 38 • Operations should support unordered hashtables, where applicable. • Map and Filter iterate using pairs, keeping input table keys: Map(f,{[foo]=a,[bar]=b,[baz]=c}) → {[foo]=f(a),[bar]=f(b),[baz]=f(c)} • KeyValueMapping operation is very useful: define a table as a function of the keys. E.g: KeyValueMapping(OddOrEven,{2,10,11}) → {[2]=“even”, [10]=“even”, [11]=“odd”} • Keyed Zip and Unzip: Zip into keyed tables, unzip from keyed tables: KeyedZip({“pants”,”size”},{“corduroy”,”gabardine”},{32,36}) → {{pants=“corduroy”,size=32},{pants=“gabardine”,size=36} Lua-specific considerations (or: Lua is not Lisp.)
  • 39. 39 • Operations should support unordered hashtables, where applicable. • Map and Filter iterate using pairs, keeping input table keys: Map(f,{[foo]=a,[bar]=b,[baz]=c}) → {[foo]=f(a),[bar]=f(b),[baz]=f(c)} • KeyValueMapping operation is very useful: define a table as a function of the keys. E.g: KeyValueMapping(OddOrEven,{2,10,11}) → {[2]=“even”, [10]=“even”, [11]=“odd”} • Keyed Zip and Unzip: Zip into keyed tables, unzip from keyed tables: KeyedZip({“pants”,”size”},{“corduroy”,”gabardine”},{32,36}) → {{pants=“corduroy”,size=32},{pants=“gabardine”,size=36} Lua-specific considerations (or: Lua is not Lisp.) (Keyedunzip is inverse of keyed zip)
  • 41. 41 local setpoints,sprayCurrents,intensities= table.KeyedUnzip( fun.IteratorToArray( fun.Map(AcquireResponse, fun.TerminateIf(APCIIsOutOfControl, fun.Map(SetAndReadback, fun.Values(grid))))), {"setting","readback","ionIntensity"}) • Motivation: current is limited by spray chemistry, and true value can lag setpoint • From the inside out: 1. Values makes an iterator from a table Example 1: Ion source tuning (with complications)
  • 42. 42 local setpoints,sprayCurrents,intensities= table.KeyedUnzip( fun.IteratorToArray( fun.Map(AcquireResponse, fun.TerminateIf(APCIIsOutOfControl, fun.Map(SetAndReadback, fun.Values(grid))))), {"setting","readback","ionIntensity"}) • Motivation: current is limited by spray chemistry, and true value can lag setpoint • From the inside out: 1. Values makes an iterator from a table 2. SetAndReadback sets the current target, waits, and takes a measurement Example 1: Ion source tuning (with complications)
  • 43. 43 local setpoints,sprayCurrents,intensities= table.KeyedUnzip( fun.IteratorToArray( fun.Map(AcquireResponse, fun.TerminateIf(APCIIsOutOfControl, fun.Map(SetAndReadback, fun.Values(grid))))), {"setting","readback","ionIntensity"}) • Motivation: current is limited by spray chemistry, and true value can lag setpoint • From the inside out: 1. Values makes an iterator from a table 2. SetAndReadback sets the current target, waits, and takes a measurement 3. TerminateIf is an iterator controller/passthrough, breaking iteration if the current iterand satisfies a predicate Example 1: Ion source tuning (with complications)
  • 44. 44 local setpoints,sprayCurrents,intensities= table.KeyedUnzip( fun.IteratorToArray( fun.Map(AcquireResponse, fun.TerminateIf(APCIIsOutOfControl, fun.Map(SetAndReadback, fun.Values(grid))))), {"setting","readback","ionIntensity"}) • Motivation: current is limited by spray chemistry, and true value can lag setpoint • From the inside out: 1. Values makes an iterator from a table 2. SetAndReadback sets the current target, waits, and takes a measurement 3. TerminateIf is an iterator controller/passthrough, breaking iteration if the current iterand satisfies a predicate 4. AcquireResponse is at left Example 1: Ion source tuning (with complications) local AcquireResponse= function (sourceStatus) Sys.TakeAveragedScan(nScans) return {setting=sourceStatus.setting, readback=sourceStatus.readback, ionIntensity=DQ:TIC()} end
  • 45. 45 local setpoints,sprayCurrents,intensities= table.KeyedUnzip( fun.IteratorToArray( fun.Map(AcquireResponse, fun.TerminateIf(APCIIsOutOfControl, fun.Map(SetAndReadback, fun.Values(grid))))), {"setting","readback","ionIntensity"}) • Motivation: current is limited by spray chemistry, and true value can lag setpoint • From the inside out: 1. Values makes an iterator from a table 2. SetAndReadback sets the current target, waits, and takes a measurement 3. TerminateIf is an iterator controller/passthrough, breaking iteration if the current iterand satisfies a predicate 4. AcquireResponse is at left 5. We pack it all into an array, then unzip for further processing. Example 1: Ion source tuning (with complications) local AcquireResponse= function (sourceStatus) Sys.TakeAveragedScan(nScans) return {setting=sourceStatus.setting, readback=sourceStatus.readback, ionIntensity=DQ:TIC()} end
  • 46. 46 local setpoints,sprayCurrents,intensities= table.KeyedUnzip( fun.IteratorToArray( fun.Map(AcquireResponse, fun.TerminateIf(APCIIsOutOfControl, fun.Map(SetAndReadback, fun.Values(grid))))), {"setting","readback","ionIntensity"}) • Motivation: current is limited by spray chemistry, and true value can lag setpoint • From the inside out: 1. Values makes an iterator from a table 2. SetAndReadback sets the current target, waits, and takes a measurement 3. TerminateIf is an iterator controller/passthrough, breaking iteration if the current iterand satisfies a predicate 4. AcquireResponse is at left 5. We pack it all into an array, then unzip for further processing. Example 1: Ion source tuning (with complications) local AcquireResponse= function (sourceStatus) Sys.TakeAveragedScan(nScans) return {setting=sourceStatus.setting, readback=sourceStatus.readback, ionIntensity=DQ:TIC()} end
  • 47. 47 function utils.AutoPlotOneParameterFunction(f,Plotter) return function(x) local y=f(x) Plotter(x,y) return y end end Example 1 continued: Function decoration for output and more.
  • 48. 48 function utils.AutoPlotOneParameterFunction(f,Plotter) return function(x) local y=f(x) Plotter(x,y) return y end end Example 1 continued: Function decoration for output and more. AcquireResponse= utils.AutoPlotOneParameterFunction( AcquireResponse, function (x,y) graph:Plot(x.readback,y.ionIntensity,2) end)
  • 49. 49 function utils.AutoPlotOneParameterFunction(f,Plotter) return function(x) local y=f(x) Plotter(x,y) return y end end Example 1 continued: Function decoration for output and more. AcquireResponse= utils.AutoPlotOneParameterFunction( AcquireResponse, function (x,y) graph:Plot(x.readback,y.ionIntensity,2) end) AcquireResponse= CO.ErrorHandlerDecorator( AcquireResponse, Cal.CommonErrorHandler())
  • 50. 50 local pCallStatus,result= pcall(function () return fun.IteratorToArray( fun.Map(utils.AutoPlotOneParameterFunction(ReadDevices(readbackDevices),Plotter), fun.Map(SetDeviceAndSleep(rampDevice,sleepTime), fun.iValues(table.Range(rampStart,rampStop,stepSize))))) end) Example 2: Electronics ramp test
  • 51. 51 local pCallStatus,result= pcall(function () return fun.IteratorToArray( fun.Map(utils.AutoPlotOneParameterFunction(ReadDevices(readbackDevices),Plotter), fun.Map(SetDeviceAndSleep(rampDevice,sleepTime), fun.iValues(table.Range(rampStart,rampStop,stepSize))))) end) Example 2: Electronics ramp test Creates a function of setpoint that returns a table: {setpoint=setpoint, responses=a table of device readbacks, keyed by device)}
  • 52. 52 local pCallStatus,result= pcall(function () return fun.IteratorToArray( fun.Map(utils.AutoPlotOneParameterFunction(ReadDevices(readbackDevices),Plotter), fun.Map(SetDeviceAndSleep(rampDevice,sleepTime), fun.iValues(table.Range(rampStart,rampStop,stepSize))))) end) Example 2: Electronics ramp test
  • 53. 53 local pCallStatus,result= pcall(function () return fun.IteratorToArray( fun.Map(utils.AutoPlotOneParameterFunction(ReadDevices(readbackDevices),Plotter), fun.Map(SetDeviceAndSleep(rampDevice,sleepTime), fun.iValues(table.Range(rampStart,rampStop,stepSize))))) end) (Restore system state, process pcall, omitted from example) local setpoints,responses=table.KeyedUnzip(result,{"setpoint","readbacks"}) local selfResponse,crossResponses=table.KeyedUnzip(responses,{selfReadback}), table.KeyedTranspose(responses,otherReadDevices) responses=table.KeyedTranspose(responses,readbackDevices) Example 2: Electronics ramp test
  • 54. 54 local pCallStatus,result= pcall(function () return fun.IteratorToArray( fun.Map(utils.AutoPlotOneParameterFunction(ReadDevices(readbackDevices),Plotter), fun.Map(SetDeviceAndSleep(rampDevice,sleepTime), fun.iValues(table.Range(rampStart,rampStop,stepSize))))) end) (Restore system state, process pcall, omitted from example) local setpoints,responses=table.KeyedUnzip(result,{"setpoint","readbacks"}) local selfResponse,crossResponses=table.KeyedUnzip(responses,{selfReadback}), table.KeyedTranspose(responses,otherReadDevices) responses=table.KeyedTranspose(responses,readbackDevices) (Evaluate device setpoint-readback correspondence, omitted from example) --Now check the cross responses: local impedances= table.KeyValueMapping(function (dev) return MutualImpedance(selfResponse,crossResponses[dev]) end, otherReadDevices) local shortedDevices= fun.Filter(function (dev) return impedances[dev]<minMutualImpedance end,otherReadDevices) (Plotting of suspected shorts, return table formatting omitted) Example 2: Electronics ramp test
  • 55. 55 Compound-dependent tuning of a TSQ mass spectrometer
  • 56. 56 Compound-dependent tuning of a TSQ mass spectrometer More ions==greater sensitivity. Greater precision, lower LLOD and LLOQ, or Higher throughput, or lower assay cost
  • 57. 57 Compound-dependent tuning of a TSQ mass spectrometer Ion source parameters (voltages, gas flows) are dependent on chemistry and sample delivery rate.
  • 58. 58 Compound-dependent tuning of a TSQ mass spectrometer Ion funnel: RF tuning trades off several effects; DC offset used for declustering or fragmentation.
  • 59. 59 Compound-dependent tuning of a TSQ mass spectrometer Ion funnel: RF tuning trades off several effects; DC offset used for declustering or fragmentation.
  • 60. 60 Compound-dependent tuning of a TSQ mass spectrometer Fragment ions to select in Q3 for are often unknown.
  • 61. 61 Compound-dependent tuning of a TSQ mass spectrometer Collision energy optimizing any CID transition must be determined empirically.
  • 62. 62 • We want to be able to insert or remove optimizations at (customer) will. • Future compatibility is also desired. • Optimizations should use previous results in a clean way. • Design: • Precursor and product data structures: attributes name, mass, tunings, etc. • Precursor ion optimizations take a precursor as input and yield a precursor as output, with updated tunings or updated mass. • Product ion optimizations are similar • Optimizations are composed/put into sequence by function composition. • Optimization internals may be procedural code, but no persistent side effects or communication at a distance through instrument state allowed. (Either clean up state changes or be indifferent.) Optimizations as pure and composable functions
  • 63. 63 Assay optimization: Handling state using decorators • Decorator sets system according to previous tunings; optimizer functions concerned only with their proper optimization operation: local function PrecursorStateSetter(precursor) local doWait=false if Sys.Polarity()~=precursor.polarity then DS:SetSystemPolarity(precursor.polarity) doWait=true end --Set ion source devices for _,dev in pairs(Sys.IonSourceDevices()) do if precursor.tunings[dev.name] and (precursor.tunings[dev.name]~=dev.value) then CF2:SetAndUpdate(precursor.tunings[dev.name],dev) doWait=true end end --Now set everything else: (…) if doWait then SleepSec(SOURCE_WAIT) end return end function CO.StateManipulationDecoratorPrecursor(f) return function (precursor) if precursor then PrecursorStateSetter(precursor) end return f(precursor) end end
  • 64. 64 Assay optimization: Handling state using decorators Sample delivery request and detection by sample delivery decorator: function CO.GetSampleDecorator(f,timeout) return function (ion) local monitoredMZ= ion.precursor and ion.precursor.mz or ion.mz --This construction makes this precursor or product compatible local monitoredPolarity=ion.precursor and ion.precursor.polarity or ion.polarity if firstInjectionReceived then --Don't do this for first injection of a series. Signal(DS.SIG_REQUEST_SAMPLE) if not MethodControl.WaitCC() error(CO.exceptions.ABORTED_WAITING) end end local result=Sys.GetSample({mass parameters: omitted details},timeout,false) if result==0 then Signal(DS.SIG_SAMPLE_NOT_RECEIVED) (…) error(CO.exceptions.SAMPLE_NOT_RECEIVED) elseif result==1 then Signal(DS.SIG_RECEIVED_SAMPLE) (…) end SleepSec(0.5) return f(ion) end end
  • 65. 65 Composite spectrum generated by fun.Reduce(function (a,b) return CO.MergeSpectra(a,b,false) end, fun.Map(SingleRampScan,fun.Values(CEs))) where MergeSpectra is a pointwise max intensity selector function CO.MergeSpectra(a,b) local retstructure=a (…) for index=1,#a.y do retstructure.y[index]=math.max(a.y[index],b.y[index]) end return retstructure end Assay optimization: Use of Reduce() in product search
  • 66. 66 Optimize precursor list: local runSucceeded, result= pcall(function () return ProductOptimization( PrecursorOptimization( fun.Map(SourceOptimization, GetInjection(experiment.precursors)))) end) Optimize product list: ProductOptimization= function (precursor) if precursor then precursor.products= fun.IteratorToArray( fun.Map(function (x) return GraphProductPoint(x) end, fun.TakeFirstN(experiment.nProducts, CheckProductExistencesAndCountFailures( fun.Filter(ProductMassFilterCondition, fun.Map(OptimizeProduct, GetProducts(precursor).ProductsIterator)))))) (…) end return precursor end OptimizeProduct is a composition of optimizer functions (tuning mass, collision energy). A binary compose operation is reduced across a list to make it. Assay optimization: putting it all together

Editor's Notes

  1. This is the default title slide for Thermo Fisher Scientific Title photo options specific to end-markets will be available via commercial overview presentations due for release 2015-2016