Skip to content
This repository has been archived by the owner on Dec 6, 2023. It is now read-only.

Add RSA blocks #43

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 33 additions & 4 deletions blocks/DATA/VISUALIZATION/PLOTLY/HEATMAP/HEATMAP.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
DataFrame,
Vector,
OrderedTriple,
Surface,
)
import plotly.graph_objects as go
import plotly.express as px
Expand All @@ -18,15 +19,21 @@

@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:
"""Create a Plotly Heatmap visualization for a given input DataContainer.

Inputs
------
default : OrderedPair|OrderedTriple|DataFrame|Vector|Matrix|Grayscale
default : OrderedPair|OrderedTriple|DataFrame|Vector|Matrix|Grayscale|Surface
the DataContainer to be visualized

Parameters
Expand All @@ -40,8 +47,8 @@ def HEATMAP(
-------
Plotly
the DataContainer containing the Plotly heatmap visualization

"""

layout = plot_layout(title="HEATMAP")
if histogram:
layout.sliders = [
Expand Down Expand Up @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion blocks/DATA/VISUALIZATION/PLOTLY/HEATMAP/block_data.json
Original file line number Diff line number Diff line change
@@ -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": [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -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"
)
Comment on lines +50 to +59
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this dll always located here? Also, this only works on windows?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it's only available for Windows. The default install location is the second one but I moved mine because I didn't want it on C: directly.


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
Original file line number Diff line number Diff line change
@@ -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": []
}
Loading