Skip to content

Commit b5468ff

Browse files
committed
Merge branch 'dev'
2 parents 532301f + 873c2e6 commit b5468ff

26 files changed

+1015
-378
lines changed

README.md

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -34,33 +34,41 @@ For educational purposes, it is possible to use a laser pointer and a photo-diod
3434

3535
# Contents of this project
3636

37-
* **scanAndAcquire_Minimal** - The least you need to scan the mirrors across a sample and obtain an image:
38-
1. Uni-directional scanning
39-
2. Displays image to screen only
40-
3. One channel only
41-
4. No correction for imaging artefacts
37+
* **scanAndAcquire_Minimal** - This tutorial function is the least you need to scan the mirrors across a sample and obtain an image:
38+
1. Uni-directional scanning.
39+
2. Displays image to screen only.
40+
3. One channel only.
41+
4. No correction for imaging artefacts.
4242
5. Scanning parameters are hard-coded into the function. User can change scanner amplitude, number of pixels in the image, and sample rate.
4343

44-
* **scanAndAcquire_Basic** - The same as scanAndAcquire_Minimal but adds:
45-
1. Averaging using multiple samples per pixel
46-
2. Correction of the X mirror (fast axis) turn-around artefact
44+
* **scanAndAcquire_Basic** - This tutorial function is the least you need to get good images and save them to disk.
45+
It provides the same features as scanAndAcquire_Minimal but adds:
46+
1. Averaging using multiple samples per pixel.
47+
2. Correction of the X mirror (fast axis) turn-around artefact.
48+
3. Saving to disk as a TIFF stack. A function to read back the data is provided.
4749

4850
* **scanAndAcquire_Polished** - The same as scanAndAcquire_Basic but adds the following features:
49-
1. All important parameters can be set via parameter/value pairs
50-
2. More error checks
51-
3. Acquisition of multiple channels
52-
4. Generation of scan patterns and image display are handled by external functions
53-
5. Adds an optional histogram overlay on top of the scan images
54-
6. Saving to disk with time-stamps in TIFF info
55-
7. Bidirectional scanning
56-
57-
* **scanAndAcquire_OO** - The same features as scanAndAcquire_Polished but in an object-oriented interface.
58-
59-
* **scannerGUI** - A simple GUI wrapper for scanAndAcquire_OO. Currently it only:
60-
1. Starts/stops scanning
61-
2. Switches back and forth between unidirectional and bidirectional modes.
62-
3. Allows update of the bidirectional phase delay
63-
4. Saving that can be toggled with a checkbox
51+
1. All important parameters can be set via parameter/value pairs.
52+
2. More error checks.
53+
3. Acquisition of multiple channels.
54+
4. Generation of scan patterns and image display are handled by external functions.
55+
5. Adds an optional histogram overlay on top of the scan images.
56+
6. Time-stamps added to the saved TIFF info.
57+
7. Bidirectional scanning.
58+
8. Improved buffering to allow for higher frame rates.
59+
60+
* **scanAndAcquire_OO** - The same features as scanAndAcquire_Polished but in an object-oriented interface.
61+
The purpose of this it to contract procedural with object-oriented code.
62+
63+
* **scannerGUI** - A simple GUI wrapper class for scanAndAcquire_OO.
64+
This showcases some of the advantages of using object-oriented techniques for data acquisition and GUI-building.
65+
The scannerGUI class is not supposed to be a complete GUI application.
66+
Its purpose is to demonstrate how easy it is to wrap an object with a GUI.
67+
Currently the scannerGUI provides the following features:
68+
1. Starts/stops scanning.
69+
2. Switches back and forth between unidirectional and bidirectional modes.
70+
3. Allows update of the bidirectional phase delay whilst scanning.
71+
4. Saving to disk.
6472

6573
* The **buildingBlocks** folder contains code snippets to help teach the individual concepts from the above without providing a solution to the whole problem.
6674

buildingBlocks/analogInput.m

Lines changed: 0 additions & 40 deletions
This file was deleted.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
function analogInput_Continuous
2+
% Example showing how to record data continuously through an analog input channel
3+
%
4+
% function out = analogInput_Continuous
5+
%
6+
% Purpose
7+
% Records data comntinuously and plots to screen.
8+
% Displays positive values only.
9+
%
10+
% Rob Campbell - Basel 2016
11+
12+
13+
%Create a session using NI hardware
14+
s=daq.createSession('ni');
15+
s.Rate=20E3;
16+
17+
%Add an analog input channel
18+
AI=s.addAnalogInputChannel('Dev1', 'ai2', 'Voltage');
19+
inputRange = 1;
20+
AI.Range = [-inputRange , inputRange]; %record over +/- 1 V
21+
22+
23+
% Number of samples to pull in at a time
24+
s.NumberOfScans = s.Rate*0.1;
25+
26+
27+
%Add a listener to get data back from this channel and plot it
28+
addlistener(s,'DataAvailable', @plotData);
29+
30+
%Trigger the listener after all data have been acquired
31+
s.NotifyWhenDataAvailableExceeds=s.NumberOfScans;
32+
33+
s.IsContinuous = true; %needed to provide continuous behavior
34+
35+
%start the acquisition and block until finished
36+
clf
37+
38+
s.startBackground
39+
40+
fprintf('Press ctrl-c to quit\n');
41+
while 1
42+
pause(0.1)
43+
end
44+
45+
46+
47+
48+
% - - - - - - - - - - - - - - - - - - - - -
49+
function plotData(~,event)
50+
%Nested function to plot data
51+
t=event.TimeStamps;
52+
x=event.Data;
53+
54+
plot(t,x)
55+
ylim([0,inputRange])
56+
grid
57+
end
58+
59+
end
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
function varargout = analogInput_SingleShot
2+
% Example showing how to record two seconds
3+
%
4+
% function data = analogInput_SingleShot
5+
%
6+
% Purpose
7+
% Records two seconds of data and plots it to screen.
8+
% Optionally returns as output argument.
9+
%
10+
% Outputs
11+
% data - [optional] Returns the data vector that was plotted to screen.
12+
%
13+
%
14+
% Rob Campbell - Basel 2016
15+
16+
17+
%Create a session using NI hardware
18+
s=daq.createSession('ni');
19+
s.Rate=20E3; %Set the sample rate
20+
21+
%Add an analog input channel
22+
AI=s.addAnalogInputChannel('Dev1', 'ai0', 'Voltage');
23+
AI.Range = [-1,1]; %record over +/- 1 V
24+
25+
%Pull in 2 seconds worth of samples
26+
s.NumberOfScans = s.Rate*2;
27+
28+
29+
%start the acquisition and block until finished
30+
fprintf('Acquiring data...');
31+
[data,t]=s.startForeground;
32+
fprintf('\n');
33+
34+
35+
%Plot
36+
plot(t,data)
37+
38+
39+
%Release the DAQ session
40+
s.release;
41+
42+
43+
if nargout>0
44+
varargout{1} = data;
45+
end
46+

