PNRF Reader SDK User Manual
PNRF Reader SDK User Manual
English
HBM GmbH
Im Tiefen See 45
64293 Darmstadt
Germany
Tel: +49 6151 80 30
Fax: +49 6151 8039100
Email: [email protected]
www.hbm.com/highspeed
Copyright © 2009
All rights reserved. No part of the contents of this book may be reproduced or
transmitted in any form or by any means without the written permission of the publisher.
2 I2697-1.1 en
Perception PNRF Reader
I2697-1.1 en 3
4 I2697-1.1 en
Perception PNRF Reader
I2697-1.1 en 5
Perception PNRF Reader
6 I2697-1.1 en
Perception PNRF Reader
Introduction
Welcome to the PNRF Software Development Kit (PNRF SDK). This SDK
provides the software, documentation and examples required to use the PNRF
Application Programmers Interface (API). This document gives you an
introduction to the PNRF API. The interface allows you to write external
programs that can read data files generated by Perception software in the
Perception Native Recording File (PNRF) format.
In this document examples are written in Microsoft Visual Basic .NET, using
the Microsoft Visual Studio 2005 development environment.
Features
l Read waveform data from any Perception Native Recording File (*.pnrf) file
Installation
The PNRF SDK contains everything you need to install and use the PNRF API.
When you received the SDK on a CD you must install the SDK from the CD
onto your hard disk; you cannot use the API from the CD.
To install:
I2697-1.1 en 7
Perception PNRF Reader
The SDK includes sample projects for Microsoft Visual Basic .NET.
The documentation assumes you understand your HBM equipment and basic
acquisition terminology.
8 I2697-1.1 en
Perception PNRF Reader
I2697-1.1 en 9
Perception PNRF Reader
Step 1
Start the Visual Basic .NET development environment. In the New Project start-
up screen select a Visual Basic Project that creates a Windows Application.
We will name this project "Ex1 PNRF Open".
The project will be created and you are now presented a form.
Step 2
First we need to include the PNRF API function calls in this project.
To do this select the Add Reference... command in the Project menu. You
are now presented a list of registered references. Use the Browse... button to
open the Select Component dialog. In this dialog browse to the C:\Program
Files\Common Files\HBM\Components folder. In this folder select
percPNRFLoader.dll and percRecordingInterface.olb and click Open to
add these files to the list of References. Select OK.
10 I2697-1.1 en
Perception PNRF Reader
Step 3
Select Code in the View menu. Now you can enter the actual programming
code. Your view should look like this:
Enter the following code below the line that starts with Inherits:
Dim FromDisk As
RecordingLoaders.PNRFLoader ' Required
Dim MyData As
RecordingInterface.IRecording ' Required
Dim WithFileName As String ' Optionally at this point
Dim CanLoad As Integer ' Optionally at this point
Step 4
We will now enter the code required for the actual program. Select in the
(Form1 Events) section the Load event. Or select the form designer and
double-click on the form. Your View will now look like this:
I2697-1.1 en 11
Perception PNRF Reader
Below the line that starts with Private Sub enter the following code:
MyData = FromDisk.LoadRecording(WithFileName)
However, to make sure that the loader can read the selected file we will re-
arrange and add the following code. This also includes output.
CanLoad = FromDisk.CanLoadRecording(WithFileName)
If (CanLoad < 100) Then
Style = vbOKOnly + vbExclamation
Text = "This file cannot be loaded."
Result = MsgBox(Text, Style, "Load Recording")
Output.Text = "no data"
Else
MyData = FromDisk.LoadRecording(WithFileName)
Output.Text = MyData.Title
End If
12 I2697-1.1 en
Perception PNRF Reader
Make sure you have included a label with name Output on your form window.
Step 5
To test your first program (!) select function key F5 to run the program. When
all is well the program should run without error messages and the title of the
recording should be displayed on your form.
The complete code of this program could look like this (without error trapping):
I2697-1.1 en 13
Perception PNRF Reader
Within your program you can set breakpoints for debugging purposes: a
position in a program at which execution pauses and control returns to you.
When execution pauses you can investigate properties from objects through
the Watch Window. This is a helpful tool when developing software with the
PNRF API.
You can set a watch and have a look at the various properties as well as the
current values of the properties.
14 I2697-1.1 en
Perception PNRF Reader
Here you can see the various basic properties of a PNRF Recording File.
I2697-1.1 en 15
Perception PNRF Reader
In general data (or waveforms) of multiple sources is stored within a single file.
All HBM Genesis HighSpeed equipment/software uses the concept of a
recorder. A recorder can have one or more channels that acquire data. All
channels within a single recorder have the same timebase settings: sample
rate, recording length and trigger parameters. As an extension to this concept,
groups are used to combine various channels into a logical configuration. This
does not alter the arrangement of the channels within the recorders.
16 I2697-1.1 en
Perception PNRF Reader
Create a dialog
In the example we will search and display the names of the recorders and the
channels in the file as well as the type of channels. A "next" command button
will be used to step through the various items.
I2697-1.1 en 17
Perception PNRF Reader
Proceed as we have done in the previous chapter to open the file. If the file
cannot be opened set:
MaxRecorders = 0
MaxChannels = 0
NOFRecordersCnt.Text = MaxRecorders
NOFChannelsCnt.Text = MaxChannels
When the file can be opened, load the file and retrieve the number of recorders
and the number of channels and display this information:
MaxRecorders = MyData.Recorders.Count
MaxChannels = MyData.Channels.Count
NOFRecordersCnt.Text = MaxRecorders
NOFChannelsCnt.Text = MaxChannels
If you want your code to be bullet proof, add a test to verify if MaxChannels
> 0. In rare circumstances files can be created without data. This is noted by
Channels.Count = 0.
18 I2697-1.1 en
Perception PNRF Reader
CurrentRecorder = 1
CurrentChannel = 1
If ((MaxRecorders = 1) And (MaxChannels = 1)) Then
NxtButton.Enabled = False
Else
NxtButton.Enabled = True
End If
RecName.Text = MyData.Recorders(1).Name
ChName.Text = MyData.Recorders(1).Channels(1).Name
If (MyData.Recorders(1).Channels(1).ChannelType =
RecordingInterface.DataChannelType.DataChannelType
_Analog)
Then
Type.Text = "Analog"
Else
Type.Text = "Digital"
End If
First we set the current recorder and channel to "1". When there is only one
recorder with one channel, the NxtButton is disabled.
Now we can fetch the recorder and channel name. The recorder has two
'names': Name and PhysicalName. The PhysicalName is the name given by
the system and typically reflects the physical position of the recorder within an
acquisition mainframe. The Name is set by a user and defaults to the
PhysicalName.
Finally the type of the channel is determined. Currently this can be either
analog or digital.
MaxChannelsInCurrentRecorder =
MyData.Recorders(CurrentRecorder).
Channels.Count
CurrentChannel = CurrentChannel + 1
If (CurrentChannel > MaxChannelsInCurrentRecorder) Then
CurrentChannel = 1
CurrentRecorder = CurrentRecorder + 1
If (CurrentRecorder > MaxRecorders) Then
CurrentRecorder = 1
End If
End If
I2697-1.1 en 19
Perception PNRF Reader
RecName.Text = MyData.Recorders(CurrentRecorder).Name
ChName.Text = MyData.Recorders(CurrentRecorder).
Channels(CurrentChannel).Name
If (MyData.Recorders(CurrentRecorder).Channels
(CurrentChannel).
ChannelType = RecordingInterface.DataChannelType.
DataChannelType_Analog) Then
Type.Text = "Analog"
Else
Type.Text = "Digital"
End If
The second part of this routine deals with the display of the results of the
selected recorder and channel as we have seen in the initialization section.
The first part of the routine is used to step through the recorders and channels.
When all is OK you can run the program and the final result should look like
this:
20 I2697-1.1 en
Perception PNRF Reader
There are many ways to retrieve data from a PNRF file. In this chapter we will
concentrate on one type only: the retrieval of raw data (1:1) in floating point
format. Other types will be mentioned briefly when applicable.
I2697-1.1 en 21
Perception PNRF Reader
22 I2697-1.1 en
Perception PNRF Reader
So far we have used fully qualified names for our coding. Fully qualified names
are object references that are prefixed with the name of the namespace where
the object is defined. This happens when we create a reference to the PNRF
classes (by choosing Add Reference from the Project menu) and then use the
fully qualified name for the object in our code. E.g.:
RecordingInterface.DataChannelType.DataChannelType_Analog
Fully qualified names prevent naming conflicts because the compiler can
always determine which object is being used. However, the names themselves
can get long and cumbersome. To get around this, we use namespaces that
we define in the project properties.
I2697-1.1 en 23
Perception PNRF Reader
24 I2697-1.1 en
Perception PNRF Reader
Declarations
Before we start: make sure you have included the RecordingLoaders in your
list of Project > References as well as the RecordingInterface (see chapter
“Getting it all to work” on page 10 for details). Also import both namespaces
as decribed earlier.
Note Since we are using imported namespaces, the complete prefixes can be
ommitted. We now have direct access to the interfaces.
Initialization
The first part of the program is globally the same as in previous examples:
create a loader, and verify if the file can be loaded. Here also note the absence
of the prefix.
MyData = FromDisk.LoadRecording(WithFileName)
I2697-1.1 en 25
Perception PNRF Reader
Load data
Now the file is open and we can have a look of what is inside. We already have
seen how to select recorders and channels in Chapter 3. For the sake of
simplicity we will fetch data only from a fixed recorder/channel in the next
example.
MySource = MyData.Recorders(1).Channels(1).DataSource
(DataSourceSelect.DataSourceSelect_Mixed)
Note When using sweeps, retrieving data between sweeps will yield empty results.
Since we now have an interface to a data source, we can try to get some data
out of it:
This will retrieve data starting at t=0 seconds through t=100 seconds and place
it in the intermediate Result object we have defined earlier.
26 I2697-1.1 en
Perception PNRF Reader
Segments = Result
Label1.Text = Segments.Count
This will copy the data from Result into our Segments interface and display
the segment count. The complete code after the between the Else and End
If statement will look like this:
Else
' here goes the code if we can load
MyData = FromDisk.LoadRecording(WithFileName)
MySource = MyData.Recorders(1).Channels(1).DataSource
(DataSourceSelect.DataSourceSelect_Mixed)
MySource.Data(0, 100, Result)
Segments = Result
Label1.Text = Segments.Count
End If
Note Segments.Count can be 0 (zero) even if there is data in the file. When the
actual data starts at a time > 0 and you request data before that point, no
segments and no data will be available.
Inside a segment
Now that we have segments of data we would like to see what is in there. A
variety of information is available. The most relevant ones at this point are:
As we will see later in this section, the data can be retrieved as floating point
data, integer data and original data:
l Floating point data: this data is in floating point format and scaled to the
user scaling. The user scaling can be found by using the YRange or
YFullRange methods.
l Integer data: raw ADC data. Needs to be scaled using the Y0 and YStep
properties.
l Original data: one of the above, depending on the type of input channel.
The units of both the X-axis and Y-axis can be found by using the
MySource.XUnit and MySource.YUnit respectively.
I2697-1.1 en 27
Perception PNRF Reader
Create a dialog
Using the form we already have, remove the label that we used so far and add a
ListView to the form. In this ListView we will use 3 columns, one for an index,
one for the time and one for the actual value of the data. Make sure you have
set the View property to Details.
Select the Colums property and click the More (...) button. This will call up the
ColumnHeader Collection Editor. Create the three columns as shown below.
Figure 4.3: PNRF Read Data and Column Header Collection Editor dialog
In the code we have come to the point that we have fetched a number of
segments with data in it. We will concentrate on one segment only.
Label1.Text = Segments.Count
28 I2697-1.1 en
Perception PNRF Reader
Samples = Segments(1).NumberOfSamples
Now we know the number of samples contained in the first segment. Note that
this can be up to 1 GigaSample! We will use this to fetch the actual data:
Segments(1).Waveform(DataSourceResultType.DataSourceResul
tType_
Double64, 1, Samples, 1, Result)
The first parameter of this method defines the data type result as we have
discussed earlier. Here we opt for the floating point data.
The second parameter is the first sample to fetch. Initially this should be "1".
Note The third parameter defines the total number of samples we want. This can
be less than the total number of samples available. You should limit this to a
reasonable value that fits easily in PC memory like 1 MegaSample (can be 4
MegaByte).
The next parameter sets the reduction factor. A reduction factor of "1"
retrieves all samples on a one-by-one basis. A reduction factor of 3 or higher
reduces the data by returning minmax pairs. Min-max pairs are also convenient
for display purposes.
The last parameter defines the result location. The data is returned in the
Result object. When you select a reduction factor of 2 or higher, the data is
returned in Result as min-max pairs. In Visual Basic this will now be a two-
dimensional array with Result(0, x) being the maximum values and Result(1, x)
being the corresponding minimum values.
I2697-1.1 en 29
Perception PNRF Reader
This will create sufficient ListView items. Also the column headers are modified
to reflect the current X- and Y-units.
When all is well and we run the program, the result could look like this:
Creating and filling the ListView entries can take a long time. Therefore make
sure that the number of samples is a few thousand or less.
30 I2697-1.1 en
Perception PNRF Reader
Start Perception and load the same file. Zoom in on a part of the channel data
that falls inside the loaded segment, until you can see the individual samples
(little squares). Drag a cursor to a location using 'sample snap': while dragging
the cursor hold down the Controlkey. The cursor will snap to samples. Press
the spacebar to call up the cursor window. Compare the results.
I2697-1.1 en 31
Perception PNRF Reader
How do we find out what data is available? I.e. what is the very first starting
point, very last end point and when did the recording start in the real world?
The very first relative start and very last relative end time can be found using
the properties MySource.Sweeps.StartTime and
MySource.Sweeps.EndTime. These values define the relative time of the
first sample and the relative time of the last sample after the start of recording,
no matter what is in between.
The relative start of the recording is always t=0. The corresponding real world
time can be found using the UTC time function:
in which:
This concludes the introduction to the PNRF reader. Refer to the various
appendices for more information on specific topics.
32 I2697-1.1 en
Perception PNRF Reader
ICount = MyData.DataValues.Count
DVType = MyData.DataValues(1).DataType
DVValue = MyData.DataValues("Comment").Value
I2697-1.1 en 33
Perception PNRF Reader
The examples in this section use the default MATLAB desktop and are given
as command line input. Version 7.1 (R14) of MATLAB is used to create these
examples. Version 7.1 and Version 7.3 (R2006b) were used to test the
examples.
34 I2697-1.1 en
Perception PNRF Reader
h = actxserver('progid')
This creates a COM server, and returns COM object, h, representing the
server's default interface. Progid is the programmatic identifier of the
component to instantiate in the server. For our application this becomes:
FromDisk =
COM.Perception_Loaders_PNRF
>> FromDisk.get
Description: 'Perception Recording File'
Extension: 'PNRF'
>>
To see the properties available through the FromDisk interface we use get. To
list the methods use invoke:
>> FromDisk.invoke
CanLoadRecording = int32 CanLoadRecording(handle,
string)
LoadRecording = handle LoadRecording(handle, string)
LoadRecordingFromInterface = handle
LoadRecordingFromInterface(handle, handle)
>>
MyData =
I2697-1.1 en 35
Perception PNRF Reader
Interface.Perception_Recording_Interface.IRecording
>>
>> MyData.Recorders.get
Count: 5
Recording: [1x1 Interface.Perception_Recording_
Interface.IRecording]
>> MyData.Recorders.invoke
Item = handle Item(handle, Variant)
>>
This means that there are 5 recorders and you can access each recorder by
using the Item method. Continue to investigate until you see the following:
>> MyData.Recorders.Item(1).Channels.Item(1).get
Name: 'Ch A1'
Recording: [1x1 Interface.Perception_Recording_
Interface.IRecording]
Recorder: [1x1 Interface.Perception_Recording_
Interface.IDataRecorder]
ChannelType: 'DataChannelType_Analog'
TimeShift: 0
>> MyData.Recorders.Item(1).Channels.Item(1).invoke
DataSource = handle DataSource(handle,
DataSourceSelect)
>>
36 I2697-1.1 en
Perception PNRF Reader
1 DataSourceSelect_Continuous
2 DataSourceSelect_Sweeps
3 DataSourceSelect_Mixed
>> ItfData =
MyData.Recorders.Item(1).Channels.Item(1).DataSource(1)
ItfData =
Interface.Perception_Recording_Interface.IDataSrc
>>
>> ItfData.get
Name: 'Ch A1'
XUnit: 's'
YUnit: 'Volt'
DataType: 'DataSourceDataType_AnalogWaveform'
TimeInfo: 'DataSourceTimeInfo_Implicit'
Status: 'DataSourceStatus_Static'
Value: NaN
Sweeps: [1x1 Interface.Perception_Recording_
Interface.IDataSweeps]
Properties: [1x1 Interface.Perception_Recording_
Interface.IProperties]
>> ItfData.invoke
Data = Variant(Pointer) Data(handle, double, double)
GetUTCTime = [int32, int32, double, bool]
GetUTCTime(handle)
GetValueAtTime = Variant GetValueAtTime(handle, double)
>>
I2697-1.1 en 37
Perception PNRF Reader
SegmentsOfData =
Interface.Perception_Recording_Interface.
IDataSegments
>> SegmentsOfData.get
Count: 1
>> SegmentsOfData.invoke
Item = handle Item(handle, int32)
Positions = [SafeArray Pointer(double), SafeArray
Pointer(double), SafeArray Pointer(int32)]
Positions(handle)
>>
>> SegmentsOfData.Item(1).get
StartTime: 63
EndTime: 78
SampleInterval: 2.0000e-004
NumberOfSamples: 75001
RelationToPrevio 'SegmentRelation_None'
us:
Y0: 0
YStep: 3.3333e-004
DisplayFrom: 10
DisplayTo: -10
38 I2697-1.1 en
Perception PNRF Reader
>> SegmentsOfData.Item(1).invoke
BestReductionFactor = int32 BestReductionFactor
(handle, int32)
DisplayRange = [double, double] DisplayRange(handle)
MathCalculations = [Variant(Pointer), Variant(Pointer),
Variant(Pointer), Variant(Pointer)]
MathCalculations(handle,
int32, int32, int32)
Waveform = Variant(Pointer) Waveform(handle,
DataSourceResultType, int32, int32, int32)
XFullRange = [double, double] XFullRange(handle)
XRange = [double, double, double, int32] XRange(handle)
YFullRange = [double, double, double, double, double,
double]
YFullRange(handle)
YRange = [double, double] YRange(handle)
>>
Use the Waveform method to get the data. This method requires the following:
I2697-1.1 en 39
Perception PNRF Reader
Example:
WaveformData =
Columns 1 through 9
...
>>
40 I2697-1.1 en
Perception PNRF Reader
year =
2006
day =
11
time =
49219
valid =
1
>>
>> ItfData.Sweeps.get
Count: 1
StartTime: 62.5500
EndTime: 78.9330
>>
>> ItfData.Sweeps.get
Count: 2
StartTime: 9.6000
EndTime: 11.9330
>> ItfData.Sweeps.Item(1).get
StartTime: 9.6000
EndTime: 10.0998
TriggerTime: 9.7000
TriggerSource: 'TriggerSource_Manual'
Finished: 1
>> ItfData.Sweeps.Item(2).get
StartTime: 11.4332
EndTime: 11.9330
TriggerTime: 11.5332
TriggerSource: 'TriggerSource_Manual'
Finished: 1
>>
I2697-1.1 en 41
Perception PNRF Reader
>> MyData.get
Title: 'pnrf_example_runup'
Recorders: [1x1 Interface.Perception_Recording_
Interface.IDataRecorders]
Channels: [1x1 Interface.Perception_Recording_
Interface.IDataChannels]
TimeTagRecorders: []
Sweeps: []
Filename: 'D:\temp\pnrf_example_runup.pnrf'
Comment: ''
Groups: [1x1 Interface.Perception_Recording_
Interface.IDataGroups]
PreferredDisplayLayout: [1x9001 char]
DataValues: [1x1 Interface.Perception_Recording_
Interface.IDataValues]
>> MyData.DataValues.get
Count: 3
>> MyData.DataValues.Item(1).get
Value: ''
DataType: 'DataSourceDataType_String'
Name: 'Comment'
Units: ''
>> MyData.DataValues.Item(2).get
Value: 'Administrator'
DataType: 'DataSourceDataType_String'
Name: 'UserName'
Units: ''
>> MyData.DataValues.Item(3).get
Value: 'LDS Test and Measurement'
DataType: 'DataSourceDataType_String'
Name: 'Company'
Units: ''
>> MyData.DataValues.Item('Comment').get
Value: ''
DataType: 'DataSourceDataType_String'
Name: 'Comment'
Units: ''
>>
42 I2697-1.1 en
Perception PNRF Reader
Note Legacy PNRF files do not contain DataValues. Therefore the array will be
empty in these files.
I2697-1.1 en 43
Perception PNRF Reader
44 I2697-1.1 en
Perception PNRF Reader
B Enumerations
B.1 Introduction
Various methods require a number as a means to select an option. these
numbers are defined. This appendix lists all the enumerations that are currently
in use.
typedef enum {
DataChannelType_Analog = 1,
DataChannelType_Event = 2
} DataChannelType;
typedef enum {
DataSourceDataType_Unknown = 0,
DataSourceDataType_Numerical = 1,
DataSourceDataType_String = 2,
DataSourceDataType_AnalogWaveform = 3,
DataSourceDataType_DigitalWaveform = 4,
DataSourceDataType_TimeMarks = 10
} DataSourceDataType;
typedef enum {
DataSourceResultType_Original = 0xffffffff,
DataSourceResultType_Int16 = 2,
DataSourceResultType_Double64 = 4
} DataSourceResultType;
typedef enum {
DataSourceStatus_Static = 0,
DataSourceStatus_Dynamic = 1
} DataSourceStatus;
I2697-1.1 en 45
Perception PNRF Reader
typedef enum {
DataSourceTimeInfo_Implicit = 0,
DataSourceTimeInfo_Explicit = 1,
DataSourceTimeInfo_External = 2
} DataSourceTimeInfo;
typedef enum {
SegmentRelation_None = 0,
SegmentRelation_Continuous = 1,
SegmentRelation_Overlapped = 2
} SegmentRelation;
typedef enum {
DataSrcInfoMaskItem_Name = 1,
DataSrcInfoMaskItem_XUnits = 2,
DataSrcInfoMaskItem_YUnits = 4,
DataSrcInfoMaskItem_UTCTime = 8
} DataSrcInfoMaskItem;
typedef enum {
TriggerSource_NoTrigger = 0,
TriggerSource_Unknown = 1,
TriggerSource_Bus = 2,
TriggerSource_Manual = 3,
TriggerSource_External = 4,
TriggerSource_Auto = 5,
TriggerSource_Display = 6,
TriggerSource_Channel = 7,
TriggerSource_MyChannel = 99,
TriggerSource_NoData = 0x80000000,
TriggerSource_Mask = 65535
} TriggerSourceInfo;
typedef enum {
TimeMarkType_Trigger = 1,
TimeMarkType_TriggerAnnotation = 2,
TimeMarkType_BookMark = 4,
TimeMarkType_Marker = 8,
TimeMarkType_VoiceMark = 16,
TimeMarkType_EventMark = 32
} TimeMarkType;
46 I2697-1.1 en
Perception PNRF Reader
typedef enum {
EventMark_RecordingStart = 1,
EventMark_RecordingEnd = 2
} EventMarkType;
I2697-1.1 en 47
Perception PNRF Reader
C Summary of Commands
C.1 Introdution
Each object within the PNRF Reader and Recording interface can have
properties and methods. This appendix lists the most relevant properties and
methods that are currently in use.
IRecording
Properties
Title Title of recording
Recorders All recorders
Channels All channels
Sweeps Sweeps collection
Filename Filename
Comment Comment
Groups Groups collection
PreferredDisplayLayout Proprietary XML stream
DataValues Data of Perception Info
sheet
Methods
GetUTCTime UTC time start of recording
DeleteOnRelease Delete file on release of
i'fces
IRecording.Recorders
Properties
Count Number of recorders
Methods
Item Retrieve interface
IRecording.Recorders.Item(i) = IDataRecorder
Properties
Name Name of recorder
PhysicalName Physical name of recorder
Channels All channels in recorder
48 I2697-1.1 en
Perception PNRF Reader
IRecording.Recorders.Item(i) = IDataRecorder
Triggers Collection of trigger
infos
XUnits X-Units (timebase)
IDataRecorder.Channels
Properties
Count Number of channels
Methods
Item Retrieve interface
IDataRecorder.Channel.Item(i) = IDataChannel
Properties
Name Name of channel
ChannelType Type of channel
Methods
DataSource Retrieve pointer to data
source
IDataSrc
Properties
Name Name of data source
XUnit Timebase units
YUnit Y-axis units
DataType Type of data, e.g. analog
TimeInfo Timebase source
Sweeps Sweeps information
Properties Collection of properties
Methods
Data Fetch data segments
IDataSrc.Sweeps
Properties
Count Number of sweeps
StartTime Start time of total
recording
EndTime End time of total recording
Methods
Item Retrieve interface to
sweeps
I2697-1.1 en 49
Perception PNRF Reader
IDataSrc.Sweeps.Item(i) = IDataSweep
Properties
StartTime Start time of this sweep
EndTime End time of this sweep
TriggerTime Time of trigger
TriggerSource Source of trigger
Finished Sweep has finished yes /
no
Methods
GetInfo Get trigger information
IDataSegments
Properties
Count Number of data segments
returnedby a call to the
Data method ofIDataSrc
Methods
Item Retrieve interface to
segment
IDataSegments.Item(i) = IDataSegment
Properties
StartTime Start time of this segment
EndTime End time of this segment
SampleInterval Time interval between
samples
NumberOfSamples Number of samples in
thissegment
Y0 Y0 value
YStep Input range / ADC # of
values
Methods
Waveform Returns the data
50 I2697-1.1 en
Perception PNRF Reader
Note The type of markers available depends on the instrument that created the
recording. Therefore some markers may not be available as type of markers.
I2697-1.1 en 51
Perception PNRF Reader
D.2 Triggers
Triggers and trigger annotations are easily accessed through the
Recording.Recorders interface as well as the DataSource.Sweeps
interface:
MyData = FromDisk.LoadRecording(WithFileName)
TriggerCount = MyData.Recorders(1).Triggers.Count
TriggerTime = MyData.Recorders(1).Triggers(1).Time
TriggerType = MyData.Recorders(1).Triggers(1).MarkType
MySource = MyData.Recorders(1).Channels(1).DataSource
(DataSourceSelect.DataSourceSelect_Mixed)
TriggerTime = MySource.Sweeps(1).TriggerTime
TriggerSource = MySource.Sweeps(1).TriggerSource
52 I2697-1.1 en
Perception PNRF Reader
D.3 Markers
To access the various markers you will need to use a different technique. As
mentioned earlier, any number of markers can be present. Therefore these
markers are grouped in a separate data stream.
Instead of fetching data from a channel, we will now fetch data from the
recorder, using the TimeMarks data stream:
MySource = MyData.Recorders(1).DataSource
(DataSourceSelect.DataSourceSelect_Timemarks)
MySource.Data(0, 63, Result)
MyMarkers = Result
TriggerCount = MyMarkers.Count
TriggerType = MyMarkers(1).MarkType
TriggerTime = MyMarkers(1).Time
In the above code the type of marker determines the end result. For events the
event type can be returned. For triggers the trigger source is available.
I2697-1.1 en 53
Perception PNRF Reader
Within the PNRF definition a recording can have the following types of data
storage by nature:
When you want to fetch data from a PNRF file you will need to consider this
data source select issue. The safest option is to go always for the mixed data
source.
When you retrieve the data, you will get initially a list of segments. Each
segment is a piece of data with its own X- and Y- information as well as begin
and end time. Data may be segmented due to timebase changes as well as
amplifier range changes. Also gaps create segements.
54 I2697-1.1 en
Perception PNRF Reader
Use either the continuous or mixed mode select for the data source.
Start and end of the complete recording can be found by using the properties
MySource.
Sweeps.StartTime and MySource.Sweeps.EndTime.
If you want to retrieve data between 6 and 8 seconds you will use something
like:
MySource.Data(6, 8, Result)
Segments = Result
Label1.Text = Segments.Count
At this point Segments.Count should be one (1), i.e. the data you requested
is contained within one segment. You can have a look at the properties of
Segments(1) to find out the details.
I2697-1.1 en 55
Perception PNRF Reader
E.3 Sweeps
Assume a recording with sweeps as shown in Figure E.2.
This is a single recording starting at t=2 that ends at t=12. When you want to
retrieve data select either the sweeps or mixed mode select for the data
source.
In the following example we will retrieve data from the same file between t= 4
and t=10. To fetch this data proceed as usual:
56 I2697-1.1 en
Perception PNRF Reader
Use Segments(1) and Segments(2) to find out the details of each segment.
I2697-1.1 en 57
Perception PNRF Reader
Here a situation is depicted in which both continuous data and sweeped data
are available. Now there are three basic options:
MySource = MyData.Recorders(1).Channels(1).DataSource
(DataSourceSelect.DataSourceSelect_Sweeps)
MySource.Data(3, 5, Result)
MySource = MyData.Recorders(1).Channels(1).DataSource
(DataSourceSelect.DataSourceSelect_Mixed)
MySource.Data(3, 5, Result)
58 I2697-1.1 en
Perception PNRF Reader
As result a single segment will be returned with the sweeped data in it. Using
the continuous data source would result in the situation as described at (C).
MySource = MyData.Recorders(1).Channels(1).DataSource
(DataSourceSelect.DataSourceSelect_Continuous)
MySource.Data(6, 8, Result)
MySource = MyData.Recorders(1).Channels(1).DataSource
(DataSourceSelect.DataSourceSelect_Mixed)
MySource.Data(6, 8, Result)
As result a single segment will be returned with the continuous data in it. Using
the sweeps data source would return nothing.
MySource = MyData.Recorders(1).Channels(1).DataSource
(DataSourceSelect.DataSourceSelect_Continuous)
MySource.Data(9, 11, Result)
As result a single segment will be returned with the continuous data in it. Using
the sweeps or mixed data source would return the sweeped data as described
at (A).
Usually you will not know exactly what kind of data is in the file. Therefore you
will retrieve a section with 'random' start and end point. Depending on the type
of data source select you can have various results.
I2697-1.1 en 59
Perception PNRF Reader
Figure E.5: Recording with continous data, sweeps and mixed mode
A Use sweeps: you will get two segments, one ranging from 4.5 to 5.5
seconds, the other one starting at 8.5 seconds and ending at 10.5
seconds.
B Select continuous. The result will be a single segment that comprises the
complete requested data.
C Select mixed mode: now you will get three segments. The first one ranges
from 4.5. to 5.5 seconds, containing (high speed) sweep data. The second
segment has (slow speed) continuous data, starting at 5.5 seconds* and
ending at 8.5 seconds. The last segment again has sweep data up to 10.5
seconds.
* Actually the time between the last sample of the segment and the first sample
of the next segment will be somewhere between
IDataSegment.SampleInterval of the segment and the
IDataSegment.SampleInterval of the next segment. Due to the nature of
HBM digitizing equipment however, the exact timing of these samples is
correct and they are synchronized.
60 I2697-1.1 en
Perception PNRF Reader
F Using C++
F.1 Introduction (Using C++)
C++ (pronounced "see plus plus") is a general-purpose, high-level
programming language with low-level facilities. It is a statically typed free-form
multi-paradigm language supporting procedural programming, data
abstraction, object-oriented programming, generic programming and RTTI.
Since the 1990s, C++ has been one of the most popular commercial
programming languages.
In this appendix we will give an example of how to use the PNRF API with C+
+. The code is also included "as-is" with the PNRF Reader SDK and developed
in the Microsoft Visual Studio development environment (2005 edition).
I2697-1.1 en 61
Perception PNRF Reader
F.2 Initialization
Initialize the program. Depending on your requirements include the various
libraries. Include the Loader and Recording interface by ID rather than by
actual name.
62 I2697-1.1 en
Perception PNRF Reader
F.3 Main
The main program uses CoInitialize to initialize the COM library on the current
thread. Applications must initialize the COM library before they can call COM
library functions.
Once done CoUninitialize closes the COM library on the current thread,
unloads all DLLs loaded by the thread, frees any other resources that the
thread maintains, and forces all RPC connections on the thread to close.
I2697-1.1 en 63
Perception PNRF Reader
void ProcessFile()
{
IRecordingLoaderPtr itfLoader;
itfLoader.CreateInstance(__uuidof (PNRFLoader));
// Enter the name of the pnrf recording here
IRecordingPtr itfRecording = itfLoader->LoadRecording
("d:\\Temp\\pnrf_example_runup.pnrf" );
// print recording name
_tprintf(TEXT("Recording title: %s\n"),
(wchar_t *)itfRecording->Title);
// print company name when data values are available
if (itfRecording->DataValues != NULL)
{
myCompany = itfRecording->DataValues->
Item["Company"]->GetValue();
_tprintf(TEXT("Company: %s\n"),
(wchar_t*)myCompany.bstrVal);
}
// connect to data source channel 1
IDataSrcPtr MySource = itfRecording->Channels->
Item[1]->DataSource[DataSourceSelect_Mixed];
// fetch YUnits
MySource->get_YUnit(&myUnits);
_tprintf(TEXT("Y Unit: %s\n", (wchar_t*)myUnits);
// fetch start and stop time
MySource->Sweeps->get_StartTime(&dStart);
MySource->Sweeps->get_EndTime(&dEnd);
_tprintf(TEXT(
"Start time: %lf s, End time: %lf s\n\n"),
dStart, dEnd);
cout <<
"Press any key to continue, or Q to quit\n\n";
cAnyKey = _getch();
if ((cAnyKey == 'Q') || (cAnyKey == 'q'))
return;
64 I2697-1.1 en
Perception PNRF Reader
I2697-1.1 en 65
Perception PNRF Reader
At this point we can loop through all available segments and display the data.
Before we actually display the data we display the number of data points and
give the option to continue or quit.
if (satmp->cDims > 1)
{
// It's a multi dimensional array
_tprintf(TEXT("Too many dimensions.\n"));
continue;
}
double *pData;
66 I2697-1.1 en
Perception PNRF Reader
SafeArrayAccessData(satmp,(void**)&pData);
double X0 = itfSegment->StartTime;
double DeltaX = itfSegment->SampleInterval;
double X, Y;
I2697-1.1 en 67
Perception PNRF Reader
G Using C#
G.1 Introduction (Using C#)
C# (pronounced see sharp) is an object-oriented programming language
developed by Microsoft as part of their .NET initiative, and later approved as
a standard by ECMA and ISO. C# has a procedural, object-oriented syntax
based on several other programming languages (most notably Delphi and
Java) with a particular emphasis on simplification.
It should be noted that all .NET programming languages share the same
runtime engine, and when compiled produced binaries that are seamlessly
compatible with other .NET programming languages, including cross language
inheritance, exception handling, and debugging.
In this appendix we will give an example of how to use the PNRF API with C#.
The code is also included "as-is" with the PNRF Reader SDK and developed
in the Microsoft Visual Studio development environment (2005 edition).
68 I2697-1.1 en
Perception PNRF Reader
G.2 Initialization
Start a new project and include the correct references. To do this select the
Add Reference... command in the Project menu. You are now presented a
list of registered references. Use the Browse... button to open the Select
Component dialog. In this dialog browse to the C:\Program Files\Common
Files\HBM\Components folder. In this folder select percPNRFLoader.dll
and percRecordingInterface.olb and click Open to add these files to the list
of References. Select OK. Now the RecordingLoaders and RecordingInterface
are added to your list of included references.
Depending on your installation you can also include the COM reference
Perception PNRF Loader when available. This will load the two references in
one go.
using System;
using System.Collections.Generic;
using System.Text;
using RecordingLoaders;
using RecordingInterface;
namespace Ex1_CSharp_PNRF_Load
{
classProgram
{
static void Main(string [] args)
{
object myCompany; // company name
string myUnits; // units
double dStart; // start time
double dEnd; // stop time
I2697-1.1 en 69
Perception PNRF Reader
// create a pnrfloader
PNRFLoader FromDisk = new PNRFLoader();
// enter the correct name of the pnrf file here
String WithFileName = "D:\\Temp\
\pnrf_example_dual.pnrf" ;
// load recording
IRecording myData =
FromDisk.LoadRecording(WithFileName);
// print recording name
Console.WriteLine(myData.Title);
if (myData.DataValues != null)
{
// only when data values are available
myCompany =
myData.DataValues["Company"].Value;
Console.WriteLine("Company: " + myCompany);
}
// connect to the first channel as data source
IDataSrc mySource =
myData.Channels[1].get_DataSource
(DataSourceSelect.DataSourceSelect_Mixed);
The result at this point could look like this (no data values present):
70 I2697-1.1 en
Perception PNRF Reader
At this point we can loop through all available segments and display the data.
Before we actually display the data we display the number of data points and
give the option to continue or skip the segment.
I2697-1.1 en 71
Perception PNRF Reader
if (varData == null)
{
Console.WriteLine("No valid data
found.");
return;
}
double X0 = mySegment.StartTime;
double DeltaX = mySegment.SampleInterval;
double X, Y;
72 I2697-1.1 en
Perception PNRF Reader
I2697-1.1 en 73
Perception PNRF Reader
H NRF Files
H.1 Introduction
The PNRF Reader SDK also supports reading Odyssey/Vision NRF files.
Reading an NRF file requires changing a single line of code in the various code
examples.
Visual Basic
FromDisk = New RecordingLoaders.NRFLoader
MATLAB
The Progid for the NRF loader is ‘Perception.Loaders.NRF’.
C#
// create a nrfloader
IRecordingLoader FromDisk = new NRFLoader() ;
C++
IRecordingLoaderPtr itfLoader;
itfLoader.CreateInstance(__uuidof (NRFLoader));
74 I2697-1.1 en
Perception PNRF Reader
I LRF Files
I.1 Introduction
The PNRF Reader SDK also supports reading Dimension LRF files. Reading
an LRF file requires one or two changes in the various code examples
depending on the programming tools in use.
Visual Basic
Add a reference to C:\Program Files\Common Files\HBM\Components
\LRFLoader.dll
MATLAB
The Progid for the NRF loader is ‘Perception.Loaders.LRF’.
C#
Add a reference to C:\Program Files\Common Files\HBM\Components
\LRFLoader.dll
// create a nrfloader
IRecordingLoader FromDisk = new CLRFRecordingLoader() ;
C++
To reference the LRF loader the following #import statement must be added.
#import"libid:8098371E-98AD-0069-BEF3-21B9A51D6B3E"
no_namespace
I2697-1.1 en 75
Perception PNRF Reader
IRecordingLoaderPtr itfLoader;
itfLoader.CreateInstance(__uuidof
(CLRFRecordingLoader));
76 I2697-1.1 en
Perception PNRF Reader
Index
A Interfacing with MATLAB
Getting started ................................................ 35
A word on segments ............................................ 22 Inspect the file contents .................................. 36
Introduction
B Inside the PNRF .............................................. 16
Introduction (Using C#) ........................................ 68
Before we start ..................................................... 23
Begin and end of recording ............................ 32, 41
L
E
M
Enumarations
Introduction ..................................................... 45 Markers ................................................................ 53
TimeMarks ....................................................... 53
MATLAB GUI ........................................................ 44
F MATLAB Plot ........................................................ 40
Microsoft Visual Basic .NET ................................... 7
Fetch data ............................................................ 37 Mixed data ............................................................ 58
Continuous data .............................................. 58
G Mixed mode .................................................... 60
Sweeps ............................................................ 58
General ................................................................... 7
Installation ......................................................... 7
N
Getting it all to Work
Introduction ..................................................... 10 NRF Files
Getting it all to work C# .................................................................... 74
Test ................................................................. 13 C++ ................................................................. 74
GUI example ......................................................... 44 Introduction ..................................................... 74
MATLAB .......................................................... 74
I Visual Basic ..................................................... 74
Imprint ......................................................................
P
Interfacing with MAT LAB
Introduction ..................................................... 34 PNRF API function ............................................... 10
I2697-1.1 en 77
Perception PNRF Reader
Triggers ................................................................ 52
Triggers and Markers
Introduction ..................................................... 51
Using C++
CoInitialize ....................................................... 63
CoUninitialize .................................................. 63
Initialization ...................................................... 62
Introduction ..................................................... 61
Main ................................................................. 63
PNRFLoad.exe ................................................ 65
Process the data ............................................. 64
ProcessFile ...................................................... 64
78 I2697-1.1 en
Head Office
HBM
Im Tiefen See 45
64293 Darmstadt
Germany
Tel: +49 6151 8030
Email: [email protected]
France
HBM France SAS
46 rue du Champoreux
BP76
91542 Mennecy Cedex
Tél:+33 (0)1 69 90 63 70
Fax: +33 (0) 1 69 90 63 80
Email: [email protected]
Germany
HBM Sales Office
Carl-Zeiss-Ring 11-13
85737 Ismaning
Tel: +49 89 92 33 33 0
Email: [email protected]
UK
HBM United Kingdom
1 Churchill Court, 58 Station Road
North Harrow, Middlesex, HA2 7SA
Tel: +44 (0) 208 515 6100
Email: [email protected]
USA
HBM, Inc.
19 Bartlett Street
Marlborough, MA 01752, USA
Tel : +1 (800) 578-4260
Email: [email protected]
PR China
HBM Sales Office
Room 2912, Jing Guang Centre
Beijing, China 100020
Tel: +86 10 6597 4006
Email: [email protected]