Scope
Example config for a one-area DAQmx system using one NI-6259 card

This is the most simple and cheapest configuration.

The same card does analog output and analog input. We use the 6259 as a workhorse for this, many other cards probably also work.

Copy ScopeDefinesExamples.h (which is in the repository) to ScopeDefine.h by using Windows Explorer (not Visual Studio!). Git ignores ScopeDefines.h so that you can adapt this to your needs without messing up for other people. Now choose the following defines in ScopeDefines.h

  • #define SCOPE_NAREAS 1
  • #define SCOPE_USE_SIMPLEDAQMX_OUTPUTS
  • #define SCOPE_USE_DAQMX_INPUTS and xyz hardware as you want it e.g. #define SCOPE_USE_NOXYFPUSTAGE and #define SCOPE_USE_GALIL_XYZSTAGE. Then compile your scope.exe.

Check http://sine.ni.com/nips/cds/view/p/lang/en/nid/14129 for details of the 6259 card.

Now to the xml file (remember: you cann find all the parameters here in scope::parameters with detailed descriptions!):

<?xml version="1.0" encoding="utf-8"?>
<Date>2013-04-03</Date>
<Time>10-20-54</Time>
<Comment></Comment>
<StartInputsFirst>true</StartInputsFirst>
<CommonMasterTrigger>/PXI-6259_0/ao/StartTrigger</CommonMasterTrigger>

A fundamental parameters is StartInputsFirst, it determines if input tasks are started first (and then outputs) or vice versa. For a DAQmx system start inputs first and use an analog output task as mastertrigger for synchronizing all tasks (see scope::OutputsDAQmx) for more details.
The CommonMasterTrigger determines which signal all tasks wait for to start synchronously. Here we would start the inputs first, then the outputs with output of area 0 last. Since the StartTrigger of area 0 is the common master trigger, all tasks wait for it and start synchronously when area 0 output task is started. Since this configuration only has one area this does not really matter.

<MasterFOVSizeX_um>3000</MasterFOVSizeX_um>
<MasterFOVSizeY_um>3000</MasterFOVSizeY_um>

This is the maximum FOV you can reach with the current scanner configuration (see below). It is used for a little diagram showing the current FOV (with zoom and offset) with respect to the maximum FOV. In a multi-area system it also shows the FPU movement of the single areas FOVs. There the MasterFOVSize is limited only by the objective performance and the FPU stage travel range. For a one-area system just use BaseMicronPerPixel * 256 (see below).

<area0>
<Area>0</Area>
<IsSlaveArea>false</IsSlaveArea>
<Linerate_Hz>1</Linerate_Hz>
<Framerate_Hz>1</Framerate_Hz>
<Frametime_s>1</Frametime_s>
<ScanMode>Sawtooth</ScanMode>
<BaseMicronPerPixelX>3.1</BaseMicronPerPixelX>
<BaseMicronPerPixelY>3.1</BaseMicronPerPixelY>
<MicronPerPixelX>0.1</MicronPerPixelX>
<MicronPerPixelY>0.1</MicronPerPixelY>

This is area number 0 and it is a master area. For multiarea configurations these parameters become important.
Linerate_Hz, Framerate_Hz, ScanMode, and MicronPerPixelX/Y are filled with real values in the xml file that is saved together with acquired images. Here they are just placeholders.
However, important now is the BaseMicronPerPixel value, this is how many microns is one pixel at zoom 1 and 256x256 pixel resolution. Edit this values after you took some first calibration images.
Now it gets interesting...

<daq>
<inputs>
<Channels>2</Channels>
<Oversampling>true</Oversampling>

