diff --git a/blocks/DATA/VISUALIZATION/PLOTLY/HEATMAP/HEATMAP.py b/blocks/DATA/VISUALIZATION/PLOTLY/HEATMAP/HEATMAP.py
index b8f22cc9..e7a0b233 100644
--- a/blocks/DATA/VISUALIZATION/PLOTLY/HEATMAP/HEATMAP.py
+++ b/blocks/DATA/VISUALIZATION/PLOTLY/HEATMAP/HEATMAP.py
@@ -7,6 +7,7 @@
DataFrame,
Vector,
OrderedTriple,
+ Surface,
)
import plotly.graph_objects as go
import plotly.express as px
@@ -18,7 +19,13 @@
@flojoy
def HEATMAP(
- default: OrderedPair | Matrix | Grayscale | DataFrame | Vector | OrderedTriple,
+ default: OrderedPair
+ | Matrix
+ | Grayscale
+ | DataFrame
+ | Vector
+ | OrderedTriple
+ | Surface,
show_text: bool = False,
histogram: bool = False,
) -> Plotly:
@@ -26,7 +33,7 @@ def HEATMAP(
Inputs
------
- default : OrderedPair|OrderedTriple|DataFrame|Vector|Matrix|Grayscale
+ default : OrderedPair|OrderedTriple|DataFrame|Vector|Matrix|Grayscale|Surface
the DataContainer to be visualized
Parameters
@@ -40,8 +47,8 @@ def HEATMAP(
-------
Plotly
the DataContainer containing the Plotly heatmap visualization
-
"""
+
layout = plot_layout(title="HEATMAP")
if histogram:
layout.sliders = [
@@ -189,7 +196,29 @@ def HEATMAP(
case DataFrame():
df = default.m
fig = px.imshow(df, text_auto=show_text)
-
+ case Surface():
+ x = np.unique(default.x)
+ y = np.unique(default.y)
+ z = default.z
+ fig.add_trace(
+ go.Heatmap(
+ z=z,
+ x=x,
+ y=y,
+ text=z if show_text else None,
+ texttemplate=text_template,
+ colorscale="Electric",
+ ),
+ row=None if not histogram else 1,
+ col=None if not histogram else 1,
+ )
+ if histogram:
+ histogram = np.histogram(z, bins="auto")
+ x_values = histogram[1][:-1] + 0.05 # Center bars on bin edges
+ histogram_trace = go.Bar(
+ x=x_values, y=histogram[0], orientation="h", showlegend=False
+ )
+ fig.add_trace(histogram_trace, row=1, col=2)
if histogram:
layout.xaxis2 = dict(
tickmode="array",
diff --git a/blocks/DATA/VISUALIZATION/PLOTLY/HEATMAP/block_data.json b/blocks/DATA/VISUALIZATION/PLOTLY/HEATMAP/block_data.json
index 50c13b19..680d90cc 100644
--- a/blocks/DATA/VISUALIZATION/PLOTLY/HEATMAP/block_data.json
+++ b/blocks/DATA/VISUALIZATION/PLOTLY/HEATMAP/block_data.json
@@ -1,6 +1,6 @@
{
"docstring": {
- "long_description": "Inputs\n------\ndefault : OrderedPair|OrderedTriple|DataFrame|Vector|Matrix|Grayscale\n the DataContainer to be visualized",
+ "long_description": "Inputs\n------\ndefault : OrderedPair|OrderedTriple|DataFrame|Vector|Matrix|Grayscale|Surface\n the DataContainer to be visualized",
"short_description": "Create a Plotly Heatmap visualization for a given input DataContainer.",
"parameters": [
{
diff --git a/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/BLOCK_IQ_RSA500/BLOCK_IQ_RSA500.py b/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/BLOCK_IQ_RSA500/BLOCK_IQ_RSA500.py
new file mode 100644
index 00000000..86cf7a06
--- /dev/null
+++ b/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/BLOCK_IQ_RSA500/BLOCK_IQ_RSA500.py
@@ -0,0 +1,118 @@
+from flojoy import flojoy, DataContainer, OrderedPair
+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_float, byref
+from os import path
+import numpy as np
+
+
+class IQSplitOutput(TypedDict):
+ I_real: OrderedPair
+ Q_imag: OrderedPair
+
+
+@flojoy
+def BLOCK_IQ_RSA500(
+ input: Optional[DataContainer] = None,
+ center_freq: float = 100e6,
+ ref_level: float = -30,
+ record_length: float = 1e3,
+ bandwidth: float = 5e5,
+) -> IQSplitOutput:
+ """Extract Block IQ measurement from a Tektronix RSA.
+
+ This block should also work with compatible Tektronix RSAXXX instruments.
+
+ Tested with RSA507a.
+
+ Parameters
+ ----------
+ 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.
+ record_length : float, default=1e3
+ The length to record (length of x axis), in ms.
+ bandwidth : float, default=5e5
+ Resolution bandwidth, in Hz.
+
+ Returns
+ -------
+ I_real: OrderedPair
+ x: time
+ y: power
+ Q_imag: OrderedPair
+ x: time
+ y: power
+ """
+
+ # Connect to RSA
+ defau = "C:/Tektronix/RSA_API/lib/x64/RSA_API.dll"
+ moved = "C:/Program Files/Tek/RSA_API/lib/x64/RSA_API.dll"
+ if path.isfile(defau):
+ rsa = cdll.LoadLibrary(defau)
+ elif path.isfile(moved):
+ rsa = cdll.LoadLibrary(moved)
+ else:
+ raise FileNotFoundError(
+ "Cannot find RSA_API.dll. Download from: https://www.tek.com/en/products/spectrum-analyzers/rsa500"
+ )
+
+ 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))
+
+ # 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()
+
+ # Configure spectrum
+ cf = center_freq
+ refLevel = ref_level
+ iq_bw = bandwidth
+ record_length
+ record_length = int(record_length)
+ rsa.CONFIG_SetCenterFreq(c_double(cf))
+ rsa.CONFIG_SetReferenceLevel(c_double(refLevel))
+ rsa.IQBLK_SetIQBandwidth(c_double(iq_bw))
+ rsa.IQBLK_SetIQRecordLength(c_int(record_length))
+
+ # Create array of time data for plotting IQ vs time
+ iqSampleRate = c_double(0)
+ rsa.IQBLK_GetIQSampleRate(byref(iqSampleRate))
+ time = np.linspace(0, record_length / iqSampleRate.value, record_length)
+
+ # Acquire data
+ record_length = int(record_length)
+ ready = c_bool(False)
+ iqArray = c_float * record_length
+ iData = iqArray()
+ qData = iqArray()
+ outLength = 0
+ rsa.DEVICE_Run()
+ rsa.IQBLK_AcquireIQData()
+ while not ready.value:
+ rsa.IQBLK_WaitForIQDataReady(c_int(100), byref(ready))
+ rsa.IQBLK_GetIQDataDeinterleaved(
+ byref(iData), byref(qData), byref(c_int(outLength)), c_int(record_length)
+ )
+ rsa.DEVICE_Stop()
+ rsa.DEVICE_Disconnect()
+
+ return IQSplitOutput(
+ I_real=OrderedPair(x=time, y=np.array(iData)),
+ Q_imag=OrderedPair(x=time, y=np.array(qData)),
+ )
+
+
+def err_check(rs):
+ if ReturnStatus(rs) != ReturnStatus.noError: # noqa: F405
+ raise RSAError(ReturnStatus(rs).name) # noqa: F405
diff --git a/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/BLOCK_IQ_RSA500/app.json b/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/BLOCK_IQ_RSA500/app.json
new file mode 100644
index 00000000..0e28292d
--- /dev/null
+++ b/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/BLOCK_IQ_RSA500/app.json
@@ -0,0 +1,197 @@
+{
+ "rfInstance": {
+ "nodes": [
+ {
+ "width": 192,
+ "height": 192,
+ "id": "BLOCK_IQ_RSA500-33713d6b-4202-414e-b8a3-2d9870aa0c7e",
+ "type": "HARDWARE",
+ "data": {
+ "id": "BLOCK_IQ_RSA500-33713d6b-4202-414e-b8a3-2d9870aa0c7e",
+ "label": "BLOCK IQ RSA500",
+ "func": "BLOCK_IQ_RSA500",
+ "type": "HARDWARE",
+ "ctrls": {
+ "center_freq": {
+ "type": "float",
+ "default": 100000000,
+ "desc": "The center frequency, in Hz.",
+ "overload": null,
+ "functionName": "BLOCK_IQ_RSA500",
+ "param": "center_freq",
+ "value": 99300000
+ },
+ "ref_level": {
+ "type": "float",
+ "default": -30,
+ "desc": "The reference level (the maximum y axis value), in dBm.",
+ "overload": null,
+ "functionName": "BLOCK_IQ_RSA500",
+ "param": "ref_level",
+ "value": -30
+ },
+ "record_length": {
+ "type": "float",
+ "default": 1000,
+ "desc": "The length to record (length of x axis), in ms.",
+ "overload": null,
+ "functionName": "BLOCK_IQ_RSA500",
+ "param": "record_length",
+ "value": 500
+ },
+ "bandwidth": {
+ "type": "float",
+ "default": 500000,
+ "desc": "Resolution bandwidth, in Hz.",
+ "overload": null,
+ "functionName": "BLOCK_IQ_RSA500",
+ "param": "bandwidth",
+ "value": 500000
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "I_real",
+ "id": "I_real",
+ "type": "OrderedPair",
+ "desc": "x: time\ny: power"
+ },
+ {
+ "name": "Q_imag",
+ "id": "Q_imag",
+ "type": "OrderedPair",
+ "desc": "x: time\ny: power"
+ }
+ ],
+ "path": "HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/BLOCK_IQ_RSA500/BLOCK_IQ_RSA500.py"
+ },
+ "position": {
+ "x": -56.027539485865546,
+ "y": -144.34132183199543
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -56.027539485865546,
+ "y": -144.34132183199543
+ },
+ "dragging": true
+ },
+ {
+ "width": 380,
+ "height": 293,
+ "id": "LINE-7f8f05d3-8628-400e-8b6b-5b5c01ac63bd",
+ "type": "VISUALIZATION",
+ "data": {
+ "id": "LINE-7f8f05d3-8628-400e-8b6b-5b5c01ac63bd",
+ "label": "LINE",
+ "func": "LINE",
+ "type": "VISUALIZATION",
+ "ctrls": {},
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "OrderedPair|DataFrame|Matrix|Vector",
+ "multiple": false,
+ "desc": "the DataContainer to be visualized"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "Plotly",
+ "desc": "the DataContainer containing the Plotly Line visualization of the input data"
+ }
+ ],
+ "path": "DATA/VISUALIZATION/PLOTLY/LINE/LINE.py"
+ },
+ "position": {
+ "x": 285.36059388919506,
+ "y": -27.241936012938595
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 285.36059388919506,
+ "y": -27.241936012938595
+ },
+ "dragging": true
+ },
+ {
+ "width": 380,
+ "height": 293,
+ "id": "LINE-b386bedb-cff5-4f45-bd9a-88af92b4a933",
+ "type": "VISUALIZATION",
+ "data": {
+ "id": "LINE-b386bedb-cff5-4f45-bd9a-88af92b4a933",
+ "label": "LINE 1",
+ "func": "LINE",
+ "type": "VISUALIZATION",
+ "ctrls": {},
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "OrderedPair|DataFrame|Matrix|Vector",
+ "multiple": false,
+ "desc": "the DataContainer to be visualized"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "Plotly",
+ "desc": "the DataContainer containing the Plotly Line visualization of the input data"
+ }
+ ],
+ "path": "DATA/VISUALIZATION/PLOTLY/LINE/LINE.py"
+ },
+ "position": {
+ "x": 287.25605181479796,
+ "y": -299.6107860259417
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 287.25605181479796,
+ "y": -299.6107860259417
+ },
+ "dragging": true
+ }
+ ],
+ "edges": [
+ {
+ "source": "BLOCK_IQ_RSA500-33713d6b-4202-414e-b8a3-2d9870aa0c7e",
+ "sourceHandle": "I_real",
+ "target": "LINE-b386bedb-cff5-4f45-bd9a-88af92b4a933",
+ "targetHandle": "default",
+ "id": "reactflow__edge-BLOCK_IQ_RSA500-33713d6b-4202-414e-b8a3-2d9870aa0c7eI_real-LINE-b386bedb-cff5-4f45-bd9a-88af92b4a933default"
+ },
+ {
+ "source": "BLOCK_IQ_RSA500-33713d6b-4202-414e-b8a3-2d9870aa0c7e",
+ "sourceHandle": "Q_imag",
+ "target": "LINE-7f8f05d3-8628-400e-8b6b-5b5c01ac63bd",
+ "targetHandle": "default",
+ "id": "reactflow__edge-BLOCK_IQ_RSA500-33713d6b-4202-414e-b8a3-2d9870aa0c7eQ_imag-LINE-7f8f05d3-8628-400e-8b6b-5b5c01ac63bddefault"
+ }
+ ],
+ "viewport": {
+ "x": 948.751833426666,
+ "y": 548.8961711096587,
+ "zoom": 0.8898510191682055
+ }
+ },
+ "textNodes": []
+}
\ No newline at end of file
diff --git a/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/BLOCK_IQ_RSA500/block_data.json b/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/BLOCK_IQ_RSA500/block_data.json
new file mode 100644
index 00000000..ce6ee7af
--- /dev/null
+++ b/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/BLOCK_IQ_RSA500/block_data.json
@@ -0,0 +1,40 @@
+{
+ "docstring": {
+ "long_description": "This block should also work with compatible Tektronix RSAXXX instruments.\n\nTested with RSA507a.",
+ "short_description": "Extract Block IQ measurement from a Tektronix RSA.",
+ "parameters": [
+ {
+ "name": "center_freq",
+ "type": "float, default=100e6",
+ "description": "The center frequency, in Hz."
+ },
+ {
+ "name": "ref_level",
+ "type": "float, default=-30",
+ "description": "The reference level (the maximum y axis value), in dBm."
+ },
+ {
+ "name": "record_length",
+ "type": "float, default=1e3",
+ "description": "The length to record (length of x axis), in ms."
+ },
+ {
+ "name": "bandwidth",
+ "type": "float, default=5e5",
+ "description": "Resolution bandwidth, in Hz."
+ }
+ ],
+ "returns": [
+ {
+ "name": "I_real",
+ "type": "OrderedPair",
+ "description": "x: time\ny: power"
+ },
+ {
+ "name": "Q_imag",
+ "type": "OrderedPair",
+ "description": "x: time\ny: power"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/BLOCK_IQ_RSA500/example.md b/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/BLOCK_IQ_RSA500/example.md
new file mode 100644
index 00000000..d5c1bea1
--- /dev/null
+++ b/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/BLOCK_IQ_RSA500/example.md
@@ -0,0 +1,8 @@
+In this example, Flojoy was used to extract I/Q data from a Tektronix RSA500.
+
+First the necessary blocks were added:
+
+- `BLOCK_IQ_RSA500`
+- 2x `LINE`
+
+Connect the blocks as shown an run the app. See [here](https://www.allaboutcircuits.com/textbook/radio-frequency-analysis-design/radio-frequency-demodulation/understanding-i-q-signals-and-quadrature-modulation/) for further technical explaination.
diff --git a/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/DPX_RSA500/DPX_RSA500.py b/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/DPX_RSA500/DPX_RSA500.py
new file mode 100644
index 00000000..d19eba97
--- /dev/null
+++ b/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/DPX_RSA500/DPX_RSA500.py
@@ -0,0 +1,162 @@
+from flojoy import flojoy, DataContainer, Surface
+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
+from os import path
+import numpy as np
+
+
+class DPXSplitOutput(TypedDict):
+ bitmap: Surface
+ dpx_ogram: Surface
+
+
+@flojoy
+def DPX_RSA500(
+ 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
+ ----------
+ 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
+ defau = "C:/Tektronix/RSA_API/lib/x64/RSA_API.dll"
+ moved = "C:/Program Files/Tek/RSA_API/lib/x64/RSA_API.dll"
+ if path.isfile(defau):
+ rsa = cdll.LoadLibrary(defau)
+ elif path.isfile(moved):
+ rsa = cdll.LoadLibrary(moved)
+ else:
+ raise FileNotFoundError(
+ "Cannot find RSA_API.dll. Download from: https://www.tek.com/en/products/spectrum-analyzers/rsa500"
+ )
+
+ 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
diff --git a/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/DPX_RSA500/app.json b/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/DPX_RSA500/app.json
new file mode 100644
index 00000000..0002bc9c
--- /dev/null
+++ b/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/DPX_RSA500/app.json
@@ -0,0 +1,235 @@
+{
+ "rfInstance": {
+ "nodes": [
+ {
+ "width": 192,
+ "height": 192,
+ "id": "DPX_RSA500-9793ef30-3342-49e0-9050-68b8580762d9",
+ "type": "HARDWARE",
+ "data": {
+ "id": "DPX_RSA500-9793ef30-3342-49e0-9050-68b8580762d9",
+ "label": "DPX RSA500",
+ "func": "DPX_RSA500",
+ "type": "HARDWARE",
+ "ctrls": {
+ "center_freq": {
+ "type": "float",
+ "default": 100000000,
+ "desc": "The center frequency, in Hz.",
+ "overload": null,
+ "functionName": "DPX_RSA500",
+ "param": "center_freq",
+ "value": 99300000
+ },
+ "ref_level": {
+ "type": "float",
+ "default": -30,
+ "desc": "The reference level (the maximum y axis value), in dBm.",
+ "overload": null,
+ "functionName": "DPX_RSA500",
+ "param": "ref_level",
+ "value": -30
+ },
+ "span": {
+ "type": "float",
+ "default": 1000000,
+ "desc": "The width of the x axis, in Hz.",
+ "overload": null,
+ "functionName": "DPX_RSA500",
+ "param": "span",
+ "value": 1000000
+ },
+ "bandwidth": {
+ "type": "float",
+ "default": 20000,
+ "desc": "Resolution bandwidth, in Hz.",
+ "overload": null,
+ "functionName": "DPX_RSA500",
+ "param": "bandwidth",
+ "value": 20000
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "bitmap",
+ "id": "bitmap",
+ "type": "Surface",
+ "desc": "x: frequency\ny: power\nz: occurances"
+ },
+ {
+ "name": "dpx_ogram",
+ "id": "dpx_ogram",
+ "type": "Surface",
+ "desc": "x: frequency\ny: trace number\nz: occurances"
+ }
+ ],
+ "path": "HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/DPX_RSA500/DPX_RSA500.py"
+ },
+ "position": {
+ "x": -132.74144499664698,
+ "y": -22.72976403902004
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": -132.74144499664698,
+ "y": -22.72976403902004
+ },
+ "dragging": true
+ },
+ {
+ "width": 380,
+ "height": 293,
+ "id": "HEATMAP-e93684b6-b790-43c5-b20b-5a654eed0e60",
+ "type": "VISUALIZATION",
+ "data": {
+ "id": "HEATMAP-e93684b6-b790-43c5-b20b-5a654eed0e60",
+ "label": "HEATMAP",
+ "func": "HEATMAP",
+ "type": "VISUALIZATION",
+ "ctrls": {
+ "show_text": {
+ "type": "bool",
+ "default": false,
+ "desc": "whether or not to show the text inside the heatmap color blocks",
+ "overload": null,
+ "functionName": "HEATMAP",
+ "param": "show_text",
+ "value": false
+ },
+ "histogram": {
+ "type": "bool",
+ "default": false,
+ "desc": "whether or not to render a histogram of the image next to the render",
+ "overload": null,
+ "functionName": "HEATMAP",
+ "param": "histogram",
+ "value": false
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "OrderedPair|Matrix|Grayscale|DataFrame|Vector|OrderedTriple|Surface",
+ "multiple": false,
+ "desc": "the DataContainer to be visualized"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "Plotly",
+ "desc": "the DataContainer containing the Plotly heatmap visualization"
+ }
+ ],
+ "path": "DATA/VISUALIZATION/PLOTLY/HEATMAP/HEATMAP.py"
+ },
+ "position": {
+ "x": 257.6702070990542,
+ "y": 75.60765713787168
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 257.6702070990542,
+ "y": 75.60765713787168
+ },
+ "dragging": true
+ },
+ {
+ "width": 380,
+ "height": 293,
+ "id": "HEATMAP-92039989-a727-4e17-990e-7aa31270fe0b",
+ "type": "VISUALIZATION",
+ "data": {
+ "id": "HEATMAP-92039989-a727-4e17-990e-7aa31270fe0b",
+ "label": "HEATMAP 1",
+ "func": "HEATMAP",
+ "type": "VISUALIZATION",
+ "ctrls": {
+ "show_text": {
+ "type": "bool",
+ "default": false,
+ "desc": "whether or not to show the text inside the heatmap color blocks",
+ "overload": null,
+ "functionName": "HEATMAP",
+ "param": "show_text",
+ "value": false
+ },
+ "histogram": {
+ "type": "bool",
+ "default": false,
+ "desc": "whether or not to render a histogram of the image next to the render",
+ "overload": null,
+ "functionName": "HEATMAP",
+ "param": "histogram",
+ "value": false
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "OrderedPair|Matrix|Grayscale|DataFrame|Vector|OrderedTriple|Surface",
+ "multiple": false,
+ "desc": "the DataContainer to be visualized"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "Plotly",
+ "desc": "the DataContainer containing the Plotly heatmap visualization"
+ }
+ ],
+ "path": "DATA/VISUALIZATION/PLOTLY/HEATMAP/HEATMAP.py"
+ },
+ "position": {
+ "x": 257.9907441712394,
+ "y": -202.85292611674154
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 257.9907441712394,
+ "y": -202.85292611674154
+ },
+ "dragging": true
+ }
+ ],
+ "edges": [
+ {
+ "source": "DPX_RSA500-9793ef30-3342-49e0-9050-68b8580762d9",
+ "sourceHandle": "dpx_ogram",
+ "target": "HEATMAP-e93684b6-b790-43c5-b20b-5a654eed0e60",
+ "targetHandle": "default",
+ "id": "reactflow__edge-DPX_RSA500-9793ef30-3342-49e0-9050-68b8580762d9dpx_ogram-HEATMAP-e93684b6-b790-43c5-b20b-5a654eed0e60default"
+ },
+ {
+ "source": "DPX_RSA500-9793ef30-3342-49e0-9050-68b8580762d9",
+ "sourceHandle": "bitmap",
+ "target": "HEATMAP-92039989-a727-4e17-990e-7aa31270fe0b",
+ "targetHandle": "default",
+ "id": "reactflow__edge-DPX_RSA500-9793ef30-3342-49e0-9050-68b8580762d9bitmap-HEATMAP-92039989-a727-4e17-990e-7aa31270fe0bdefault"
+ }
+ ],
+ "viewport": {
+ "x": 948.751833426666,
+ "y": 548.8961711096587,
+ "zoom": 0.8898510191682055
+ }
+ },
+ "textNodes": []
+}
\ No newline at end of file
diff --git a/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/DPX_RSA500/block_data.json b/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/DPX_RSA500/block_data.json
new file mode 100644
index 00000000..85597a28
--- /dev/null
+++ b/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/DPX_RSA500/block_data.json
@@ -0,0 +1,40 @@
+{
+ "docstring": {
+ "long_description": "This block should also work with compatible Tektronix RSAXXX instruments.\n\nTested with RSA507a.",
+ "short_description": "Run DPX (Digital Phosphor) analysis on the RSA500.",
+ "parameters": [
+ {
+ "name": "center_freq",
+ "type": "float, default=100e6",
+ "description": "The center frequency, in Hz."
+ },
+ {
+ "name": "ref_level",
+ "type": "float, default=-30",
+ "description": "The reference level (the maximum y axis value), in dBm."
+ },
+ {
+ "name": "span",
+ "type": "float, default=1e6",
+ "description": "The width of the x axis, in Hz."
+ },
+ {
+ "name": "bandwidth",
+ "type": "float, default=20e3",
+ "description": "Resolution bandwidth, in Hz."
+ }
+ ],
+ "returns": [
+ {
+ "name": "bitmap",
+ "type": "Surface",
+ "description": "x: frequency\ny: power\nz: occurances"
+ },
+ {
+ "name": "dpx_ogram",
+ "type": "Surface",
+ "description": "x: frequency\ny: trace number\nz: occurances"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/DPX_RSA500/example.md b/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/DPX_RSA500/example.md
new file mode 100644
index 00000000..12be45db
--- /dev/null
+++ b/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/DPX_RSA500/example.md
@@ -0,0 +1,8 @@
+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](https://www.tek.com/en/documents/primer/dpx-acquisition-technology-spectrum-analyzers-fundamentals) for further technical explaination.
diff --git a/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/EXTRACT_SPECTRUM_RSA500/EXTRACT_SPECTRUM_RSA500.py b/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/EXTRACT_SPECTRUM_RSA500/EXTRACT_SPECTRUM_RSA500.py
new file mode 100644
index 00000000..20628933
--- /dev/null
+++ b/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/EXTRACT_SPECTRUM_RSA500/EXTRACT_SPECTRUM_RSA500.py
@@ -0,0 +1,117 @@
+from flojoy import flojoy, DataContainer, OrderedPair
+from typing import Optional
+from flojoy.instruments.tektronix.RSA_API import * # noqa: F403
+from ctypes import cdll, c_int, c_bool, c_double, c_float, byref
+from os import path
+import numpy as np
+
+
+@flojoy()
+def EXTRACT_SPECTRUM_RSA500(
+ input: Optional[DataContainer] = None,
+ center_freq: float = 100e6,
+ ref_level: float = -30,
+ span: float = 1e6,
+ bandwidth: float = 10e3,
+) -> OrderedPair:
+ """Extracts and returns the spectrum trace from an Tektronix RSA.
+
+ This block should also work with compatible Tektronix RSAXXX instruments.
+
+ Tested with RSA507a.
+
+ Parameters
+ ----------
+ 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=10e3
+ Resolution bandwidth, in Hz.
+
+ Returns
+ -------
+ OrderedPair
+ RF spectrum trace
+ """
+
+ # Connect to RSA
+ moved = "C:/Program Files/Tek/RSA_API/lib/x64/RSA_API.dll"
+ defau = "C:/Tektronix/RSA_API/lib/x64/RSA_API.dll"
+ if path.isfile(defau):
+ rsa = cdll.LoadLibrary(defau)
+ elif path.isfile(moved):
+ rsa = cdll.LoadLibrary(moved)
+ else:
+ raise FileNotFoundError(
+ "Cannot find RSA_API.dll. Download from: https://www.tek.com/en/products/spectrum-analyzers/rsa500"
+ )
+
+ 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))
+
+ # 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()
+
+ # Configure spectrum
+ cf = center_freq
+ refLevel = ref_level
+ rbw = bandwidth
+
+ rsa.SPECTRUM_SetEnable(c_bool(True))
+ rsa.CONFIG_SetCenterFreq(c_double(cf))
+ rsa.CONFIG_SetReferenceLevel(c_double(refLevel))
+
+ rsa.SPECTRUM_SetDefault()
+ specSet = Spectrum_Settings() # noqa: F405
+ rsa.SPECTRUM_GetSettings(byref(specSet)) # noqa: F405
+ specSet.window = SpectrumWindows.SpectrumWindow_Kaiser # noqa: F405
+ specSet.verticalUnit = SpectrumVerticalUnits.SpectrumVerticalUnit_dBm # noqa: F405
+ specSet.span = span
+ specSet.rbw = rbw
+ rsa.SPECTRUM_SetSettings(specSet)
+ rsa.SPECTRUM_GetSettings(byref(specSet))
+
+ ready = c_bool(False)
+ traceArray = c_float * specSet.traceLength
+ traceData = traceArray()
+ outTracePoints = c_int(0)
+ traceSelector = SpectrumTraces.SpectrumTrace1 # noqa: F405
+
+ # Retrieve spectrum
+ rsa.DEVICE_Run()
+ rsa.SPECTRUM_AcquireTrace()
+ while not ready.value:
+ rsa.SPECTRUM_WaitForDataReady(c_int(100), byref(ready))
+ rsa.SPECTRUM_GetTrace(
+ traceSelector, specSet.traceLength, byref(traceData), byref(outTracePoints)
+ )
+ rsa.DEVICE_Stop()
+ trace = np.array(traceData)
+
+ freq = np.arange(
+ specSet.actualStartFreq,
+ specSet.actualStartFreq + specSet.actualFreqStepSize * specSet.traceLength,
+ specSet.actualFreqStepSize,
+ )
+
+ rsa.DEVICE_Disconnect()
+
+ return OrderedPair(x=freq, y=trace)
+
+
+def err_check(rs):
+ if ReturnStatus(rs) != ReturnStatus.noError: # noqa: F405
+ raise RSAError(ReturnStatus(rs).name) # noqa: F405
diff --git a/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/EXTRACT_SPECTRUM_RSA500/app.json b/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/EXTRACT_SPECTRUM_RSA500/app.json
new file mode 100644
index 00000000..748733de
--- /dev/null
+++ b/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/EXTRACT_SPECTRUM_RSA500/app.json
@@ -0,0 +1,141 @@
+{
+ "rfInstance": {
+ "nodes": [
+ {
+ "width": 192,
+ "height": 192,
+ "id": "EXTRACT_SPECTRUM_RSA500-af96bf14-3bdd-4d09-b8e7-ca7e24083c8e",
+ "type": "HARDWARE",
+ "data": {
+ "id": "EXTRACT_SPECTRUM_RSA500-af96bf14-3bdd-4d09-b8e7-ca7e24083c8e",
+ "label": "EXTRACT SPECTRUM RSA500",
+ "func": "EXTRACT_SPECTRUM_RSA500",
+ "type": "HARDWARE",
+ "ctrls": {
+ "center_freq": {
+ "type": "float",
+ "default": 100000000,
+ "desc": "The center frequency, in Hz.",
+ "overload": null,
+ "functionName": "EXTRACT_SPECTRUM_RSA500",
+ "param": "center_freq",
+ "value": 99300000
+ },
+ "ref_level": {
+ "type": "float",
+ "default": -30,
+ "desc": "The reference level (the maximum y axis value), in dBm.",
+ "overload": null,
+ "functionName": "EXTRACT_SPECTRUM_RSA500",
+ "param": "ref_level",
+ "value": -30
+ },
+ "span": {
+ "type": "float",
+ "default": 1000000,
+ "desc": "The width of the x axis, in Hz.",
+ "overload": null,
+ "functionName": "EXTRACT_SPECTRUM_RSA500",
+ "param": "span",
+ "value": 1000000
+ },
+ "bandwidth": {
+ "type": "float",
+ "default": 10000,
+ "desc": "Resolution bandwidth, in Hz.",
+ "overload": null,
+ "functionName": "EXTRACT_SPECTRUM_RSA500",
+ "param": "bandwidth",
+ "value": 10000
+ }
+ },
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "input",
+ "id": "input",
+ "type": "Any",
+ "multiple": false,
+ "desc": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "OrderedPair",
+ "desc": "RF spectrum trace"
+ }
+ ],
+ "path": "HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/EXTRACT_SPECTRUM_RSA500/EXTRACT_SPECTRUM_RSA500.py"
+ },
+ "position": {
+ "x": 294.6907674218594,
+ "y": 110.23947430672145
+ },
+ "selected": true,
+ "positionAbsolute": {
+ "x": 294.6907674218594,
+ "y": 110.23947430672145
+ }
+ },
+ {
+ "width": 380,
+ "height": 293,
+ "id": "LINE-e98d4d4b-6372-4419-9ebe-3af956455b26",
+ "type": "VISUALIZATION",
+ "data": {
+ "id": "LINE-e98d4d4b-6372-4419-9ebe-3af956455b26",
+ "label": "LINE",
+ "func": "LINE",
+ "type": "VISUALIZATION",
+ "ctrls": {},
+ "initCtrls": {},
+ "inputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "OrderedPair|DataFrame|Matrix|Vector",
+ "multiple": false,
+ "desc": "the DataContainer to be visualized"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "default",
+ "id": "default",
+ "type": "Plotly",
+ "desc": "the DataContainer containing the Plotly Line visualization of the input data"
+ }
+ ],
+ "path": "DATA/VISUALIZATION/PLOTLY/LINE/LINE.py"
+ },
+ "position": {
+ "x": 599.2583922530205,
+ "y": 93.16762276530585
+ },
+ "selected": false,
+ "positionAbsolute": {
+ "x": 599.2583922530205,
+ "y": 93.16762276530585
+ },
+ "dragging": true
+ }
+ ],
+ "edges": [
+ {
+ "source": "EXTRACT_SPECTRUM_RSA500-af96bf14-3bdd-4d09-b8e7-ca7e24083c8e",
+ "sourceHandle": "default",
+ "target": "LINE-e98d4d4b-6372-4419-9ebe-3af956455b26",
+ "targetHandle": "default",
+ "id": "reactflow__edge-EXTRACT_SPECTRUM_RSA500-af96bf14-3bdd-4d09-b8e7-ca7e24083c8edefault-LINE-e98d4d4b-6372-4419-9ebe-3af956455b26default"
+ }
+ ],
+ "viewport": {
+ "x": 948.751833426666,
+ "y": 548.8961711096587,
+ "zoom": 0.8898510191682055
+ }
+ },
+ "textNodes": []
+}
\ No newline at end of file
diff --git a/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/EXTRACT_SPECTRUM_RSA500/block_data.json b/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/EXTRACT_SPECTRUM_RSA500/block_data.json
new file mode 100644
index 00000000..f6552a04
--- /dev/null
+++ b/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/EXTRACT_SPECTRUM_RSA500/block_data.json
@@ -0,0 +1,35 @@
+{
+ "docstring": {
+ "long_description": "This block should also work with compatible Tektronix RSAXXX instruments.\n\nTested with RSA507a.",
+ "short_description": "Extracts and returns the spectrum trace from an Tektronix RSA.",
+ "parameters": [
+ {
+ "name": "center_freq",
+ "type": "float, default=100e6",
+ "description": "The center frequency, in Hz."
+ },
+ {
+ "name": "ref_level",
+ "type": "float, default=-30",
+ "description": "The reference level (the maximum y axis value), in dBm."
+ },
+ {
+ "name": "span",
+ "type": "float, default=1e6",
+ "description": "The width of the x axis, in Hz."
+ },
+ {
+ "name": "bandwidth",
+ "type": "float, default=10e3",
+ "description": "Resolution bandwidth, in Hz."
+ }
+ ],
+ "returns": [
+ {
+ "name": null,
+ "type": "OrderedPair",
+ "description": "RF spectrum trace"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/EXTRACT_SPECTRUM_RSA500/example.md b/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/EXTRACT_SPECTRUM_RSA500/example.md
new file mode 100644
index 00000000..957b9ea5
--- /dev/null
+++ b/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/EXTRACT_SPECTRUM_RSA500/example.md
@@ -0,0 +1,8 @@
+In this example, Flojoy was used to extract an RF spectrum from a Tektronix RSA500.
+
+First the necessary blocks were added:
+
+- `EXTRACT_SPECTRUM_RSA500`
+- `LINE`
+
+The default parameters are set to the FM radio frequencies (100 MHz). Set `center_freq` to your favourite station and see the resulting spectrum.
diff --git a/docs/src/content/docs/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/BLOCK_IQ_RSA500.mdx b/docs/src/content/docs/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/BLOCK_IQ_RSA500.mdx
new file mode 100644
index 00000000..4d4d29b9
--- /dev/null
+++ b/docs/src/content/docs/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/BLOCK_IQ_RSA500.mdx
@@ -0,0 +1,43 @@
+---
+title: BLOCK_IQ_RSA500
+description: "Extract Block IQ measurement from a Tektronix RSA."
+slug: blocks/hardware/signal-analyzers/tektronix/rsa500/block-iq-rsa500
+---
+
+{/* DO NOT EDIT THIS FILE! IT IS BEING AUTO GENERATED */}
+{/* PLEASE REFER TO THE CONTRIBUTION GUIDE ON THE DOCS PAGE */}
+
+import block_data from "@blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/BLOCK_IQ_RSA500/block_data.json";
+import PythonDocsDisplay from "@/components/PythonDocsDisplay.astro";
+
+
+
+Python Code
+
+import pythonCode from "@blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/BLOCK_IQ_RSA500/BLOCK_IQ_RSA500.py?raw";
+
+import { Code } from 'astro:components';
+
+
+
+[Find this Flojoy Block on GitHub](https://github.com/flojoy-ai/blocks/blob/main/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/BLOCK_IQ_RSA500/BLOCK_IQ_RSA500.py)
+
+
+
+## Example
+
+import GetHelpWidget from "@/components/GetHelpWidget.astro";
+
+
+
+import app from "@blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/BLOCK_IQ_RSA500/app.json";
+import AppDisplay from "@/components/AppDisplay.tsx";
+
+
+
+import Example from "@blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/BLOCK_IQ_RSA500/example.md";
+
+
+
+{/* DO NOT EDIT THIS FILE! IT IS BEING AUTO GENERATED */}
+{/* PLEASE REFER TO THE CONTRIBUTION GUIDE ON THE DOCS PAGE */}
diff --git a/docs/src/content/docs/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/DPX_RSA500.mdx b/docs/src/content/docs/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/DPX_RSA500.mdx
new file mode 100644
index 00000000..7895e7a8
--- /dev/null
+++ b/docs/src/content/docs/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/DPX_RSA500.mdx
@@ -0,0 +1,43 @@
+---
+title: DPX_RSA500
+description: "Run DPX (Digital Phosphor) analysis on the RSA500."
+slug: blocks/hardware/signal-analyzers/tektronix/rsa500/dpx-rsa500
+---
+
+{/* DO NOT EDIT THIS FILE! IT IS BEING AUTO GENERATED */}
+{/* PLEASE REFER TO THE CONTRIBUTION GUIDE ON THE DOCS PAGE */}
+
+import block_data from "@blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/DPX_RSA500/block_data.json";
+import PythonDocsDisplay from "@/components/PythonDocsDisplay.astro";
+
+
+
+Python Code
+
+import pythonCode from "@blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/DPX_RSA500/DPX_RSA500.py?raw";
+
+import { Code } from 'astro:components';
+
+
+
+[Find this Flojoy Block on GitHub](https://github.com/flojoy-ai/blocks/blob/main/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/DPX_RSA500/DPX_RSA500.py)
+
+
+
+## Example
+
+import GetHelpWidget from "@/components/GetHelpWidget.astro";
+
+
+
+import app from "@blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/DPX_RSA500/app.json";
+import AppDisplay from "@/components/AppDisplay.tsx";
+
+
+
+import Example from "@blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/DPX_RSA500/example.md";
+
+
+
+{/* DO NOT EDIT THIS FILE! IT IS BEING AUTO GENERATED */}
+{/* PLEASE REFER TO THE CONTRIBUTION GUIDE ON THE DOCS PAGE */}
diff --git a/docs/src/content/docs/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/EXTRACT_SPECTRUM_RSA500.mdx b/docs/src/content/docs/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/EXTRACT_SPECTRUM_RSA500.mdx
new file mode 100644
index 00000000..ad158bef
--- /dev/null
+++ b/docs/src/content/docs/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/EXTRACT_SPECTRUM_RSA500.mdx
@@ -0,0 +1,43 @@
+---
+title: EXTRACT_SPECTRUM_RSA500
+description: "Extracts and returns the spectrum trace from an Tektronix RSA."
+slug: blocks/hardware/signal-analyzers/tektronix/rsa500/extract-spectrum-rsa500
+---
+
+{/* DO NOT EDIT THIS FILE! IT IS BEING AUTO GENERATED */}
+{/* PLEASE REFER TO THE CONTRIBUTION GUIDE ON THE DOCS PAGE */}
+
+import block_data from "@blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/EXTRACT_SPECTRUM_RSA500/block_data.json";
+import PythonDocsDisplay from "@/components/PythonDocsDisplay.astro";
+
+
+
+Python Code
+
+import pythonCode from "@blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/EXTRACT_SPECTRUM_RSA500/EXTRACT_SPECTRUM_RSA500.py?raw";
+
+import { Code } from 'astro:components';
+
+
+
+[Find this Flojoy Block on GitHub](https://github.com/flojoy-ai/blocks/blob/main/blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/EXTRACT_SPECTRUM_RSA500/EXTRACT_SPECTRUM_RSA500.py)
+
+
+
+## Example
+
+import GetHelpWidget from "@/components/GetHelpWidget.astro";
+
+
+
+import app from "@blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/EXTRACT_SPECTRUM_RSA500/app.json";
+import AppDisplay from "@/components/AppDisplay.tsx";
+
+
+
+import Example from "@blocks/HARDWARE/SIGNAL_ANALYZERS/TEKTRONIX/RSA500/EXTRACT_SPECTRUM_RSA500/example.md";
+
+
+
+{/* DO NOT EDIT THIS FILE! IT IS BEING AUTO GENERATED */}
+{/* PLEASE REFER TO THE CONTRIBUTION GUIDE ON THE DOCS PAGE */}
diff --git a/docs/src/content/docs/blocks/HARDWARE/overview.mdx b/docs/src/content/docs/blocks/HARDWARE/overview.mdx
index 92cd4530..334fc932 100644
--- a/docs/src/content/docs/blocks/HARDWARE/overview.mdx
+++ b/docs/src/content/docs/blocks/HARDWARE/overview.mdx
@@ -132,6 +132,11 @@ import BlockCategory from "@/components/BlockCategory.astro";
+#### TEKTRONIX
+##### RSA500
+
+
+
### SOURCEMETERS
#### KEITHLEY