diff --git a/docs/nodes/IO/IMAGING/OPEN_WEBCAM/OPEN_WEBCAM.md b/docs/nodes/IO/IMAGING/OPEN_WEBCAM/OPEN_WEBCAM.md new file mode 100644 index 0000000000..5c49b7dfdf --- /dev/null +++ b/docs/nodes/IO/IMAGING/OPEN_WEBCAM/OPEN_WEBCAM.md @@ -0,0 +1,57 @@ + +[//]: # (Custom component imports) + +import DocString from '@site/src/components/DocString'; +import PythonCode from '@site/src/components/PythonCode'; +import AppDisplay from '@site/src/components/AppDisplay'; +import SectionBreak from '@site/src/components/SectionBreak'; +import AppendixSection from '@site/src/components/AppendixSection'; + +[//]: # (Docstring) + +import DocstringSource from '!!raw-loader!./a1-[autogen]/docstring.txt'; +import PythonSource from '!!raw-loader!./a1-[autogen]/python_code.txt'; + +{DocstringSource} +{PythonSource} + + + + + +[//]: # (Examples) + +## Examples + +import Example1 from './examples/EX1/example.md'; +import App1 from '!!raw-loader!./examples/EX1/app.json'; + + + + + {App1} + + + + + + + + +[//]: # (Appendix) + +import Notes from './appendix/notes.md'; +import Hardware from './appendix/hardware.md'; +import Media from './appendix/media.md'; + +## Appendix + + + + + + diff --git a/docs/nodes/IO/IMAGING/OPEN_WEBCAM/a1-[autogen]/docstring.txt b/docs/nodes/IO/IMAGING/OPEN_WEBCAM/a1-[autogen]/docstring.txt new file mode 100644 index 0000000000..6f4374314e --- /dev/null +++ b/docs/nodes/IO/IMAGING/OPEN_WEBCAM/a1-[autogen]/docstring.txt @@ -0,0 +1,12 @@ +The OPEN_WEBCAM node opens a connection with the selected camera. + + Parameters + ---------- + camera : Camera + The camera to use. + resolution : select + Camera resolution. Choose from a few options. + + Returns + ------- + None diff --git a/docs/nodes/IO/IMAGING/OPEN_WEBCAM/a1-[autogen]/python_code.txt b/docs/nodes/IO/IMAGING/OPEN_WEBCAM/a1-[autogen]/python_code.txt new file mode 100644 index 0000000000..fd4be81271 --- /dev/null +++ b/docs/nodes/IO/IMAGING/OPEN_WEBCAM/a1-[autogen]/python_code.txt @@ -0,0 +1,20 @@ +import cv2 +from flojoy import CameraDevice, flojoy, DataContainer +from flojoy.connection_manager import DeviceConnectionManager +from typing import Optional, Literal + + +@flojoy(deps={"opencv-python-headless": "4.7.0.72"}) +def OPEN_WEBCAM( + camera: CameraDevice, + default: Optional[DataContainer] = None, +) -> Optional[DataContainer]: + + + if not camera: + raise ValueError("No camera selected") + + cam = cv2.VideoCapture(camera.get_id()) + DeviceConnectionManager.register_connection(camera, cam) + + return None diff --git a/docs/nodes/IO/IMAGING/OPEN_WEBCAM/appendix/hardware.md b/docs/nodes/IO/IMAGING/OPEN_WEBCAM/appendix/hardware.md new file mode 100644 index 0000000000..7f78a555c4 --- /dev/null +++ b/docs/nodes/IO/IMAGING/OPEN_WEBCAM/appendix/hardware.md @@ -0,0 +1 @@ +This node does not require any peripheral hardware to operate. Please see INSTRUMENTS for nodes that interact with the physical world through connected hardware. \ No newline at end of file diff --git a/docs/nodes/IO/IMAGING/OPEN_WEBCAM/appendix/media.md b/docs/nodes/IO/IMAGING/OPEN_WEBCAM/appendix/media.md new file mode 100644 index 0000000000..8bcee9be90 --- /dev/null +++ b/docs/nodes/IO/IMAGING/OPEN_WEBCAM/appendix/media.md @@ -0,0 +1 @@ +No supporting screenshots, photos, or videos have been added to the media.md file for this node. \ No newline at end of file diff --git a/docs/nodes/IO/IMAGING/OPEN_WEBCAM/appendix/notes.md b/docs/nodes/IO/IMAGING/OPEN_WEBCAM/appendix/notes.md new file mode 100644 index 0000000000..04aded2ec9 --- /dev/null +++ b/docs/nodes/IO/IMAGING/OPEN_WEBCAM/appendix/notes.md @@ -0,0 +1 @@ +No theory or technical notes have been contributed for this node yet. \ No newline at end of file diff --git a/docs/nodes/IO/IMAGING/OPEN_WEBCAM/examples/EX1/app.json b/docs/nodes/IO/IMAGING/OPEN_WEBCAM/examples/EX1/app.json new file mode 100644 index 0000000000..5db0940404 --- /dev/null +++ b/docs/nodes/IO/IMAGING/OPEN_WEBCAM/examples/EX1/app.json @@ -0,0 +1,204 @@ +{ + "rfInstance": { + "nodes": [ + { + "width": 192, + "height": 192, + "id": "OPEN_WEBCAM-89c7016f-6198-4bee-bb37-0ffa21729da5", + "type": "IO", + "data": { + "id": "OPEN_WEBCAM-89c7016f-6198-4bee-bb37-0ffa21729da5", + "label": "OPEN WEBCAM", + "func": "OPEN_WEBCAM", + "type": "IO", + "ctrls": { + "camera": { + "type": "CameraDevice", + "default": null, + "desc": null, + "overload": null, + "functionName": "OPEN_WEBCAM", + "param": "camera", + "value": "" + } + }, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "Any", + "multiple": false, + "desc": null + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "Any", + "desc": null + } + ], + "pip_dependencies": [ + { + "name": "opencv-python-headless", + "v": "4.7.0.72" + } + ], + "path": "IO/IMAGING/OPEN_WEBCAM/OPEN_WEBCAM.py", + "selected": false + }, + "position": { + "x": -179.01679378861343, + "y": 3.074962043597168 + }, + "selected": false, + "positionAbsolute": { + "x": -179.01679378861343, + "y": 3.074962043597168 + }, + "dragging": true + }, + { + "width": 192, + "height": 192, + "id": "WEBCAM-89b91b3a-0682-44db-95d9-b1e26d1dd12c", + "type": "IO", + "data": { + "id": "WEBCAM-89b91b3a-0682-44db-95d9-b1e26d1dd12c", + "label": "WEBCAM", + "func": "WEBCAM", + "type": "IO", + "ctrls": { + "connection": { + "type": "CameraConnection", + "default": null, + "desc": null, + "overload": null, + "functionName": "WEBCAM", + "param": "connection", + "value": "" + }, + "resolution": { + "type": "select", + "options": [ + "default", + "640x360", + "640x480", + "1280x720", + "1920x1080" + ], + "default": "default", + "desc": "Camera resolution. Choose from a few options.", + "overload": null, + "functionName": "WEBCAM", + "param": "resolution", + "value": "default" + } + }, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "Any", + "multiple": false, + "desc": null + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "Image", + "desc": null + } + ], + "pip_dependencies": [ + { + "name": "opencv-python-headless", + "v": "4.7.0.72" + } + ], + "path": "IO/IMAGING/WEBCAM/WEBCAM.py", + "selected": false + }, + "position": { + "x": 179.0676354144525, + "y": 0.6447218141543658 + }, + "selected": false, + "positionAbsolute": { + "x": 179.0676354144525, + "y": 0.6447218141543658 + }, + "dragging": true + }, + { + "width": 225, + "height": 226, + "id": "IMAGE-d27c4496-301f-4882-8670-6bb84ebe7e06", + "type": "VISUALIZERS", + "data": { + "id": "IMAGE-d27c4496-301f-4882-8670-6bb84ebe7e06", + "label": "IMAGE", + "func": "IMAGE", + "type": "VISUALIZERS", + "ctrls": {}, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "Image|Grayscale", + "multiple": false, + "desc": "the DataContainer to be visualized" + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "Plotly", + "desc": "the DataContainer containing the Plotly Image visualization of the input image" + } + ], + "path": "VISUALIZERS/PLOTLY/IMAGE/IMAGE.py", + "selected": false + }, + "position": { + "x": 515.9438185125092, + "y": -20.240488117947223 + }, + "selected": false, + "positionAbsolute": { + "x": 515.9438185125092, + "y": -20.240488117947223 + }, + "dragging": true + } + ], + "edges": [ + { + "source": "WEBCAM-89b91b3a-0682-44db-95d9-b1e26d1dd12c", + "sourceHandle": "default", + "target": "IMAGE-d27c4496-301f-4882-8670-6bb84ebe7e06", + "targetHandle": "default", + "id": "reactflow__edge-WEBCAM-89b91b3a-0682-44db-95d9-b1e26d1dd12cdefault-IMAGE-d27c4496-301f-4882-8670-6bb84ebe7e06default" + }, + { + "source": "OPEN_WEBCAM-89c7016f-6198-4bee-bb37-0ffa21729da5", + "sourceHandle": "default", + "target": "WEBCAM-89b91b3a-0682-44db-95d9-b1e26d1dd12c", + "targetHandle": "default", + "id": "reactflow__edge-OPEN_WEBCAM-89c7016f-6198-4bee-bb37-0ffa21729da5default-WEBCAM-89b91b3a-0682-44db-95d9-b1e26d1dd12cdefault" + } + ], + "viewport": { + "x": 255.10425070720453, + "y": 317.88940714410813, + "zoom": 0.5 + } + } +} \ No newline at end of file diff --git a/docs/nodes/IO/IMAGING/OPEN_WEBCAM/examples/EX1/example.md b/docs/nodes/IO/IMAGING/OPEN_WEBCAM/examples/EX1/example.md new file mode 100644 index 0000000000..8255654e7e --- /dev/null +++ b/docs/nodes/IO/IMAGING/OPEN_WEBCAM/examples/EX1/example.md @@ -0,0 +1,12 @@ +--- +title: OPEN_WEBCAM +description: In this example, the OPEN_WEBCAM opens the connection with the connected camera, then uses the `WEBCAM` node takes and returns a picture. The IMSHOW node then displays the image taken by the camera. +keyword: [Python, Instrument, Web cam, Camera, Python webcam integration, Camera instrument in Python, Capture images and videos, Streamline webcam usage, Python-based camera control, Webcam integration techniques, Python image and video capture, Enhance projects with webcam, Accurate media processing, Webcam usage with Python] +image: https://raw.githubusercontent.com/flojoy-ai/docs/main/docs/nodes/INSTRUMENTS/WEB_CAM/CAMERA/examples/EX1/output.jpeg +--- + +In this example app, the [`CAMERA`](https://github.com/flojoy-io/nodes/blob/main/INSTRUMENTS/WEB_CAM/CAMERA/CAMERA.py) node takes and returns a picture from a camera connected to the computer. + +The camera first has to be opened with the [`OPEN_CAMERA`](https://github.com/flojoy-io/nodes/blob/main/INSTRUMENTS/WEB_CAM/CAMERA/CAMERA.py) node, which requires you to select which camera to use. + +The [`IMSHOW`](https://github.com/flojoy-io/nodes/blob/main/VISUALIZERS/PLOTLY/TABLE/TABLE.py) node displays the image taken by the camera that was selected. diff --git a/docs/nodes/IO/IMAGING/WEBCAM/a1-[autogen]/docstring.txt b/docs/nodes/IO/IMAGING/WEBCAM/a1-[autogen]/docstring.txt index f529c130a9..8844ece47a 100644 --- a/docs/nodes/IO/IMAGING/WEBCAM/a1-[autogen]/docstring.txt +++ b/docs/nodes/IO/IMAGING/WEBCAM/a1-[autogen]/docstring.txt @@ -1,11 +1,11 @@ The CAMERA node acquires an image using the selected camera. - If no camera is detected, an error would be shown. + The selected camera must be opened already using the OPEN_WEBCAM node. Parameters ---------- - camera_ind : int - Camera index (i.e. camera identifier). + connection : Camera + The opened camera connection to use. resolution : select Camera resolution. Choose from a few options. diff --git a/docs/nodes/IO/IMAGING/WEBCAM/a1-[autogen]/python_code.txt b/docs/nodes/IO/IMAGING/WEBCAM/a1-[autogen]/python_code.txt index 857b54e822..1d2c71d19e 100644 --- a/docs/nodes/IO/IMAGING/WEBCAM/a1-[autogen]/python_code.txt +++ b/docs/nodes/IO/IMAGING/WEBCAM/a1-[autogen]/python_code.txt @@ -1,41 +1,38 @@ import cv2 -import os -from flojoy import flojoy, DataContainer +from flojoy import flojoy, DataContainer, CameraConnection, Image from typing import Optional, Literal -from PIL import Image -import numpy as np -@flojoy(deps={"opencv-python-headless": "4.7.0.72"}) +@flojoy(deps={"opencv-python-headless": "4.7.0.72"}, inject_connection=True) def WEBCAM( + connection: CameraConnection, default: Optional[DataContainer] = None, - camera_ind: int = -1, resolution: Literal[ "default", "640x360", "640x480", "1280x720", "1920x1080" ] = "default", -) -> DataContainer: +) -> Image: + cam = connection.get_handle() try: - camera = cv2.VideoCapture(camera_ind) if resolution != "default": resolution = resolution.split("x") try: - camera.set(cv2.CAP_PROP_FRAME_WIDTH, int(resolution[0])) - camera.set(cv2.CAP_PROP_FRAME_HEIGHT, int(resolution[1])) + cam.set(cv2.CAP_PROP_FRAME_WIDTH, int(resolution[0])) + cam.set(cv2.CAP_PROP_FRAME_HEIGHT, int(resolution[1])) except cv2.error as camera_error: print(f"Invalid resolution ({resolution}). Try a lower value.") raise camera_error - if not camera.isOpened(): + if not cam.isOpened(): raise cv2.error("Failed to open camera") - result, BGR_img = camera.read() + result, BGR_img = cam.read() if not result: raise cv2.error("Failed to capture image") - camera.release() - del camera + # cam.release() + # del cam RGB_img = cv2.cvtColor(BGR_img, cv2.COLOR_BGR2RGB) @@ -49,8 +46,7 @@ def WEBCAM( else: alpha_channel = None - camera_image = DataContainer( - type="Image", + camera_image = Image( r=red_channel, g=green_channel, b=blue_channel, diff --git a/docs/nodes/IO/IMAGING/WEBCAM/examples/EX1/app.json b/docs/nodes/IO/IMAGING/WEBCAM/examples/EX1/app.json index b0da688128..5db0940404 100644 --- a/docs/nodes/IO/IMAGING/WEBCAM/examples/EX1/app.json +++ b/docs/nodes/IO/IMAGING/WEBCAM/examples/EX1/app.json @@ -2,26 +2,86 @@ "rfInstance": { "nodes": [ { - "width": 150, - "height": 150, - "id": "CAMERA-29dc2b2f-b87c-46a3-9ddc-11e685de3206", - "type": "INSTRUMENTS", + "width": 192, + "height": 192, + "id": "OPEN_WEBCAM-89c7016f-6198-4bee-bb37-0ffa21729da5", + "type": "IO", "data": { - "id": "CAMERA-29dc2b2f-b87c-46a3-9ddc-11e685de3206", - "label": "CAMERA", - "func": "CAMERA", - "type": "INSTRUMENTS", + "id": "OPEN_WEBCAM-89c7016f-6198-4bee-bb37-0ffa21729da5", + "label": "OPEN WEBCAM", + "func": "OPEN_WEBCAM", + "type": "IO", "ctrls": { - "camera_ind": { - "type": "int", - "default": -1, - "functionName": "CAMERA", - "param": "camera_ind", - "value": -1 + "camera": { + "type": "CameraDevice", + "default": null, + "desc": null, + "overload": null, + "functionName": "OPEN_WEBCAM", + "param": "camera", + "value": "" + } + }, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "Any", + "multiple": false, + "desc": null + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "Any", + "desc": null + } + ], + "pip_dependencies": [ + { + "name": "opencv-python-headless", + "v": "4.7.0.72" + } + ], + "path": "IO/IMAGING/OPEN_WEBCAM/OPEN_WEBCAM.py", + "selected": false + }, + "position": { + "x": -179.01679378861343, + "y": 3.074962043597168 + }, + "selected": false, + "positionAbsolute": { + "x": -179.01679378861343, + "y": 3.074962043597168 + }, + "dragging": true + }, + { + "width": 192, + "height": 192, + "id": "WEBCAM-89b91b3a-0682-44db-95d9-b1e26d1dd12c", + "type": "IO", + "data": { + "id": "WEBCAM-89b91b3a-0682-44db-95d9-b1e26d1dd12c", + "label": "WEBCAM", + "func": "WEBCAM", + "type": "IO", + "ctrls": { + "connection": { + "type": "CameraConnection", + "default": null, + "desc": null, + "overload": null, + "functionName": "WEBCAM", + "param": "connection", + "value": "" }, "resolution": { "type": "select", - "default": "default", "options": [ "default", "640x360", @@ -29,24 +89,30 @@ "1280x720", "1920x1080" ], - "functionName": "CAMERA", + "default": "default", + "desc": "Camera resolution. Choose from a few options.", + "overload": null, + "functionName": "WEBCAM", "param": "resolution", "value": "default" } }, + "initCtrls": {}, "inputs": [ { "name": "default", "id": "default", "type": "Any", - "multiple": false + "multiple": false, + "desc": null } ], "outputs": [ { "name": "default", "id": "default", - "type": "Any" + "type": "Image", + "desc": null } ], "pip_dependencies": [ @@ -55,93 +121,84 @@ "v": "4.7.0.72" } ], - "path": "PYTHON/nodes/INSTRUMENTS/WEB_CAM/CAMERA/CAMERA.py", + "path": "IO/IMAGING/WEBCAM/WEBCAM.py", "selected": false }, "position": { - "x": 934.4795759482945, - "y": -38.568710835013746 + "x": 179.0676354144525, + "y": 0.6447218141543658 }, "selected": false, "positionAbsolute": { - "x": 934.4795759482945, - "y": -38.568710835013746 + "x": 179.0676354144525, + "y": 0.6447218141543658 }, "dragging": true }, { "width": 225, "height": 226, - "id": "IMAGE-cd503f68-87fd-478a-b577-baa959f3df08", + "id": "IMAGE-d27c4496-301f-4882-8670-6bb84ebe7e06", "type": "VISUALIZERS", "data": { - "id": "IMAGE-cd503f68-87fd-478a-b577-baa959f3df08", + "id": "IMAGE-d27c4496-301f-4882-8670-6bb84ebe7e06", "label": "IMAGE", "func": "IMAGE", "type": "VISUALIZERS", "ctrls": {}, + "initCtrls": {}, "inputs": [ { "name": "default", "id": "default", - "type": "Image", - "multiple": false + "type": "Image|Grayscale", + "multiple": false, + "desc": "the DataContainer to be visualized" } ], "outputs": [ { "name": "default", "id": "default", - "type": "Plotly" + "type": "Plotly", + "desc": "the DataContainer containing the Plotly Image visualization of the input image" } ], - "path": "PYTHON/nodes/VISUALIZERS/PLOTLY/IMAGE/IMAGE.py", + "path": "VISUALIZERS/PLOTLY/IMAGE/IMAGE.py", "selected": false }, "position": { - "x": 1261.9152508247892, - "y": -78.58047260527047 + "x": 515.9438185125092, + "y": -20.240488117947223 }, "selected": false, "positionAbsolute": { - "x": 1261.9152508247892, - "y": -78.58047260527047 + "x": 515.9438185125092, + "y": -20.240488117947223 }, "dragging": true } ], "edges": [ { - "source": "CAMERA-29dc2b2f-b87c-46a3-9ddc-11e685de3206", + "source": "WEBCAM-89b91b3a-0682-44db-95d9-b1e26d1dd12c", "sourceHandle": "default", - "target": "IMAGE-cd503f68-87fd-478a-b577-baa959f3df08", + "target": "IMAGE-d27c4496-301f-4882-8670-6bb84ebe7e06", "targetHandle": "default", - "id": "reactflow__edge-CAMERA-29dc2b2f-b87c-46a3-9ddc-11e685de3206default-IMAGE-cd503f68-87fd-478a-b577-baa959f3df08default" + "id": "reactflow__edge-WEBCAM-89b91b3a-0682-44db-95d9-b1e26d1dd12cdefault-IMAGE-d27c4496-301f-4882-8670-6bb84ebe7e06default" + }, + { + "source": "OPEN_WEBCAM-89c7016f-6198-4bee-bb37-0ffa21729da5", + "sourceHandle": "default", + "target": "WEBCAM-89b91b3a-0682-44db-95d9-b1e26d1dd12c", + "targetHandle": "default", + "id": "reactflow__edge-OPEN_WEBCAM-89c7016f-6198-4bee-bb37-0ffa21729da5default-WEBCAM-89b91b3a-0682-44db-95d9-b1e26d1dd12cdefault" } ], "viewport": { - "x": -358.59636577932724, - "y": 99.85117439980638, - "zoom": 1.0581352782820395 - } - }, - "ctrlsManifest": [ - { - "type": "input", - "name": "Slider", - "id": "INPUT_PLACEHOLDER", - "hidden": false, - "minHeight": 1, - "minWidth": 2, - "layout": { - "x": 0, - "y": 0, - "h": 2, - "w": 2, - "minH": 1, - "minW": 2, - "i": "INPUT_PLACEHOLDER" - } + "x": 255.10425070720453, + "y": 317.88940714410813, + "zoom": 0.5 } - ] + } } \ No newline at end of file diff --git a/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/a1-[autogen]/docstring.txt b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/a1-[autogen]/docstring.txt index 862fbadae6..87fc889b00 100644 --- a/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/a1-[autogen]/docstring.txt +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/a1-[autogen]/docstring.txt @@ -1,11 +1,14 @@ -The KEITHLEY2400 node takes an I-V curve measurement with a Keithley 2400 source meter, send voltages, and measures currents. +The IV_SWEEP node takes an I-V curve measurement with a Keithley 2400 source meter, send voltages, and measures currents. + + Inputs + ------ + default: OrderedPair | Vector + The voltages to send to the Keithley 2400 source meter. Parameters ---------- - comport : str - Defines the serial communication port for the Keithley2400 source meter. - baudrate : float - Specifies the baud rate for the serial communication between the Keithley2400 and the computer. + connection: Serial + The open connection with the Keithley2400 source meter. Returns ------- diff --git a/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/a1-[autogen]/python_code.txt b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/a1-[autogen]/python_code.txt index 822d972e5c..9f7546ea48 100644 --- a/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/a1-[autogen]/python_code.txt +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/a1-[autogen]/python_code.txt @@ -1,24 +1,26 @@ -from flojoy import flojoy, OrderedPair, Vector, node_initialization, NodeInitContainer import serial +import numpy as np +from flojoy import SerialConnection, flojoy, OrderedPair, Vector +from typing import cast -@flojoy(deps={"pyserial": "3.5"}) +@flojoy(deps={"pyserial": "3.5"}, inject_connection=True) def IV_SWEEP( - init_container: NodeInitContainer, default: OrderedPair | Vector + connection: SerialConnection, default: OrderedPair | Vector ) -> OrderedPair: # Start serial communication with the instrument - # ser: serial = serial.Serial() + ser = cast(serial.Serial, connection.get_handle()) - ser = init_container.get() if ser is None: raise ValueError("Serial communication is not open") # Keithley 2400 Configuration ser.write(b"*RST\n") # reinitialisation of the instrument - ser.write(b":SOUR:FUNC:MODE VOLT\n") # Sourcing tension - ser.write(b':SENS:FUNC "CURR"\n') # Measuring current + ser.write( + b":SOUR:FUNC:MODE VOLT\n" + ) # Sourcing tension ser.write(b':SENS:FUNC "CURR"\n') # Measuring current ser.write( b":SENS:CURR:PROT 1.05\n" ) # Current protection set at 1.05A (Keithley 2400) @@ -37,11 +39,8 @@ def IV_SWEEP( ser.write(b":INIT\n") # Start measuring ser.write(b":FETC?\n") # Retrieve the measured values - current_str: str = ( - ser.readline().decode("ascii").strip() - ) # Save answers in a string - voltage_current_values: str = current_str.split( - ",") # Split the string + current_str = ser.readline().decode("ascii").strip() # Save answers in a string + voltage_current_values = current_str.split(",") # Split the string currents_neg.append(-float(voltage_current_values[1])) ser.write(b":OUTP OFF\n") # Close output from Instrument @@ -49,23 +48,4 @@ def IV_SWEEP( # Close Serial Communication ser.close() - return OrderedPair(x=voltages, y=currents_neg) - - -@node_initialization(for_node=IV_SWEEP) -def init(comport: str = "/dev/ttyUSB0", baudrate: float = 9600): - ser: serial = serial.Serial() - - # Specific parameters - ser.port = comport # Specify serial port for com - ser.baudrate = baudrate # Specify Baudrate - - # General parameters - ser.bytesize = serial.EIGHTBITS # Specify Bites number - ser.parity = serial.PARITY_NONE # Specify Parity - ser.stopbits = serial.STOPBITS_ONE # Specify Stop bites - ser.timeout = 1 - # Open Serial Com - ser.open() - - return ser + return OrderedPair(x=voltages, y=np.array(currents_neg)) diff --git a/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/examples/EX1/app.json b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/examples/EX1/app.json index 2617aef0d7..6784b06926 100644 --- a/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/examples/EX1/app.json +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/examples/EX1/app.json @@ -4,32 +4,84 @@ { "width": 192, "height": 192, - "id": "KEITHLEY2400-33053219-7ec1-40d0-9cb9-5d337294a01e", - "type": "INSTRUMENTS", + "id": "OPEN_KEITHLEY_24XX-097d2560-f5b9-468a-9517-32e89dedecc1", + "type": "IO", "data": { - "id": "KEITHLEY2400-33053219-7ec1-40d0-9cb9-5d337294a01e", - "label": "KEITHLEY2400", - "func": "KEITHLEY2400", - "type": "INSTRUMENTS", - "ctrls": {}, - "initCtrls": { - "comport": { - "type": "str", - "default": "/dev/ttyUSB0", + "id": "OPEN_KEITHLEY_24XX-097d2560-f5b9-468a-9517-32e89dedecc1", + "label": "OPEN KEITHLEY 24XX", + "func": "OPEN_KEITHLEY_24XX", + "type": "IO", + "ctrls": { + "device": { + "type": "SerialDevice", + "default": null, "desc": null, - "functionName": "KEITHLEY2400", - "param": "comport", - "value": "/dev/ttyUSB0" + "overload": null, + "functionName": "OPEN_KEITHLEY_24XX", + "param": "device", + "value": "" }, "baudrate": { - "type": "float", + "type": "int", "default": 9600, "desc": null, - "functionName": "KEITHLEY2400", + "overload": null, + "functionName": "OPEN_KEITHLEY_24XX", "param": "baudrate", "value": 9600 } }, + "initCtrls": {}, + "outputs": [ + { + "name": "default", + "id": "default", + "type": "Any", + "desc": null + } + ], + "pip_dependencies": [ + { + "name": "pyserial", + "v": "3.5" + } + ], + "path": "IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/OPEN_KEITHLEY_24XX.py", + "selected": false + }, + "position": { + "x": -140.35863305434796, + "y": 1.9088042829506549 + }, + "selected": false, + "positionAbsolute": { + "x": -140.35863305434796, + "y": 1.9088042829506549 + }, + "dragging": true + }, + { + "width": 192, + "height": 192, + "id": "IV_SWEEP-41060d63-89ff-46f2-914b-944a11d24ed7", + "type": "IO", + "data": { + "id": "IV_SWEEP-41060d63-89ff-46f2-914b-944a11d24ed7", + "label": "IV SWEEP", + "func": "IV_SWEEP", + "type": "IO", + "ctrls": { + "connection": { + "type": "SerialConnection", + "default": null, + "desc": null, + "overload": null, + "functionName": "IV_SWEEP", + "param": "connection", + "value": "" + } + }, + "initCtrls": {}, "inputs": [ { "name": "default", @@ -53,27 +105,27 @@ "v": "3.5" } ], - "path": "PYTHON/nodes/INSTRUMENTS/KEITHLEY/KEITHLEY2400/KEITHLEY2400.py", + "path": "IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/IV_SWEEP.py", "selected": false }, "position": { - "x": 114.41979939902592, - "y": -225.9703888733589 + "x": 511.6912461233678, + "y": 5.980216390951398 }, "selected": false, "positionAbsolute": { - "x": 114.41979939902592, - "y": -225.9703888733589 + "x": 511.6912461233678, + "y": 5.980216390951398 }, "dragging": true }, { "width": 208, "height": 96, - "id": "LINSPACE-a3ec55cd-d572-437a-a823-7a8707fc2099", + "id": "LINSPACE-db9bbe29-66a0-4122-ad24-e3c00b1fba28", "type": "GENERATORS", "data": { - "id": "LINSPACE-a3ec55cd-d572-437a-a823-7a8707fc2099", + "id": "LINSPACE-db9bbe29-66a0-4122-ad24-e3c00b1fba28", "label": "LINSPACE", "func": "LINSPACE", "type": "GENERATORS", @@ -82,6 +134,7 @@ "type": "float", "default": 10, "desc": "The start point of the data.", + "overload": null, "functionName": "LINSPACE", "param": "start", "value": 10 @@ -90,6 +143,7 @@ "type": "float", "default": 0, "desc": "The end point of the data.", + "overload": null, "functionName": "LINSPACE", "param": "end", "value": 0 @@ -98,9 +152,10 @@ "type": "int", "default": 1000, "desc": "The number of points in the vector.", + "overload": null, "functionName": "LINSPACE", "param": "step", - "value": 1000 + "value": 10 } }, "initCtrls": {}, @@ -118,32 +173,32 @@ "name": "default", "id": "default", "type": "Vector", - "desc": "v: the vector between start and end with step number of points." + "desc": "v: the vector between 'start' and 'end' with a 'step' number of points." } ], - "path": "PYTHON/nodes/GENERATORS/SIMULATIONS/LINSPACE/LINSPACE.py", + "path": "GENERATORS/SIMULATIONS/LINSPACE/LINSPACE.py", "selected": false }, "position": { - "x": -220.989828306302, - "y": -177.3419913453396 + "x": 192.47824090745922, + "y": 49.8416165273091 }, "selected": false, "positionAbsolute": { - "x": -220.989828306302, - "y": -177.3419913453396 + "x": 192.47824090745922, + "y": 49.8416165273091 }, "dragging": true }, { "width": 225, "height": 226, - "id": "LINE-5ea158cf-c235-4bff-bec2-0714507a1bf0", + "id": "SCATTER-fee34277-0702-4342-af77-37c9d68701c6", "type": "VISUALIZERS", "data": { - "id": "LINE-5ea158cf-c235-4bff-bec2-0714507a1bf0", - "label": "LINE", - "func": "LINE", + "id": "SCATTER-fee34277-0702-4342-af77-37c9d68701c6", + "label": "SCATTER", + "func": "SCATTER", "type": "VISUALIZERS", "ctrls": {}, "initCtrls": {}, @@ -161,44 +216,51 @@ "name": "default", "id": "default", "type": "Plotly", - "desc": "the DataContainer containing Plotly Line visualization of the input data" + "desc": "the DataContainer containing the Plotly Scatter visualization" } ], - "path": "PYTHON/nodes/VISUALIZERS/PLOTLY/LINE/LINE.py", - "selected": true + "path": "VISUALIZERS/PLOTLY/SCATTER/SCATTER.py", + "selected": false }, "position": { - "x": 448.130869654421, - "y": -243.92275361997378 + "x": 822.0611229804773, + "y": -8.822814846961876 }, - "selected": true, + "selected": false, "positionAbsolute": { - "x": 448.130869654421, - "y": -243.92275361997378 + "x": 822.0611229804773, + "y": -8.822814846961876 }, "dragging": true } ], "edges": [ { - "source": "LINSPACE-a3ec55cd-d572-437a-a823-7a8707fc2099", + "source": "OPEN_KEITHLEY_24XX-097d2560-f5b9-468a-9517-32e89dedecc1", + "sourceHandle": "default", + "target": "LINSPACE-db9bbe29-66a0-4122-ad24-e3c00b1fba28", + "targetHandle": "default", + "id": "reactflow__edge-OPEN_KEITHLEY_24XX-097d2560-f5b9-468a-9517-32e89dedecc1default-LINSPACE-db9bbe29-66a0-4122-ad24-e3c00b1fba28default" + }, + { + "source": "LINSPACE-db9bbe29-66a0-4122-ad24-e3c00b1fba28", "sourceHandle": "default", - "target": "KEITHLEY2400-33053219-7ec1-40d0-9cb9-5d337294a01e", + "target": "IV_SWEEP-41060d63-89ff-46f2-914b-944a11d24ed7", "targetHandle": "default", - "id": "reactflow__edge-LINSPACE-a3ec55cd-d572-437a-a823-7a8707fc2099default-KEITHLEY2400-33053219-7ec1-40d0-9cb9-5d337294a01edefault" + "id": "reactflow__edge-LINSPACE-db9bbe29-66a0-4122-ad24-e3c00b1fba28default-IV_SWEEP-41060d63-89ff-46f2-914b-944a11d24ed7default" }, { - "source": "KEITHLEY2400-33053219-7ec1-40d0-9cb9-5d337294a01e", + "source": "IV_SWEEP-41060d63-89ff-46f2-914b-944a11d24ed7", "sourceHandle": "default", - "target": "LINE-5ea158cf-c235-4bff-bec2-0714507a1bf0", + "target": "SCATTER-fee34277-0702-4342-af77-37c9d68701c6", "targetHandle": "default", - "id": "reactflow__edge-KEITHLEY2400-33053219-7ec1-40d0-9cb9-5d337294a01edefault-LINE-5ea158cf-c235-4bff-bec2-0714507a1bf0default" + "id": "reactflow__edge-IV_SWEEP-41060d63-89ff-46f2-914b-944a11d24ed7default-SCATTER-fee34277-0702-4342-af77-37c9d68701c6default" } ], "viewport": { - "x": 621.1813795484834, - "y": 324.9597014372874, - "zoom": 0.6891413136990774 + "x": 255.10425070720453, + "y": 317.88940714410813, + "zoom": 0.5 } } } \ No newline at end of file diff --git a/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/OPEN_KEITHLEY_24XX.md b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/OPEN_KEITHLEY_24XX.md new file mode 100644 index 0000000000..ba9d4f78f2 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/OPEN_KEITHLEY_24XX.md @@ -0,0 +1,57 @@ + +[//]: # (Custom component imports) + +import DocString from '@site/src/components/DocString'; +import PythonCode from '@site/src/components/PythonCode'; +import AppDisplay from '@site/src/components/AppDisplay'; +import SectionBreak from '@site/src/components/SectionBreak'; +import AppendixSection from '@site/src/components/AppendixSection'; + +[//]: # (Docstring) + +import DocstringSource from '!!raw-loader!./a1-[autogen]/docstring.txt'; +import PythonSource from '!!raw-loader!./a1-[autogen]/python_code.txt'; + +{DocstringSource} +{PythonSource} + + + + + +[//]: # (Examples) + +## Examples + +import Example1 from './examples/EX1/example.md'; +import App1 from '!!raw-loader!./examples/EX1/app.json'; + + + + + {App1} + + + + + + + + +[//]: # (Appendix) + +import Notes from './appendix/notes.md'; +import Hardware from './appendix/hardware.md'; +import Media from './appendix/media.md'; + +## Appendix + + + + + + diff --git a/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/a1-[autogen]/docstring.txt b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/a1-[autogen]/docstring.txt new file mode 100644 index 0000000000..09000ede9f --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/a1-[autogen]/docstring.txt @@ -0,0 +1,10 @@ +The OPEN_KEITHLEY_24XX node opens a connection with the Keithley 2400 source meter. + + Parameters + ---------- + device: Serial + The connected serial device corresponding to the Keithley 2400 source meter. + + Returns + ------- + None diff --git a/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/a1-[autogen]/python_code.txt b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/a1-[autogen]/python_code.txt new file mode 100644 index 0000000000..c32487e867 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/a1-[autogen]/python_code.txt @@ -0,0 +1,24 @@ +import serial +from typing import Optional +from flojoy import SerialDevice, flojoy, DataContainer +from flojoy.connection_manager import DeviceConnectionManager + + +@flojoy(deps={"pyserial": "3.5"}) +def OPEN_KEITHLEY_24XX( + device: SerialDevice, baudrate: int = 9600 +) -> Optional[DataContainer]: + + + ser = serial.Serial( + port=device.get_port(), + baudrate=baudrate, + bytesize=serial.EIGHTBITS, + parity=serial.PARITY_NONE, + stopbits=serial.STOPBITS_ONE, + timeout=1, + ) + + DeviceConnectionManager.register_connection(device, ser) + + return None diff --git a/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/appendix/hardware.md b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/appendix/hardware.md new file mode 100644 index 0000000000..7f78a555c4 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/appendix/hardware.md @@ -0,0 +1 @@ +This node does not require any peripheral hardware to operate. Please see INSTRUMENTS for nodes that interact with the physical world through connected hardware. \ No newline at end of file diff --git a/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/appendix/media.md b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/appendix/media.md new file mode 100644 index 0000000000..8bcee9be90 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/appendix/media.md @@ -0,0 +1 @@ +No supporting screenshots, photos, or videos have been added to the media.md file for this node. \ No newline at end of file diff --git a/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/appendix/notes.md b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/appendix/notes.md new file mode 100644 index 0000000000..04aded2ec9 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/appendix/notes.md @@ -0,0 +1 @@ +No theory or technical notes have been contributed for this node yet. \ No newline at end of file diff --git a/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/examples/EX1/app.json b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/examples/EX1/app.json new file mode 100644 index 0000000000..6784b06926 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/examples/EX1/app.json @@ -0,0 +1,266 @@ +{ + "rfInstance": { + "nodes": [ + { + "width": 192, + "height": 192, + "id": "OPEN_KEITHLEY_24XX-097d2560-f5b9-468a-9517-32e89dedecc1", + "type": "IO", + "data": { + "id": "OPEN_KEITHLEY_24XX-097d2560-f5b9-468a-9517-32e89dedecc1", + "label": "OPEN KEITHLEY 24XX", + "func": "OPEN_KEITHLEY_24XX", + "type": "IO", + "ctrls": { + "device": { + "type": "SerialDevice", + "default": null, + "desc": null, + "overload": null, + "functionName": "OPEN_KEITHLEY_24XX", + "param": "device", + "value": "" + }, + "baudrate": { + "type": "int", + "default": 9600, + "desc": null, + "overload": null, + "functionName": "OPEN_KEITHLEY_24XX", + "param": "baudrate", + "value": 9600 + } + }, + "initCtrls": {}, + "outputs": [ + { + "name": "default", + "id": "default", + "type": "Any", + "desc": null + } + ], + "pip_dependencies": [ + { + "name": "pyserial", + "v": "3.5" + } + ], + "path": "IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/OPEN_KEITHLEY_24XX.py", + "selected": false + }, + "position": { + "x": -140.35863305434796, + "y": 1.9088042829506549 + }, + "selected": false, + "positionAbsolute": { + "x": -140.35863305434796, + "y": 1.9088042829506549 + }, + "dragging": true + }, + { + "width": 192, + "height": 192, + "id": "IV_SWEEP-41060d63-89ff-46f2-914b-944a11d24ed7", + "type": "IO", + "data": { + "id": "IV_SWEEP-41060d63-89ff-46f2-914b-944a11d24ed7", + "label": "IV SWEEP", + "func": "IV_SWEEP", + "type": "IO", + "ctrls": { + "connection": { + "type": "SerialConnection", + "default": null, + "desc": null, + "overload": null, + "functionName": "IV_SWEEP", + "param": "connection", + "value": "" + } + }, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedPair|Vector", + "multiple": false, + "desc": null + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedPair", + "desc": null + } + ], + "pip_dependencies": [ + { + "name": "pyserial", + "v": "3.5" + } + ], + "path": "IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/IV_SWEEP.py", + "selected": false + }, + "position": { + "x": 511.6912461233678, + "y": 5.980216390951398 + }, + "selected": false, + "positionAbsolute": { + "x": 511.6912461233678, + "y": 5.980216390951398 + }, + "dragging": true + }, + { + "width": 208, + "height": 96, + "id": "LINSPACE-db9bbe29-66a0-4122-ad24-e3c00b1fba28", + "type": "GENERATORS", + "data": { + "id": "LINSPACE-db9bbe29-66a0-4122-ad24-e3c00b1fba28", + "label": "LINSPACE", + "func": "LINSPACE", + "type": "GENERATORS", + "ctrls": { + "start": { + "type": "float", + "default": 10, + "desc": "The start point of the data.", + "overload": null, + "functionName": "LINSPACE", + "param": "start", + "value": 10 + }, + "end": { + "type": "float", + "default": 0, + "desc": "The end point of the data.", + "overload": null, + "functionName": "LINSPACE", + "param": "end", + "value": 0 + }, + "step": { + "type": "int", + "default": 1000, + "desc": "The number of points in the vector.", + "overload": null, + "functionName": "LINSPACE", + "param": "step", + "value": 10 + } + }, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "Vector|OrderedPair", + "multiple": false, + "desc": "Optional input in case LINSPACE is used in a loop. Not used." + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "Vector", + "desc": "v: the vector between 'start' and 'end' with a 'step' number of points." + } + ], + "path": "GENERATORS/SIMULATIONS/LINSPACE/LINSPACE.py", + "selected": false + }, + "position": { + "x": 192.47824090745922, + "y": 49.8416165273091 + }, + "selected": false, + "positionAbsolute": { + "x": 192.47824090745922, + "y": 49.8416165273091 + }, + "dragging": true + }, + { + "width": 225, + "height": 226, + "id": "SCATTER-fee34277-0702-4342-af77-37c9d68701c6", + "type": "VISUALIZERS", + "data": { + "id": "SCATTER-fee34277-0702-4342-af77-37c9d68701c6", + "label": "SCATTER", + "func": "SCATTER", + "type": "VISUALIZERS", + "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 Scatter visualization" + } + ], + "path": "VISUALIZERS/PLOTLY/SCATTER/SCATTER.py", + "selected": false + }, + "position": { + "x": 822.0611229804773, + "y": -8.822814846961876 + }, + "selected": false, + "positionAbsolute": { + "x": 822.0611229804773, + "y": -8.822814846961876 + }, + "dragging": true + } + ], + "edges": [ + { + "source": "OPEN_KEITHLEY_24XX-097d2560-f5b9-468a-9517-32e89dedecc1", + "sourceHandle": "default", + "target": "LINSPACE-db9bbe29-66a0-4122-ad24-e3c00b1fba28", + "targetHandle": "default", + "id": "reactflow__edge-OPEN_KEITHLEY_24XX-097d2560-f5b9-468a-9517-32e89dedecc1default-LINSPACE-db9bbe29-66a0-4122-ad24-e3c00b1fba28default" + }, + { + "source": "LINSPACE-db9bbe29-66a0-4122-ad24-e3c00b1fba28", + "sourceHandle": "default", + "target": "IV_SWEEP-41060d63-89ff-46f2-914b-944a11d24ed7", + "targetHandle": "default", + "id": "reactflow__edge-LINSPACE-db9bbe29-66a0-4122-ad24-e3c00b1fba28default-IV_SWEEP-41060d63-89ff-46f2-914b-944a11d24ed7default" + }, + { + "source": "IV_SWEEP-41060d63-89ff-46f2-914b-944a11d24ed7", + "sourceHandle": "default", + "target": "SCATTER-fee34277-0702-4342-af77-37c9d68701c6", + "targetHandle": "default", + "id": "reactflow__edge-IV_SWEEP-41060d63-89ff-46f2-914b-944a11d24ed7default-SCATTER-fee34277-0702-4342-af77-37c9d68701c6default" + } + ], + "viewport": { + "x": 255.10425070720453, + "y": 317.88940714410813, + "zoom": 0.5 + } + } +} \ No newline at end of file diff --git a/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/examples/EX1/example.md b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/examples/EX1/example.md new file mode 100644 index 0000000000..00d085c787 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/examples/EX1/example.md @@ -0,0 +1,25 @@ +--- +title: OPEN_KEITHLEY_24XX +description: In this example, we demonstrate how to record an I"-"V curve using Flojoy, a Keithley 2400 source meter, and a computer. +keyword: [Python, Instrument, Keithley 2400 control, Python instrument integration, Measurement and analysis, Python"-"based instrument control, Keithley instrument control, Enhance measurements with Python, Python"-"based measurement techniques, Streamline instrument usage, Accurate data analysis,Python integration with Keithley 2400] +image: https://raw.githubusercontent.com/flojoy-ai/docs/main/docs/nodes/INSTRUMENTS/KEITHLEY/KEITHLEY2/examples/EX1/output.jpeg +--- + +In this example, we demonstrate how to record an I-V curve using Flojoy, a Keithley2400 source meter, and a computer. Fist you need to connect the Keithley2400 sourcemeter to the computer with a serial communication cable. Then, connect your device (Solar cell in this example) to the sourcemeter. After that you can prepare your flojoy app: + +The [`LINSPACE`](https://github.com/flojoy-io/nodes/blob/main/GENERATORS/SIMULATIONS/LINSPACE/LINSPACE.py) node defines the voltage range sent to the electronic device. The user defines the voltage range by setting these parameters with Numeric Input: + +- LINSPACE START: Define your first Voltage. +- LINSPACE END: Define your last Voltage. +- LINSPACE STEP: Define the number of voltages between the first and the last one. + +The [`KEITHLEY2400`](https://github.com/flojoy-io/nodes/blob/main/INSTRUMENTS/KEITHLEY/KEITHLEY2400/KEITHLEY2400.py) node will communicate with the source meter by serial communication to send voltages and measure currents from the device. + +The connection must first be opened using the [`OPEN_KEITHLEY_24XX`](https://github.com/flojoy-io/nodes/blob/main/INSTRUMENTS/KEITHLEY/KEITHLEY2400/KEITHLEY2400.py) node, which has two communication parameters set by the user after connecting the Keithley2400 to their computer: + +- DEVICE: Select the serial device that corresponds to the Keithley2400. +- BAUDRATE: Define the Baud rate of your communication protocol (the default is 9600, the value has to correspond to the Instrument settings). + +The [`LINE`](https://github.com/flojoy-io/nodes/blob/main/VISUALIZERS/PLOTLY/LINE/LINE.py) node will display the I-V curve by plotting the currents received from the device as a function of the voltages transmitted to the device. + +When the setup is ready, and the parameters above are well defined, the experiment can be started by turning on the source meter and clicking the PLAY button. diff --git a/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/SERIAL_SINGLE_MEASUREMENT/a1-[autogen]/python_code.txt b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/SERIAL_SINGLE_MEASUREMENT/a1-[autogen]/python_code.txt index 7bb19b0d24..0b3456111a 100644 --- a/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/SERIAL_SINGLE_MEASUREMENT/a1-[autogen]/python_code.txt +++ b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/SERIAL_SINGLE_MEASUREMENT/a1-[autogen]/python_code.txt @@ -1,4 +1,4 @@ -from flojoy import flojoy, OrderedPair +from flojoy import SerialDevice, flojoy, OrderedPair from typing import Optional import serial import numpy as np @@ -6,13 +6,13 @@ import numpy as np @flojoy(deps={"pyserial": "3.5"}) def SERIAL_SINGLE_MEASUREMENT( + device: SerialDevice, default: Optional[OrderedPair] = None, - comport: str = "/dev/ttyUSB0", baudrate: int = 9600, ) -> OrderedPair: - ser = serial.Serial(comport, timeout=1, baudrate=baudrate) + ser = serial.Serial(device.port, timeout=1, baudrate=baudrate) s = "" while s == "": s = ser.readline().decode() diff --git a/docs/nodes/LOADERS/LOCAL_FILE_SYSTEM/LOCAL_FILE/a1-[autogen]/docstring.txt b/docs/nodes/LOADERS/LOCAL_FILE_SYSTEM/LOCAL_FILE/a1-[autogen]/docstring.txt index 7634cca412..b4e8a6d8dd 100644 --- a/docs/nodes/LOADERS/LOCAL_FILE_SYSTEM/LOCAL_FILE/a1-[autogen]/docstring.txt +++ b/docs/nodes/LOADERS/LOCAL_FILE_SYSTEM/LOCAL_FILE/a1-[autogen]/docstring.txt @@ -3,7 +3,9 @@ The LOCAL_FILE node loads a local file of a different type and converts it to a Parameters ---------- file_path : str - Path to the file to be loaded. + The path to the file to be loaded. This can be either an absolute path or + a path relative to the "nodes" directory. + default : Optional[TextBlob] If this input node is connected, the file name will be taken from the output of the connected node. @@ -19,4 +21,5 @@ The LOCAL_FILE node loads a local file of a different type and converts it to a ------- Image | DataFrame Image for file_type 'image'. - DataFrame for file_type 'json', 'csv', 'excel', and 'xml'. + Grayscale from file_type 'Grayscale'. + DataFrame for file_type 'json', 'csv'. diff --git a/docs/nodes/LOADERS/LOCAL_FILE_SYSTEM/LOCAL_FILE/a1-[autogen]/python_code.txt b/docs/nodes/LOADERS/LOCAL_FILE_SYSTEM/LOCAL_FILE/a1-[autogen]/python_code.txt index 6c3e713acc..a7ae3a47c7 100644 --- a/docs/nodes/LOADERS/LOCAL_FILE_SYSTEM/LOCAL_FILE/a1-[autogen]/python_code.txt +++ b/docs/nodes/LOADERS/LOCAL_FILE_SYSTEM/LOCAL_FILE/a1-[autogen]/python_code.txt @@ -2,36 +2,37 @@ from flojoy import flojoy, Image, DataFrame, Grayscale, TextBlob from typing import Literal, Optional import numpy as np from PIL import Image as PIL_Image -from os import path +import os import pandas as pd def get_file_path(file_path: str, default_path: str | None = None): - f_path = path.abspath(file_path) if file_path != "" else default_path + f_path = file_path if file_path != "" else default_path if not f_path: raise ValueError( "The file path of the input file is missing. " "Please provide a input TextBlob or a provide `file_path` with a value!" ) + if not os.path.isabs(f_path): + path_to_nodes = __file__[: __file__.rfind("nodes") + 5] + return os.path.abspath(os.path.join(path_to_nodes, f_path)) return f_path @flojoy( deps={ - "xlrd": "2.0.1", - "lxml": "4.9.2", - "openpyxl": "3.0.10", "scikit-image": "0.21.0", } ) def LOCAL_FILE( - file_path: str = None, + file_path: str | None = None, default: Optional[TextBlob] = None, - file_type: Literal["Image", "Grayscale", "JSON", "CSV", "Excel", "XML"] = "Image", -) -> Image | DataFrame: + file_type: Literal["Image", "Grayscale", "JSON", "CSV"] = "Image", +) -> Image | DataFrame | Grayscale: - default_image_path = path.join( - path.dirname(path.abspath(__file__)), + + default_image_path = os.path.join( + os.path.dirname(os.path.abspath(__file__)), "assets", "astronaut.png", ) @@ -70,11 +71,12 @@ def LOCAL_FILE( file_path = get_file_path(file_path) df = pd.read_json(file_path) return DataFrame(df=df) - case "XML": - file_path = get_file_path(file_path) - df = pd.read_xml(file_path) - return DataFrame(df=df) - case "Excel": - file_path = get_file_path(file_path) - df = pd.read_excel(file_path) - return DataFrame(df=df) + # TODO: we might add support for following file types later + # case "XML": + # file_path = get_file_path(file_path) + # df = pd.read_xml(file_path) + # return DataFrame(df=df) + # case "Excel": + # file_path = get_file_path(file_path) + # df = pd.read_excel(file_path) + # return DataFrame(df=df) diff --git a/nodeSidebar.json b/nodeSidebar.json index f5a8cd0321..32a78f070c 100644 --- a/nodeSidebar.json +++ b/nodeSidebar.json @@ -195,6 +195,7 @@ ], "I/O > SourceMeters": [ "nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/IV_SWEEP", + "nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/OPEN_KEITHLEY_24XX/OPEN_KEITHLEY_24XX", "nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/SET_VOLTAGE/SET_VOLTAGE" ], "NumPy > Linalg": [