buildingBlocks/analogOutput_Continuous.m

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
1-
function addAnalogOutput_Continuous
1+
function analogOutput_Continuous
22
% Play a continuous sine wave out of an analog output
33
%
4+
% function analogOutput_Continuous
5+
%
46
%
57
% Instructions
6-
% Simply call the function. Quit with ctrl-C.
8+
% Connect AO0 of NI device Dev1 to an oscilloscope and run this function.
9+
% Quit with ctrl-C.
710
%
811
%
9-
% Rob Campbell - Basel 2015
12+
% Rob Campbell - Basel 2016
1013

1114

1215

@@ -20,7 +23,7 @@
2023

2124

2225
%Build one cycle of a sine wave
23-
waveForm=sin(-pi : pi/1000 : pi);
26+
waveForm=sin(-pi : pi/1000 : pi)';
2427

2528

2629
%Set the sample rate to 2000 samples per second, so the waveform plays out in one second
@@ -38,7 +41,7 @@
3841

3942

4043
%queue the first cycle
41-
s.queueOutputData(dataToPlay);
44+
s.queueOutputData(waveForm);
4245

4346

4447
% START!

buildingBlocks/analogOutput_SingleShot.m

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
function analogOutput_SingleShot
22
% Play one cycle of a waveform out of an analog output
33
%
4+
% function analogOutput_SingleShot
45
%
6+
% Instructions
7+
% Connect AO0 of NI device Dev1 to an oscilloscope and run this function.
8+
%
59
%
6-
% Rob Campbell - Basel 2015
10+
%
11+
% Rob Campbell - Basel 2016
712

813

914
%Create a session using NI hardware
@@ -15,15 +20,15 @@
1520

1621

1722
%Build one cycle of a sine wave
18-
waveForm=sin(-pi : pi/1000 : pi);
23+
waveForm=sin(-pi : pi/1000 : pi)';
1924

2025

2126
%Set the sample rate to 2000 samples per second, so the waveform plays out in one second
2227
s.Rate = 2000;
2328

2429

2530
%Queue the data to the board
26-
s.queueOutputData(dataToPlay);
31+
s.queueOutputData(waveForm);
2732

2833

2934
%Play the waveform
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
function anonymousFunctionExample
2+
% Example - how to use anonymous functions in MATLAB
3+
%
4+
% function anonymousFunctionExample
5+
%
6+
% Purpose
7+
% Demo showing a few use-cases for anonymouse functions.
8+
%
9+
% For details see:
10+
% http://uk.mathworks.com/help/matlab/matlab_prog/anonymous-functions.html
11+
%
12+
%
13+
% Rob Campbell - Basel 2016
14+
15+
16+
17+
18+
% Create an anonymous function that makes a sine wave. It has one input argument
19+
% that determines the number of cucles in the sinwave
20+
sinWave = @(nCycles) ( sin(linspace(-nCycles*pi,nCycles*pi,100*nCycles)) );
21+
22+
clf
23+
n=3;
24+
plot(sinWave(n))
25+
title(sprintf('%d cycles of a sine wave',n))
26+
set(gca,'XTickLabel',[],'YTickLabel',[])
27+
grid
28+
29+
30+
31+
32+
%Use a function handle (not an anonymous function) to calculate the mean of each vector in a cell array
33+
r = {rand(1,30), randn(1,150)*100, rand(1,1000)};
34+
fprintf('\nThe contents of cell array "r" are:\n')
35+
disp(r)
36+
37+
38+
fprintf('Use cellfun and a function handle to calculate the of each each vector in "r":\n' );
39+
disp(cellfun(@mean,r))
40+
41+
42+
fprintf('Use cellfun and an anonymous function to calculate 1.96 SD of each each vector in "r":\n' );
43+
SD95 = @(x) (std(x)*1.96);
44+
disp(cellfun(SD95,r))
45+
46+

buildingBlocks/cleanUp.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
% Demo of how to run a sub-function when the caller function ends.
88
% The "cleanUp" function will run even if the caller crashes.
99
%
10-
% Rob Campbell - Basel 2015
10+
% Rob Campbell - Basel 2016
1111
%
1212
% see: http://blogs.mathworks.com/loren/2008/03/10/keeping-things-tidy/
1313
%

0 commit comments

Comments
 (0)