You want to acquire two channels and want to use oversampling, i.e. the acquisition runs at the maximum rate the NI-6259 card allows, but for every pixel several samples (pixeltime divided by device's minimum sample time) are averaged. Also the output runs at the lower pixel rate.

<Uint16Range>firsthalf</Uint16Range>

The NI-6259 card has an input range of -X Volt - +X Volt (see below). Your PMT signals only go in the negative direction. We are reading samples from the card as unsigned integers (0..65535). Negative signals are mapped to 0..32766 with 0 V beeing 0. Positive signals are mapped from 32767...65535 with 0V beeing 32767. To avoid display of the unused values choose 'firsthalf' here. Note, that still full 16 bit images are saved.

<ChannelsString>PXI-6259_0/ai0:1</ChannelsString>

These are the two input channels, adapt to your device name.

<Range_V>0.5</Range_V>

Choose the input range (changes digitizer settings on the 6259 card), here -0.5V..+0.5V. Adapt if your PMT/preamp output is different.

<DAQTimingMethod>ReferenceClock</DAQTimingMethod>
<ReferenceClockSource>PXI_Clk10</ReferenceClockSource>
<ReferenceClockRate_Hz>10000000</ReferenceClockRate_Hz>

Since the input and output tasks run with different rates (the input it oversampling at maximum sampling rate, the output runs at pixel rate) both tasks can not use the same clock. However, both tasks still need to be synchronized. NI recommends to use the PXI 10MHz backplane clock (from the PXI chassis) as a reference for both tasks. Check scope::InputsDAQmx for more information. Be careful: If you do not use the ReferenceClock timing method you still have to provide a valid ReferenceClockRate of e.g. the onboard clock, since this determines the possible sampling rates of your device (which Scope has to calculate). See DAQmx::PredictSampleRate and the references there for details.

<ExternalClockSource>/PXI-6259_0/PXI_Trig1</ExternalClockSource>

If we had choosen 'External' as timing method, e.g. for FPGA generated sample clock, this parameter is important. Here it is only a dummy.

<MaxRateAggregate_Hz>1000000</MaxRateAggregate_Hz>
<Sampling>NonSimultaneousSampling</Sampling>
</inputs>

These parameters are important to calculate the maximum sampling rate and the allowed pixel rates. 'MaxRateAggregate_Hz' is the maximum sampling rate when acquiring from both (!) channels, it is device specific. See scope::parameters::InputsDAQmx::MinimumPixeltime and scope::parameters::InputsDAQmx::CoercedPixeltime for details. The 6259 card does non-simultaneous sampling, by the way.

<outputs>
<ChannelsString>PXI-6259_0/ao0:3</ChannelsString>
<OutputRange_V>5</OutputRange_V>

The four output channels (for x-scanner, y-scanner, fast z axis, and Pockels cell). Possible output ranges for the NI-6259 are +-5V and +-10V, since we do not need to drive any output with >5V we choose 5 here for better resolution.

<DAQTimingMethod>ReferenceClock</DAQTimingMethod>
<MinimumPixelTime_us>0.8</MinimumPixelTime_us>
<ReferenceClockSource>PXI_Clk10</ReferenceClockSource>
<ReferenceClockRate_Hz>1e+007</ReferenceClockRate_Hz>
<ExternalClockSource>/PXI-6259_0/PXI_Trig1</ExternalClockSource>

Same story as for the inputs, make sure these values are exactly the same as in the input section to ensure proper synchronization of inputs and outputs. Check scope::OutputsDAQmx. The MinimumPixelTime_us is the minimal output sampling time the device supports for 4 output channels. For the 6259 it is 1.25 MSamples/second, corresponding to 0.8us.

<MinOutputScanner_V>-2</MinOutputScanner_V>
<MaxOutputScanner_V>2</MaxOutputScanner_V>
<MinOutputPockels_Fraction>0</MinOutputPockels_Fraction>
<MaxOutputPockels_Fraction>2</MaxOutputPockels_Fraction>

The 'Range_V' before was the output range setting for the digital to analog conversion. These ranges here set the minimum/maximum voltages we want to generate. Values here depend on your scanners/Pockels cell driver. The ranges and more details for the fast z axis are configured further down.

<ExportPixelClockTerminal>/PXI-6259_0/PFI12</ExportPixelClockTerminal>

The pixel clock is exported to an output terminal for your pleasure.

</outputs>
<ShutterLine>PXI-6259_0/port0/line0</ShutterLine>

The digital output line connected to the shutter. Shutter should be closed on low state and open on high.

<Pixeltime_us>6</Pixeltime_us>
<Scannerdelay_us>0</Scannerdelay_us>
<Averages>1</Averages>

The initial pixeltime, scannerdelay, and average setting on program start.

<RequestedFrames>1</RequestedFrames>
</daq>

Only a dummy now, filled for the xml acompanying saved images.

<framesawtooth>
<XResolution_Pixel>256</XResolution_Pixel>
<YResolution_Pixel>256</YResolution_Pixel>
<Zoom>1</Zoom>
<XOffset_Fraction>0</XOffset_Fraction>
<YOffset_Fraction>0</YOffset_Fraction>
<FastZ_um>0</FastZ_um>
<Pockels_Fraction>0</Pockels_Fraction>
<XRotation_Degree>0</XRotation_Degree>
<YRotation_Degree>0</YRotation_Degree>
<presets>
<preset0>
<Name>512x512</Name>
<Pixeltime_us>6</Pixeltime_us>
<Scannerdelay_us>-100</Scannerdelay_us>
<Averages>1</Averages>
<XResolution_Pixel>512</XResolution_Pixel>
<YResolution_Pixel>512</YResolution_Pixel>
<XCutoff_Fraction>0.1</XCutoff_Fraction>
<YCutoff_Fraction>0.1</YCutoff_Fraction>
<XRetrace_Fraction>0.2</XRetrace_Fraction>
<YRetrace_Fraction>0.05</YRetrace_Fraction>
</preset0>
</presets>
<XCutoff_Fraction>0.1</XCutoff_Fraction>
<YCutoff_Fraction>0.1</YCutoff_Fraction>
<XRetrace_Fraction>0.1</XRetrace_Fraction>
<YRetrace_Fraction>0.1</YRetrace_Fraction>
</framesawtooth>

Initial settings for sawtooth framescanning on program start. Important in xml files acompanying a saved image (Note: in 'area0-ScanMode' you can see which type of scan was used to acquire that image). Have a look at scope::parameters::ScannerVectorFrameBasic and scope::parameters::ScannerVectorFrameSaw for further information. Check also scope::PixelmapperFrameSaw to see how an image is assembled depending on these parameters. If have put in a preset as an example. If you save presets in Scope (and save the parameter file afterwards or use one that was saved with an image) more stuff is put in here. See scope::parameters::ScannerVectorFrameSaw::Preset.

<framebidirectional>
<XResolution_Pixel>256</XResolution_Pixel>
<YResolution_Pixel>256</YResolution_Pixel>
<Zoom>1</Zoom>
<XOffset_Fraction>0</XOffset_Fraction>
<YOffset_Fraction>0</YOffset_Fraction>
<FastZ_um>0</FastZ_um>
<Pockels_Fraction>0</Pockels_Fraction>
<XRotation_Degree>0</XRotation_Degree>
<YRotation_Degree>0</YRotation_Degree>
<presets />
<XTurning_Fraction>0.1</XTurning_Fraction>
<YTurning_Fraction>0.1</YTurning_Fraction>
</framebidirectional>

Initial settings for bidirectional framescanning on program start. This is how it looks without presets. Have a look at scope::parameters::ScannerVectorFrameBiDi for further information. Check also scope::PixelmapperFrameBiDi to see how an image is assembled depending on these parameters.

<frameplanehopper>
<XResolution>256</XResolution>
<YResolution>256</YResolution>
<Zoom>1</Zoom>
<XOffset_Fraction>0</XOffset_Fraction>
<YOffset_Fraction>0</YOffset_Fraction>
<FastZ_um>0</FastZ_um>
<Pockels_Fraction>0</Pockels_Fraction>
<XRotation_Degree>0</XRotation_Degree>
<YRotation_Degree>0</YRotation_Degree>
<presets />
</frameplanehopper>

Initial settings for plane hopper framescanning on program start. Have a look at scope::parameters::ScannerVectorFramePlaneHopper for further information. Note that the plane hopping is not fully implemented yet!

<fpuzstage>
<Position_um>0</Position_um>
<MinOutput_V>0</MinOutput_V>
<MaxOutput_V>4</MaxOutput_V>
<Voltage_V>0</Voltage_V>
<CalibrationFile>None</CalibrationFile>
</fpuzstage>

This is the configuration for the fast z axis, which is controlled by a voltage, e.g. en ETL (in a multiarea system every FPU/area would have one). This output is generated at the third channel specified at 'outputs-ChannelsString' above. Check scope::FastZControl for details on the calibration file etc.

<fpuxystage>
<XPosition_um>0</XPosition_um>
<YPosition_um>0</YPosition_um>
<PollInterval_ms>1000</PollInterval_ms>
<StepSizeForButtons_um>10</StepSizeForButtons_um>
</fpuxystage>
</area0>

This is the configuration for the xy-stage of the FPU of a multiarea system. Since we have here a single area system this is basically only a placeholder.

<storage>
<Autosave>true</Autosave>
<SaveLive>false</SaveLive>
<Basename>test</Basename>
<Folder>C:\ScopeData\</Folder>
<SaveParameters>true</SaveParameters>
<UseTIFFTags>true</UseTIFFTags>
<CompressTIFF>true</CompressTIFF>
</storage>

'Autosave' determines if stacks, timeseries, and single images are automatically saved. Note: If you are not autosaving you have no method of saving what was acquired! Set to false only for debugging.
If you set 'SaveLive' to true, also continuous/live scans are saved (like a timeseries). Also only interesting for debug purposes.
Files are saved into 'Folder' plus subfolder with current date. Filenames are composed as e.g. 'test_A0_Ch1_0002.tif', test is the 'Basename', 'A0' means area 0, 'Ch1' means channel 1, and '0002' is a sequential number (for every saved image). 'SaveParameters' determines if an xml file (basically the same as the one I am describing here, filled with all the parameters with which the image was acquire) is saved together with each image. 'true' is highly recommended. With 'UseTIFFTags' Scope writes the image scaling as TIFF tags in the image, in a format that ImageJ recognises. I.e. inside ImageJ the correct scaling (given you have set BaseMicronPerPixel above) is automatically displayed. Scope uses 'exiftool.exe', which has to be present in the 'scope/tools' folder to write TIFF flags.
If you want to write compressed tiffs (using the ZIP algorithm) set CompressTIFF to true. This setting has almost no performance overhead, use it to save space.
See scope::StorageController for details.

<stack>
<startat>
<ZPosition_um>0</ZPosition_um>
<Pockels_Fraction>0</Pockels_Fraction>
</startat>
<stopat>
<ZPosition_um>0</ZPosition_um>
<Pockels_Fraction>0</Pockels_Fraction>
</stopat>
<Spacing_um>1</Spacing_um>
<ZDeviceType>ZStage</ZDeviceType>
<OverallTime_s>1</OverallTime_s>
</stack>

This is filled with useful information in the xml accompanying a saved stack.
See scope::ScopeController::ScopeControllerImpl::RunStack for details.

<timeseries>
<Frames>1</Frames>
<Totaltime_s>2.35011</Totaltime_s>
<Triggered>false</Triggered>
<AllTriggered>false</AllTriggered>
<Triggerchannel>/PXI-6259_0/PFI0</Triggerchannel>
<Repeats>1</Repeats>
<BetweenRepeats_s>2.54986</BetweenRepeats_s>
<OverallTime_s>2.35011</OverallTime_s>
</timeseries>

This is filled with useful information in the xml accompanying a saved timeseries. The only parameters you have to fill in is the 'Triggerchannel' you want to use for external triggering. The others parameters are editable/calculated inside Scope.
See scope::ScopeController::ScopeControllerImpl::RunTimeseries for details.

<stage>
<XPosition_um>0</XPosition_um>
<YPosition_um>0</YPosition_um>
<ZPosition_um>0</ZPosition_um>
<PollInterval_ms>1000</PollInterval_ms>
<RS232Connection>COM7 19200</RS232Connection>
<XEncoderCountsPerMicrometer>2</XEncoderCountsPerMicrometer>
<YEncoderCountsPerMicrometer>2</YEncoderCountsPerMicrometer>
<ZEncoderCountsPerMicrometer>60</ZEncoderCountsPerMicrometer>
</stage>

Parameters for the Galil stage, this looks slightly different for another stage type, e.g. a Sutter stage.

<stimulation>
<Channel>PXI-6259_0/port1/line0</Channel>
<Timingsource>/PXI-6259_0/ao/SampleClock</Timingsource>

Choose a digital output line here. Attention, these lines provide only very little current, depending on your stimulation hardware this may not be enough. Ask the electronics specialist of your trust for help.
Using the sample clock of the analog output task on the same card ensures synchrony between scanning and stimulation. The stimulation task runs thus at the pixel speed.

<Duration_s>1</Duration_s>
<Enable>false</Enable>
<OffTime_s>0.5</OffTime_s>
<Onset_s>0</Onset_s>
<OnTime_s>0.5</OnTime_s>
</stimulation>

This is filled with information from inside Scope.

<frames />

If you click on "Tools->Save window positions" in Scope the current positionts of all its windows are saved. If you then choose "File->Save parameters..." these window positions are saved in here in the parameters xml file.

That's it!