DPX_RSA500
Run DPX (Digital Phosphor) analysis on the RSA500. This block should also work with compatible Tektronix RSAXXX instruments.
Tested with RSA507a. Params: dll_file : File, default=C:/Tektronix/RSA_API/lib/x64/RSA_API.dll Where the RSA_API.dll file is located. center_freq : float, default=100e6 The center frequency, in Hz. ref_level : float, default=-30 The reference level (the maximum y axis value), in dBm. span : float, default=1e6 The width of the x axis, in Hz. bandwidth : float, default=20e3 Resolution bandwidth, in Hz. Returns: bitmap : Surface x: frequency
y: power
z: occurances dpx_ogram : Surface x: frequency
y: trace number
z: occurances
Python Code
from flojoy import flojoy, DataContainer, Surface, File
from typing import Optional, TypedDict
from flojoy.instruments.tektronix.RSA_API import * # noqa: F403
from ctypes import cdll, c_int, c_bool, c_double, c_int32, byref, create_string_buffer
import numpy as np
class DPXSplitOutput(TypedDict):
bitmap: Surface
dpx_ogram: Surface
@flojoy
def DPX_RSA500(
dll_file: File,
input: Optional[DataContainer] = None,
center_freq: float = 100e6,
ref_level: float = -30,
span: float = 1e6,
bandwidth: float = 20e3,
) -> DPXSplitOutput:
"""Run DPX (Digital Phosphor) analysis on the RSA500.
This block should also work with compatible Tektronix RSAXXX instruments.
Tested with RSA507a.
Parameters
----------
dll_file : File, default=C:/Tektronix/RSA_API/lib/x64/RSA_API.dll
Where the RSA_API.dll file is located.
center_freq : float, default=100e6
The center frequency, in Hz.
ref_level : float, default=-30
The reference level (the maximum y axis value), in dBm.
span : float, default=1e6
The width of the x axis, in Hz.
bandwidth : float, default=20e3
Resolution bandwidth, in Hz.
Returns
-------
bitmap: Surface
x: frequency
y: power
z: occurances
dpx_ogram: Surface
x: frequency
y: trace number
z: occurances
"""
# Connect to RSA
rsa = cdll.LoadLibrary(dll_file.unwrap())
numFound = c_int(0)
intArray = c_int * DEVSRCH_MAX_NUM_DEVICES # noqa: F405
deviceIDs = intArray()
deviceSerial = create_string_buffer(DEVSRCH_SERIAL_MAX_STRLEN) # noqa: F405
deviceType = create_string_buffer(DEVSRCH_TYPE_MAX_STRLEN) # noqa: F405
apiVersion = create_string_buffer(DEVINFO_MAX_STRLEN) # noqa: F405
rsa.DEVICE_GetAPIVersion(apiVersion)
err_check(rsa.DEVICE_Search(byref(numFound), deviceIDs, deviceSerial, deviceType)) # noqa: F405
# note: the API can only currently access one at a time
# Connects to first available
err_check(rsa.DEVICE_Connect(deviceIDs[0]))
rsa.CONFIG_Preset()
# Set up windows
yTop = ref_level
yBottom = yTop - 100
yUnit = VerticalUnitType.VerticalUnit_dBm # noqa: F405
dpxSet = DPX_SettingStruct() # noqa: F405
rsa.CONFIG_SetCenterFreq(c_double(center_freq))
rsa.CONFIG_SetReferenceLevel(c_double(ref_level))
rsa.DPX_SetEnable(c_bool(True))
rsa.DPX_SetParameters(
c_double(span),
c_double(bandwidth),
c_int(801),
c_int(1),
yUnit,
c_double(yTop),
c_double(yBottom),
c_bool(False),
c_double(1.0),
c_bool(False),
)
rsa.DPX_SetSogramParameters(
c_double(1e-3), c_double(1e-3), c_double(ref_level), c_double(ref_level - 100)
)
rsa.DPX_Configure(c_bool(True), c_bool(True))
rsa.DPX_SetSpectrumTraceType(c_int32(0), c_int(2))
rsa.DPX_SetSpectrumTraceType(c_int32(1), c_int(4))
rsa.DPX_SetSpectrumTraceType(c_int32(2), c_int(0))
rsa.DPX_GetSettings(byref(dpxSet))
dpxFreq = np.linspace(
(center_freq - span / 2), (center_freq + span / 2), dpxSet.bitmapWidth
)
dpxAmp = np.linspace(yBottom, yTop, dpxSet.bitmapHeight)
frameAvailable = c_bool(False)
ready = c_bool(False)
fb = DPX_FrameBuffer() # noqa: F405
# Acquire data
rsa.DEVICE_Run()
rsa.DPX_Reset()
while not frameAvailable.value:
rsa.DPX_IsFrameBufferAvailable(byref(frameAvailable))
while not ready.value:
rsa.DPX_WaitForDataReady(c_int(100), byref(ready))
rsa.DPX_GetFrameBuffer(byref(fb))
rsa.DPX_FinishFrameBuffer()
rsa.DEVICE_Stop()
dpxBitmap = np.array(fb.spectrumBitmap[: fb.spectrumBitmapSize])
dpxBitmap = dpxBitmap.reshape((fb.spectrumBitmapHeight, fb.spectrumBitmapWidth))
# Convert trace data from W to dBm
# http://www.rapidtables.com/convert/power/Watt_to_dBm.htm
# Note: fb.spectrumTraces is a pointer to a pointer, so we need to
# go through an additional dereferencing step
traces = []
for i in range(3):
traces.append(
10
* np.log10(1000 * np.array(fb.spectrumTraces[i][: fb.spectrumTraceLength]))
+ 30
)
dpxogram = np.array(fb.sogramBitmap[: fb.sogramBitmapSize])
dpxogram = dpxogram.reshape((fb.sogramBitmapHeight, fb.sogramBitmapWidth))
dpxogram = dpxogram[: fb.sogramBitmapNumValidLines, :]
plotFreq = np.linspace(
center_freq - span / 2.0, center_freq + span / 2.0, fb.sogramBitmapWidth
)
rsa.DEVICE_Disconnect()
return DPXSplitOutput(
bitmap=Surface(x=dpxFreq, y=dpxAmp, z=np.flip(dpxBitmap, axis=0)),
dpx_ogram=Surface(x=plotFreq, y=np.arange(dpxBitmap.shape[1]), z=dpxogram),
)
def err_check(rs):
if ReturnStatus(rs) != ReturnStatus.noError: # noqa: F405
raise RSAError(ReturnStatus(rs).name) # noqa: F405
Example
Having problems with this example app? Join our Discord community and we will help you out!
In this example, Flojoy was used to extract a DPX spectrum from a Tektronix RSA500.
First the necessary blocks were added:
DPX_RSA500
- 2x
SURFACE
Connect the blocks as shown an run the app. See source for further technical explaination.