diff --git a/docs/nodes/AI_ML/OPENAI/DALLE_IMAGE_GENERATOR/DALLE_IMAGE_GENERATOR.md b/docs/nodes/AI_ML/OPENAI/DALLE_IMAGE_GENERATOR/DALLE_IMAGE_GENERATOR.md new file mode 100644 index 0000000000..47d9af9a04 --- /dev/null +++ b/docs/nodes/AI_ML/OPENAI/DALLE_IMAGE_GENERATOR/DALLE_IMAGE_GENERATOR.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/AI_ML/OPENAI/DALLE_IMAGE_GENERATOR/a1-[autogen]/docstring.txt b/docs/nodes/AI_ML/OPENAI/DALLE_IMAGE_GENERATOR/a1-[autogen]/docstring.txt new file mode 100644 index 0000000000..c00f058fdb --- /dev/null +++ b/docs/nodes/AI_ML/OPENAI/DALLE_IMAGE_GENERATOR/a1-[autogen]/docstring.txt @@ -0,0 +1,14 @@ + +The DALLE_IMAGE_GENERATOR node takes a prompt and generates an image +using OpenAI's DALL-E model. +The prompt should be a sentence describing the image you want to generate. +The image will be returned as a DataContainer with the type 'image'. + +Parameters +---------- +prompt: string + A sentence describing the image you want to generate. +width: int + The width of the generated image. +height: int + The height of the generated image. diff --git a/docs/nodes/AI_ML/OPENAI/DALLE_IMAGE_GENERATOR/a1-[autogen]/python_code.txt b/docs/nodes/AI_ML/OPENAI/DALLE_IMAGE_GENERATOR/a1-[autogen]/python_code.txt new file mode 100644 index 0000000000..ef581246d4 --- /dev/null +++ b/docs/nodes/AI_ML/OPENAI/DALLE_IMAGE_GENERATOR/a1-[autogen]/python_code.txt @@ -0,0 +1,66 @@ +import numpy as np +from flojoy import flojoy, Image, run_in_venv +import base64 +from io import BytesIO +import os +import time + +API_RETRY_ATTEMPTS = 5 +API_RETRY_INTERVAL_IN_SECONDS = 1 + + +@flojoy +@run_in_venv(pip_dependencies=["openai==0.27.8", "Pillow==10.0.0", "requests==2.28.1"]) +def DALLE_IMAGE_GENERATOR( + prompt: str, + width: int = 1024, + height: int = 1024, +) -> Image: + + import openai + from PIL import Image as PilImage + + api_key = os.environ.get("OPENAI_API_KEY") + if not api_key: + raise Exception("OPENAI_API_KEY environment variable not set") + + openai.api_key = api_key + + for i in range(API_RETRY_ATTEMPTS): + try: + result = openai.Image.create( + prompt=prompt, n=1, size=f"{width}x{height}", response_format="b64_json" + ) + print(f"No error in attempt {i} of generating image") + break + except openai.error.RateLimitError: + if i > API_RETRY_ATTEMPTS: + raise Exception("Rate limit error. Max retries exceeded.") + + print( + f"Rate limit error, retrying in {API_RETRY_INTERVAL_IN_SECONDS} seconds" + ) + time.sleep(API_RETRY_INTERVAL_IN_SECONDS) + + if not result.data: + raise Exception("No image data in result") + + base64_content = result.get("data")[0].get("b64_json") + image_data = base64.b64decode(base64_content) + img = PilImage.open(BytesIO(image_data)) + + img_array = np.asarray(img) + red_channel = img_array[:, :, 0] + green_channel = img_array[:, :, 1] + blue_channel = img_array[:, :, 2] + + alpha_channel = None + if img_array.shape[2] == 4: + alpha_channel = img_array[:, :, 3] + + return Image( + r=red_channel, + g=green_channel, + b=blue_channel, + a=alpha_channel, + ) diff --git a/docs/nodes/AI_ML/OPENAI/DALLE_IMAGE_GENERATOR/appendix/hardware.md b/docs/nodes/AI_ML/OPENAI/DALLE_IMAGE_GENERATOR/appendix/hardware.md new file mode 100644 index 0000000000..7f78a555c4 --- /dev/null +++ b/docs/nodes/AI_ML/OPENAI/DALLE_IMAGE_GENERATOR/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/AI_ML/OPENAI/DALLE_IMAGE_GENERATOR/appendix/media.md b/docs/nodes/AI_ML/OPENAI/DALLE_IMAGE_GENERATOR/appendix/media.md new file mode 100644 index 0000000000..8bcee9be90 --- /dev/null +++ b/docs/nodes/AI_ML/OPENAI/DALLE_IMAGE_GENERATOR/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/AI_ML/OPENAI/DALLE_IMAGE_GENERATOR/appendix/notes.md b/docs/nodes/AI_ML/OPENAI/DALLE_IMAGE_GENERATOR/appendix/notes.md new file mode 100644 index 0000000000..04aded2ec9 --- /dev/null +++ b/docs/nodes/AI_ML/OPENAI/DALLE_IMAGE_GENERATOR/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/AI_ML/OPENAI/DALLE_IMAGE_GENERATOR/examples/EX1/example.md b/docs/nodes/AI_ML/OPENAI/DALLE_IMAGE_GENERATOR/examples/EX1/example.md new file mode 100644 index 0000000000..a4d00f0f98 --- /dev/null +++ b/docs/nodes/AI_ML/OPENAI/DALLE_IMAGE_GENERATOR/examples/EX1/example.md @@ -0,0 +1,6 @@ +This app uses the DALL-E node to generate images from text. +Based on the users input, the node will generate an image and pass it to the next node. +The input text is defined in the node's form, for this app we are using the following text: +``` +A cute baby sea otter +``` \ No newline at end of file diff --git a/docs/nodes/AI_ML/OPENAI/JSON_EXTRACTOR/JSON_EXTRACTOR.md b/docs/nodes/AI_ML/OPENAI/JSON_EXTRACTOR/JSON_EXTRACTOR.md new file mode 100644 index 0000000000..898b41b284 --- /dev/null +++ b/docs/nodes/AI_ML/OPENAI/JSON_EXTRACTOR/JSON_EXTRACTOR.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/AI_ML/OPENAI/JSON_EXTRACTOR/a1-[autogen]/docstring.txt b/docs/nodes/AI_ML/OPENAI/JSON_EXTRACTOR/a1-[autogen]/docstring.txt new file mode 100644 index 0000000000..4e60c232de --- /dev/null +++ b/docs/nodes/AI_ML/OPENAI/JSON_EXTRACTOR/a1-[autogen]/docstring.txt @@ -0,0 +1,9 @@ + +The JSON_EXTRACTOR node extract specific properties information from a text using JSON schema. + +Parameters +---------- +properties: string + Comma separated list of properties to extract. Example: "name,age,location" +prompt: string + Text to extract information from. Example: "I'm John, I am 30 years old and I live in New York." diff --git a/docs/nodes/AI_ML/OPENAI/JSON_EXTRACTOR/a1-[autogen]/python_code.txt b/docs/nodes/AI_ML/OPENAI/JSON_EXTRACTOR/a1-[autogen]/python_code.txt new file mode 100644 index 0000000000..b259a7056c --- /dev/null +++ b/docs/nodes/AI_ML/OPENAI/JSON_EXTRACTOR/a1-[autogen]/python_code.txt @@ -0,0 +1,73 @@ +from flojoy import flojoy, DataFrame as FlojoyDataFrame, run_in_venv +import os +import json +from copy import deepcopy +import time + + +ACCEPTED_SCHEMA_FORMATS = [".json"] + +BASE_SCHEMA = { + "name": "information_extraction", + "description": "Extracts the information as JSON.", + "parameters": {"type": "object", "properties": {}, "required": []}, +} + +API_RETRY_ATTEMPTS = 5 +API_RETRY_INTERVAL_IN_SECONDS = 1 + + +@flojoy +@run_in_venv(pip_dependencies=["openai==0.27.8", "pandas==2.0.2"]) +def JSON_EXTRACTOR( + properties: list[str], + prompt: str, +) -> FlojoyDataFrame: + + import openai + import pandas as pd + + api_key = os.environ.get("OPENAI_API_KEY") + if not api_key: + raise Exception("OPENAI_API_KEY environment variable not set") + openai.api_key = api_key + + if not properties: + raise Exception("No properties found to extract.") + + schema = deepcopy(BASE_SCHEMA) + for property in properties: + schema["parameters"]["properties"][property] = { + "title": property, + "type": "string", + } + schema["parameters"]["required"].append(property) + + for i in range(API_RETRY_ATTEMPTS): + try: + response = openai.ChatCompletion.create( + model="gpt-3.5-turbo-0613", + messages=[ + {"role": "user", "content": prompt}, + ], + temperature=0, + functions=[schema], + function_call={"name": schema["name"]}, + ) + print(f"No error in attempt {i} of extraction.") + break + except openai.error.RateLimitError: + if i > API_RETRY_ATTEMPTS: + raise Exception("Rate limit error. Max retries exceeded.") + + print( + f"Rate limit error, retrying in {API_RETRY_INTERVAL_IN_SECONDS} seconds" + ) + time.sleep(API_RETRY_INTERVAL_IN_SECONDS) + + if not response.choices: + raise Exception("No extraction choices found in response.") + + data = json.loads(response.choices[0].message.function_call.arguments) + df = pd.DataFrame(data=[data]) + return FlojoyDataFrame(df=df) diff --git a/docs/nodes/AI_ML/OPENAI/JSON_EXTRACTOR/appendix/hardware.md b/docs/nodes/AI_ML/OPENAI/JSON_EXTRACTOR/appendix/hardware.md new file mode 100644 index 0000000000..7f78a555c4 --- /dev/null +++ b/docs/nodes/AI_ML/OPENAI/JSON_EXTRACTOR/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/AI_ML/OPENAI/JSON_EXTRACTOR/appendix/media.md b/docs/nodes/AI_ML/OPENAI/JSON_EXTRACTOR/appendix/media.md new file mode 100644 index 0000000000..8bcee9be90 --- /dev/null +++ b/docs/nodes/AI_ML/OPENAI/JSON_EXTRACTOR/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/AI_ML/OPENAI/JSON_EXTRACTOR/appendix/notes.md b/docs/nodes/AI_ML/OPENAI/JSON_EXTRACTOR/appendix/notes.md new file mode 100644 index 0000000000..04aded2ec9 --- /dev/null +++ b/docs/nodes/AI_ML/OPENAI/JSON_EXTRACTOR/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/AI_ML/OPENAI/JSON_EXTRACTOR/examples/EX1/example.md b/docs/nodes/AI_ML/OPENAI/JSON_EXTRACTOR/examples/EX1/example.md new file mode 100644 index 0000000000..504d672ed1 --- /dev/null +++ b/docs/nodes/AI_ML/OPENAI/JSON_EXTRACTOR/examples/EX1/example.md @@ -0,0 +1,4 @@ +This example app uses the JSON_EXTRACTOR node for extracting estructured data (as JSON) from unstructured text. +In this example we are trying to extract 2 properties (price and name) from the following text: +**Headset Gamer Bluetooth MJ23 - $100** +The properties and text are defined in the node's form. \ No newline at end of file diff --git a/docs/nodes/AI_ML/OPENAI/WHISPER_SPEECH_TO_TEXT/WHISPER_SPEECH_TO_TEXT.md b/docs/nodes/AI_ML/OPENAI/WHISPER_SPEECH_TO_TEXT/WHISPER_SPEECH_TO_TEXT.md new file mode 100644 index 0000000000..580ff08964 --- /dev/null +++ b/docs/nodes/AI_ML/OPENAI/WHISPER_SPEECH_TO_TEXT/WHISPER_SPEECH_TO_TEXT.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/AI_ML/OPENAI/WHISPER_SPEECH_TO_TEXT/a1-[autogen]/docstring.txt b/docs/nodes/AI_ML/OPENAI/WHISPER_SPEECH_TO_TEXT/a1-[autogen]/docstring.txt new file mode 100644 index 0000000000..e7c4baae33 --- /dev/null +++ b/docs/nodes/AI_ML/OPENAI/WHISPER_SPEECH_TO_TEXT/a1-[autogen]/docstring.txt @@ -0,0 +1,7 @@ + +the node WHISPER_SPEECH_TO_TEXT uses OpenAI whisper transcription model to convert audio to text. The audio can be provided as a file path or as bytes from a previous node. The previous node value has priority over the file path. + +Parameters: +----------- +file_path: string + Path to the audio file to be transcribed. Only mp3 format is supported. diff --git a/docs/nodes/AI_ML/OPENAI/WHISPER_SPEECH_TO_TEXT/a1-[autogen]/python_code.txt b/docs/nodes/AI_ML/OPENAI/WHISPER_SPEECH_TO_TEXT/a1-[autogen]/python_code.txt new file mode 100644 index 0000000000..c874af5d02 --- /dev/null +++ b/docs/nodes/AI_ML/OPENAI/WHISPER_SPEECH_TO_TEXT/a1-[autogen]/python_code.txt @@ -0,0 +1,68 @@ +from flojoy import flojoy, Bytes, run_in_venv, TextBlob +from typing import Optional +import os +from pathlib import Path +import time +from tempfile import NamedTemporaryFile + + +ACCEPTED_AUDIO_FORMATS = ["mp3", "wav"] +API_RETRY_ATTEMPTS = 5 +API_RETRY_INTERVAL_IN_SECONDS = 1 + + +@flojoy +@run_in_venv(pip_dependencies=["openai==0.27.8", "pandas==2.0.2"]) +def WHISPER_SPEECH_TO_TEXT( + default: Optional[Bytes] = None, file_path: Optional[str] = None +) -> TextBlob: + + import openai + import pandas as pd + + api_key = os.environ.get("OPENAI_API_KEY") + if not api_key: + raise Exception("OPENAI_API_KEY environment variable not set") + + openai.api_key = api_key + model = "whisper-1" + f = None + if default and isinstance(getattr(default, "b"), bytes): + f = NamedTemporaryFile(suffix=".mp3") + f.write(default.bytes) + f.seek(0) + file_path = f.name + + elif file_path is None: + raise ValueError("file_path parameter is missing!") + + file_format = file_path.split(".")[-1] + if file_format not in ACCEPTED_AUDIO_FORMATS: + raise ValueError( + f"file format {file_format} is not supported. Supported formats are {ACCEPTED_AUDIO_FORMATS}" + ) + + file_path = Path(file_path) + if not file_path.exists(): + raise ValueError(f"file {file_path} does not exist!") + + with open(file_path, "rb") as f: + for i in range(API_RETRY_ATTEMPTS): + try: + transcript = openai.Audio.translate(model, f) + print(f"No error in attempt {i} of transcription") + break + except openai.error.RateLimitError: + if i > API_RETRY_ATTEMPTS: + raise Exception("Rate limit error. Max retries exceeded.") + + print( + f"Rate limit error, retrying in {API_RETRY_INTERVAL_IN_SECONDS} seconds" + ) + time.sleep(API_RETRY_INTERVAL_IN_SECONDS) + + if f is not None: + f.close() + + transcript_text = transcript.get("text") + return TextBlob(text_blob=transcript_text) diff --git a/docs/nodes/AI_ML/OPENAI/WHISPER_SPEECH_TO_TEXT/appendix/hardware.md b/docs/nodes/AI_ML/OPENAI/WHISPER_SPEECH_TO_TEXT/appendix/hardware.md new file mode 100644 index 0000000000..7f78a555c4 --- /dev/null +++ b/docs/nodes/AI_ML/OPENAI/WHISPER_SPEECH_TO_TEXT/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/AI_ML/OPENAI/WHISPER_SPEECH_TO_TEXT/appendix/media.md b/docs/nodes/AI_ML/OPENAI/WHISPER_SPEECH_TO_TEXT/appendix/media.md new file mode 100644 index 0000000000..8bcee9be90 --- /dev/null +++ b/docs/nodes/AI_ML/OPENAI/WHISPER_SPEECH_TO_TEXT/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/AI_ML/OPENAI/WHISPER_SPEECH_TO_TEXT/appendix/notes.md b/docs/nodes/AI_ML/OPENAI/WHISPER_SPEECH_TO_TEXT/appendix/notes.md new file mode 100644 index 0000000000..04aded2ec9 --- /dev/null +++ b/docs/nodes/AI_ML/OPENAI/WHISPER_SPEECH_TO_TEXT/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/AI_ML/OPENAI/WHISPER_SPEECH_TO_TEXT/examples/EX1/example.md b/docs/nodes/AI_ML/OPENAI/WHISPER_SPEECH_TO_TEXT/examples/EX1/example.md new file mode 100644 index 0000000000..08e784da89 --- /dev/null +++ b/docs/nodes/AI_ML/OPENAI/WHISPER_SPEECH_TO_TEXT/examples/EX1/example.md @@ -0,0 +1,2 @@ +This app runs a speech to text task using OpenAI API and local mp3 file. +The local file is loaded and the content is sent to OpenAI API for processing using the Whisper model. \ No newline at end of file diff --git a/docs/nodes/GENERATORS/SIMULATIONS/CONSTANT/a1-[autogen]/python_code.txt b/docs/nodes/GENERATORS/SIMULATIONS/CONSTANT/a1-[autogen]/python_code.txt index 5e69a92230..ce889fa01d 100644 --- a/docs/nodes/GENERATORS/SIMULATIONS/CONSTANT/a1-[autogen]/python_code.txt +++ b/docs/nodes/GENERATORS/SIMULATIONS/CONSTANT/a1-[autogen]/python_code.txt @@ -1,4 +1,4 @@ -import numpy as np +from numpy import arange, full from flojoy import flojoy, Vector, OrderedPair, Scalar from typing import Optional, Literal @@ -12,14 +12,14 @@ def CONSTANT( ) -> OrderedPair | Vector | Scalar: - x = np.arange(0, step, 1) + x = arange(0, step, 1) if default: match default: case OrderedPair(): x = default.y case Vector(): x = default.v - y = np.full(len(x), constant) + y = full(len(x), constant) match dc_type: case "OrderedPair": diff --git a/docs/nodes/GENERATORS/SIMULATIONS/SECOND_ORDER_SYSTEM/a1-[autogen]/python_code.txt b/docs/nodes/GENERATORS/SIMULATIONS/SECOND_ORDER_SYSTEM/a1-[autogen]/python_code.txt index 6d86d7189a..ea55603af4 100644 --- a/docs/nodes/GENERATORS/SIMULATIONS/SECOND_ORDER_SYSTEM/a1-[autogen]/python_code.txt +++ b/docs/nodes/GENERATORS/SIMULATIONS/SECOND_ORDER_SYSTEM/a1-[autogen]/python_code.txt @@ -1,4 +1,4 @@ -import numpy as np +from numpy import exp, ndarray, insert, zeros from flojoy import flojoy, OrderedPair, DefaultParams, SmallMemory, Vector, Scalar @@ -21,8 +21,8 @@ def SECOND_ORDER_SYSTEM( node_id = default_params.node_id # ... and now some helper functions - x1 = np.exp(-1.0 / d1) if d1 > 0 else 0.0 - x2 = np.exp(-1.0 / d2) if d2 > 0 else 0.0 + x1 = exp(-1.0 / d1) if d1 > 0 else 0.0 + x2 = exp(-1.0 / d2) if d2 > 0 else 0.0 ac = (1.0 - x1) * (1.0 - x2) bpd = x1 + x2 bd = x1 * x2 @@ -32,7 +32,7 @@ def SECOND_ORDER_SYSTEM( data = SmallMemory().read_memory(node_id, memory_key) if data is None: initialize = True - elif type(data) == np.ndarray: + elif type(data) == ndarray: initialize = False else: raise TypeError(f"Error loading object from REDIS. Type: {type(data)}") @@ -43,14 +43,14 @@ def SECOND_ORDER_SYSTEM( # index. However, for visualization and external access, # it makes the most sense to have the first time step # as the first index! - y_primes = np.zeros((2, 1)) if initialize else data[::-1] + y_primes = zeros((2, 1)) if initialize else data[::-1] # Using input from controller as v[0].y ... response = ac * def_key + bpd * y_primes[0] - bd * y_primes[1] y_primes[1] = y_primes[0] # prepend the most recent result to the front of the histrory - y_primes = np.insert(y_primes, 0, response) + y_primes = insert(y_primes, 0, response) # We now write to memory, reversing the order ... SmallMemory().write_to_memory(node_id, memory_key, y_primes[::-1]) # ... and return the result! diff --git a/docs/nodes/IO/ANALOG_SENSORS/PRESSURE_SENSORS/FLEXIFORCE_25LB/FLEXIFORCE_25LB.md b/docs/nodes/IO/ANALOG_SENSORS/PRESSURE_SENSORS/FLEXIFORCE_25LB/FLEXIFORCE_25LB.md new file mode 100644 index 0000000000..aa4b491fb7 --- /dev/null +++ b/docs/nodes/IO/ANALOG_SENSORS/PRESSURE_SENSORS/FLEXIFORCE_25LB/FLEXIFORCE_25LB.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/ANALOG_SENSORS/PRESSURE_SENSORS/FLEXIFORCE_25LB/a1-[autogen]/docstring.txt b/docs/nodes/IO/ANALOG_SENSORS/PRESSURE_SENSORS/FLEXIFORCE_25LB/a1-[autogen]/docstring.txt new file mode 100644 index 0000000000..69d69fe340 --- /dev/null +++ b/docs/nodes/IO/ANALOG_SENSORS/PRESSURE_SENSORS/FLEXIFORCE_25LB/a1-[autogen]/docstring.txt @@ -0,0 +1,6 @@ + +The Flexiforce node allows you to convert voltages measured with the Phidget Interface Kit into pressures. +Calibration1 : float + Calibration parameters to convert voltage into pressure. +calibration2 : float + Calibration parameters to convert voltage into pressure. diff --git a/docs/nodes/IO/ANALOG_SENSORS/PRESSURE_SENSORS/FLEXIFORCE_25LB/a1-[autogen]/python_code.txt b/docs/nodes/IO/ANALOG_SENSORS/PRESSURE_SENSORS/FLEXIFORCE_25LB/a1-[autogen]/python_code.txt new file mode 100644 index 0000000000..a121911660 --- /dev/null +++ b/docs/nodes/IO/ANALOG_SENSORS/PRESSURE_SENSORS/FLEXIFORCE_25LB/a1-[autogen]/python_code.txt @@ -0,0 +1,20 @@ +from flojoy import flojoy, OrderedPair, DataContainer +from typing import Optional + + +@flojoy(deps={"pyserial": "3.5"}) +def FLEXIFORCE_25LB( + default: OrderedPair, + calibration1: float = 0.015, + calibration2: float = 0.06, +) -> OrderedPair: + + + # Example of a Calibration to convert Voltage into pressions : + pressions: list[float] = [] + sensor_num = default.x + + pression_i: float = (default.y - calibration1) / calibration2 + pressions.append(pression_i) + + return OrderedPair(sensor_num, pressions) diff --git a/docs/nodes/IO/ANALOG_SENSORS/PRESSURE_SENSORS/FLEXIFORCE_25LB/appendix/hardware.md b/docs/nodes/IO/ANALOG_SENSORS/PRESSURE_SENSORS/FLEXIFORCE_25LB/appendix/hardware.md new file mode 100644 index 0000000000..7f78a555c4 --- /dev/null +++ b/docs/nodes/IO/ANALOG_SENSORS/PRESSURE_SENSORS/FLEXIFORCE_25LB/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/ANALOG_SENSORS/PRESSURE_SENSORS/FLEXIFORCE_25LB/appendix/media.md b/docs/nodes/IO/ANALOG_SENSORS/PRESSURE_SENSORS/FLEXIFORCE_25LB/appendix/media.md new file mode 100644 index 0000000000..8bcee9be90 --- /dev/null +++ b/docs/nodes/IO/ANALOG_SENSORS/PRESSURE_SENSORS/FLEXIFORCE_25LB/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/ANALOG_SENSORS/PRESSURE_SENSORS/FLEXIFORCE_25LB/appendix/notes.md b/docs/nodes/IO/ANALOG_SENSORS/PRESSURE_SENSORS/FLEXIFORCE_25LB/appendix/notes.md new file mode 100644 index 0000000000..04aded2ec9 --- /dev/null +++ b/docs/nodes/IO/ANALOG_SENSORS/PRESSURE_SENSORS/FLEXIFORCE_25LB/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/ANALOG_SENSORS/PRESSURE_SENSORS/FLEXIFORCE_25LB/examples/EX1/app.json b/docs/nodes/IO/ANALOG_SENSORS/PRESSURE_SENSORS/FLEXIFORCE_25LB/examples/EX1/app.json new file mode 100644 index 0000000000..959d99d530 --- /dev/null +++ b/docs/nodes/IO/ANALOG_SENSORS/PRESSURE_SENSORS/FLEXIFORCE_25LB/examples/EX1/app.json @@ -0,0 +1,61 @@ +{ + "rfInstance": { + "nodes": [ + { + "width": 150, + "height": 180, + "id": "FLEXIFORCE_25LB-6833dfdd-3730-4483-a8aa-3c094280f07e", + "type": "IO", + "data": { + "id": "FLEXIFORCE_25LB-6833dfdd-3730-4483-a8aa-3c094280f07e", + "label": "FLEXIFORCE 25LB", + "func": "FLEXIFORCE_25LB", + "type": "IO", + "ctrls": {}, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "Any", + "multiple": false, + "desc": null + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedPair", + "desc": null + } + ], + "pip_dependencies": [ + { + "name": "pyserial", + "v": "3.5" + } + ], + "path": "PYTHON/nodes/IO/ANALOG_SENSORS/PRESSURE_SENSORS/FLEXIFORCE_25LB/FLEXIFORCE_25LB.py", + "selected": false + }, + "position": { + "x": -128.77937355641933, + "y": -298.2480293081669 + }, + "selected": false, + "positionAbsolute": { + "x": -128.77937355641933, + "y": -298.2480293081669 + }, + "dragging": true + } + ], + "edges": [], + "viewport": { + "x": 819.7643144890276, + "y": 420.4113108673, + "zoom": 0.8915653288195635 + } + } +} \ No newline at end of file diff --git a/docs/nodes/IO/ANALOG_SENSORS/PRESSURE_SENSORS/FLEXIFORCE_25LB/examples/EX1/example.md b/docs/nodes/IO/ANALOG_SENSORS/PRESSURE_SENSORS/FLEXIFORCE_25LB/examples/EX1/example.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/nodes/IO/ANALOG_SENSORS/THERMOCOUPLES/LM34/LM34.md b/docs/nodes/IO/ANALOG_SENSORS/THERMOCOUPLES/LM34/LM34.md new file mode 100644 index 0000000000..bae39652cb --- /dev/null +++ b/docs/nodes/IO/ANALOG_SENSORS/THERMOCOUPLES/LM34/LM34.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/ANALOG_SENSORS/THERMOCOUPLES/LM34/a1-[autogen]/docstring.txt b/docs/nodes/IO/ANALOG_SENSORS/THERMOCOUPLES/LM34/a1-[autogen]/docstring.txt new file mode 100644 index 0000000000..b2af7fe649 --- /dev/null +++ b/docs/nodes/IO/ANALOG_SENSORS/THERMOCOUPLES/LM34/a1-[autogen]/docstring.txt @@ -0,0 +1,4 @@ + +The LM34 node allows you to convert voltages measured with a thermocouple (LM34) connected to a LabJack U3 device into temperatures. +Calibration1, Calibration2, Calibration3 : float + Calibration parameters to convert voltage into temperature in Celcius. diff --git a/docs/nodes/IO/ANALOG_SENSORS/THERMOCOUPLES/LM34/a1-[autogen]/python_code.txt b/docs/nodes/IO/ANALOG_SENSORS/THERMOCOUPLES/LM34/a1-[autogen]/python_code.txt new file mode 100644 index 0000000000..23cbb1b289 --- /dev/null +++ b/docs/nodes/IO/ANALOG_SENSORS/THERMOCOUPLES/LM34/a1-[autogen]/python_code.txt @@ -0,0 +1,25 @@ +from flojoy import flojoy, OrderedPair, DataContainer +from typing import Optional + + +@flojoy() +def LM34( + default: OrderedPair, + calibration1: float = 100.0, + calibration2: float = 32.0, + calibration3: float = 1.8, +) -> OrderedPair: + + + temperatures_celsius: list[float] = [] + voltages = default.y + sensor_num = default.x + sensors_number = len(default.x) + + # Convert Voltage into temperature in Celsius : + for i in range(0, sensors_number): + temperature: float = voltages[i] * calibration1 + temperature_celsius: float = (temperature - calibration2) / calibration3 + temperatures_celsius.append(temperature_celsius) + + return OrderedPair(sensor_num, temperatures_celsius) diff --git a/docs/nodes/IO/ANALOG_SENSORS/THERMOCOUPLES/LM34/appendix/hardware.md b/docs/nodes/IO/ANALOG_SENSORS/THERMOCOUPLES/LM34/appendix/hardware.md new file mode 100644 index 0000000000..7f78a555c4 --- /dev/null +++ b/docs/nodes/IO/ANALOG_SENSORS/THERMOCOUPLES/LM34/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/ANALOG_SENSORS/THERMOCOUPLES/LM34/appendix/media.md b/docs/nodes/IO/ANALOG_SENSORS/THERMOCOUPLES/LM34/appendix/media.md new file mode 100644 index 0000000000..8bcee9be90 --- /dev/null +++ b/docs/nodes/IO/ANALOG_SENSORS/THERMOCOUPLES/LM34/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/ANALOG_SENSORS/THERMOCOUPLES/LM34/appendix/notes.md b/docs/nodes/IO/ANALOG_SENSORS/THERMOCOUPLES/LM34/appendix/notes.md new file mode 100644 index 0000000000..04aded2ec9 --- /dev/null +++ b/docs/nodes/IO/ANALOG_SENSORS/THERMOCOUPLES/LM34/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/ANALOG_SENSORS/THERMOCOUPLES/LM34/examples/EX1/app.json b/docs/nodes/IO/ANALOG_SENSORS/THERMOCOUPLES/LM34/examples/EX1/app.json new file mode 100644 index 0000000000..82ddabeed8 --- /dev/null +++ b/docs/nodes/IO/ANALOG_SENSORS/THERMOCOUPLES/LM34/examples/EX1/app.json @@ -0,0 +1,55 @@ +{ + "rfInstance": { + "nodes": [ + { + "width": 150, + "height": 180, + "id": "LM34-a4fabeea-988a-4de9-9c47-218f4575717e", + "type": "IO", + "data": { + "id": "LM34-a4fabeea-988a-4de9-9c47-218f4575717e", + "label": "LM34", + "func": "LM34", + "type": "IO", + "ctrls": {}, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "Any", + "multiple": false, + "desc": null + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedPair", + "desc": null + } + ], + "path": "PYTHON/nodes/IO/ANALOG_SENSORS/THERMOCOUPLES/LM34/LM34.py", + "selected": true + }, + "position": { + "x": -140.33430403903543, + "y": -274.5727434927463 + }, + "selected": true, + "positionAbsolute": { + "x": -140.33430403903543, + "y": -274.5727434927463 + }, + "dragging": true + } + ], + "edges": [], + "viewport": { + "x": 819.7643144890276, + "y": 420.4113108673, + "zoom": 0.8915653288195635 + } + } +} \ No newline at end of file diff --git a/docs/nodes/IO/ANALOG_SENSORS/THERMOCOUPLES/LM34/examples/EX1/example.md b/docs/nodes/IO/ANALOG_SENSORS/THERMOCOUPLES/LM34/examples/EX1/example.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/nodes/IO/IMAGING/WEBCAM/WEBCAM.md b/docs/nodes/IO/IMAGING/WEBCAM/WEBCAM.md new file mode 100644 index 0000000000..b92c05553a --- /dev/null +++ b/docs/nodes/IO/IMAGING/WEBCAM/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/WEBCAM/a1-[autogen]/docstring.txt b/docs/nodes/IO/IMAGING/WEBCAM/a1-[autogen]/docstring.txt new file mode 100644 index 0000000000..f529c130a9 --- /dev/null +++ b/docs/nodes/IO/IMAGING/WEBCAM/a1-[autogen]/docstring.txt @@ -0,0 +1,14 @@ +The CAMERA node acquires an image using the selected camera. + + If no camera is detected, an error would be shown. + + Parameters + ---------- + camera_ind : int + Camera index (i.e. camera identifier). + resolution : select + Camera resolution. Choose from a few options. + + Returns + ------- + Image diff --git a/docs/nodes/IO/IMAGING/WEBCAM/a1-[autogen]/python_code.txt b/docs/nodes/IO/IMAGING/WEBCAM/a1-[autogen]/python_code.txt new file mode 100644 index 0000000000..857b54e822 --- /dev/null +++ b/docs/nodes/IO/IMAGING/WEBCAM/a1-[autogen]/python_code.txt @@ -0,0 +1,63 @@ +import cv2 +import os +from flojoy import flojoy, DataContainer +from typing import Optional, Literal +from PIL import Image +import numpy as np + + +@flojoy(deps={"opencv-python-headless": "4.7.0.72"}) +def WEBCAM( + default: Optional[DataContainer] = None, + camera_ind: int = -1, + resolution: Literal[ + "default", "640x360", "640x480", "1280x720", "1920x1080" + ] = "default", +) -> DataContainer: + + + 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])) + except cv2.error as camera_error: + print(f"Invalid resolution ({resolution}). Try a lower value.") + raise camera_error + + if not camera.isOpened(): + raise cv2.error("Failed to open camera") + + result, BGR_img = camera.read() + + if not result: + raise cv2.error("Failed to capture image") + camera.release() + del camera + + RGB_img = cv2.cvtColor(BGR_img, cv2.COLOR_BGR2RGB) + + # Split the image channels + red_channel = RGB_img[:, :, 0] + green_channel = RGB_img[:, :, 1] + blue_channel = RGB_img[:, :, 2] + + if RGB_img.shape[2] == 4: + alpha_channel = RGB_img[:, :, 3] + else: + alpha_channel = None + + camera_image = DataContainer( + type="Image", + r=red_channel, + g=green_channel, + b=blue_channel, + a=alpha_channel, + ) + + return camera_image + + except cv2.error as camera_error: + raise camera_error diff --git a/docs/nodes/IO/IMAGING/WEBCAM/appendix/hardware.md b/docs/nodes/IO/IMAGING/WEBCAM/appendix/hardware.md new file mode 100644 index 0000000000..7f78a555c4 --- /dev/null +++ b/docs/nodes/IO/IMAGING/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/WEBCAM/appendix/media.md b/docs/nodes/IO/IMAGING/WEBCAM/appendix/media.md new file mode 100644 index 0000000000..8bcee9be90 --- /dev/null +++ b/docs/nodes/IO/IMAGING/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/WEBCAM/appendix/notes.md b/docs/nodes/IO/IMAGING/WEBCAM/appendix/notes.md new file mode 100644 index 0000000000..04aded2ec9 --- /dev/null +++ b/docs/nodes/IO/IMAGING/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/WEBCAM/examples/EX1/app.json b/docs/nodes/IO/IMAGING/WEBCAM/examples/EX1/app.json new file mode 100644 index 0000000000..b0da688128 --- /dev/null +++ b/docs/nodes/IO/IMAGING/WEBCAM/examples/EX1/app.json @@ -0,0 +1,147 @@ +{ + "rfInstance": { + "nodes": [ + { + "width": 150, + "height": 150, + "id": "CAMERA-29dc2b2f-b87c-46a3-9ddc-11e685de3206", + "type": "INSTRUMENTS", + "data": { + "id": "CAMERA-29dc2b2f-b87c-46a3-9ddc-11e685de3206", + "label": "CAMERA", + "func": "CAMERA", + "type": "INSTRUMENTS", + "ctrls": { + "camera_ind": { + "type": "int", + "default": -1, + "functionName": "CAMERA", + "param": "camera_ind", + "value": -1 + }, + "resolution": { + "type": "select", + "default": "default", + "options": [ + "default", + "640x360", + "640x480", + "1280x720", + "1920x1080" + ], + "functionName": "CAMERA", + "param": "resolution", + "value": "default" + } + }, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "Any", + "multiple": false + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "Any" + } + ], + "pip_dependencies": [ + { + "name": "opencv-python-headless", + "v": "4.7.0.72" + } + ], + "path": "PYTHON/nodes/INSTRUMENTS/WEB_CAM/CAMERA/CAMERA.py", + "selected": false + }, + "position": { + "x": 934.4795759482945, + "y": -38.568710835013746 + }, + "selected": false, + "positionAbsolute": { + "x": 934.4795759482945, + "y": -38.568710835013746 + }, + "dragging": true + }, + { + "width": 225, + "height": 226, + "id": "IMAGE-cd503f68-87fd-478a-b577-baa959f3df08", + "type": "VISUALIZERS", + "data": { + "id": "IMAGE-cd503f68-87fd-478a-b577-baa959f3df08", + "label": "IMAGE", + "func": "IMAGE", + "type": "VISUALIZERS", + "ctrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "Image", + "multiple": false + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "Plotly" + } + ], + "path": "PYTHON/nodes/VISUALIZERS/PLOTLY/IMAGE/IMAGE.py", + "selected": false + }, + "position": { + "x": 1261.9152508247892, + "y": -78.58047260527047 + }, + "selected": false, + "positionAbsolute": { + "x": 1261.9152508247892, + "y": -78.58047260527047 + }, + "dragging": true + } + ], + "edges": [ + { + "source": "CAMERA-29dc2b2f-b87c-46a3-9ddc-11e685de3206", + "sourceHandle": "default", + "target": "IMAGE-cd503f68-87fd-478a-b577-baa959f3df08", + "targetHandle": "default", + "id": "reactflow__edge-CAMERA-29dc2b2f-b87c-46a3-9ddc-11e685de3206default-IMAGE-cd503f68-87fd-478a-b577-baa959f3df08default" + } + ], + "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" + } + } + ] +} \ No newline at end of file diff --git a/docs/nodes/IO/IMAGING/WEBCAM/examples/EX1/example.md b/docs/nodes/IO/IMAGING/WEBCAM/examples/EX1/example.md new file mode 100644 index 0000000000..227b8b2909 --- /dev/null +++ b/docs/nodes/IO/IMAGING/WEBCAM/examples/EX1/example.md @@ -0,0 +1,14 @@ +--- +title: CAMERA +description: In this example, the CAMERA node takes and returns a picture if a USB camera is connected to the computer. The IMSHOW node then displays the image taken by the camera, and the END node terminates the process. +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. + +Before using the node, you'll need to define the Camera index in the node parameter to choose your Camera (e.g. Webcam, USB camera, etc.). + +To do that, you can follow [this link](https://stackoverflow.com/questions/57577445/list-available-cameras-opencv-python?fbclid=IwAR2PJTQGE7QohTPChRG_N6hk07gjaGDnanT02aWX0oYvr9ytNGzdSkEC48c), run the python script to list all the cameras available on your computer, and then select the one that you want to use. (The index is the port where the camera is connected). + +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. \ No newline at end of file diff --git a/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/READ_A0_PINS.md b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/READ_A0_PINS.md new file mode 100644 index 0000000000..fac2632c9b --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/READ_A0_PINS.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/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/a1-[autogen]/docstring.txt b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/a1-[autogen]/docstring.txt new file mode 100644 index 0000000000..1d58d4d9e9 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/a1-[autogen]/docstring.txt @@ -0,0 +1,7 @@ +The READ_A0_PINS node allows you to record and return voltages from a sensor connected to a LABJACK U3 device. eturns temperature measurements with a + Use the sensor node to convert voltage into temperature measurements + + Parameters + ---------- + number : int + Defines the number of temperature sensors connected to the LabJack U3 device. diff --git a/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/a1-[autogen]/python_code.txt b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/a1-[autogen]/python_code.txt new file mode 100644 index 0000000000..57bbfc0a7b --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/a1-[autogen]/python_code.txt @@ -0,0 +1,36 @@ +from flojoy import flojoy, OrderedPair, node_initialization, NodeInitContainer +from typing import Optional +import u3 # Import the library from LabJackPython in order to use our U3-LV device + + +@flojoy(deps={"labjackpython": "2.1.0"}) +def READ_A0_PINS( + init_container: NodeInitContainer, + default: Optional[OrderedPair] = None, + sensor_number: int = 1, +) -> OrderedPair: + + + voltages: list[float] = [] + + sensor_num: list[int] = [] + + d = init_container.get() + if d is None: + raise ValueError("LabJack U3 device not initialized") + + for i in range(0, sensor_number): + sensor_num.append(i + 1) + # Loop on the LabJack pins + voltage: float = d.getAIN(i) + voltages.append(voltage) + + return OrderedPair(x=sensor_num, y=voltages) + + +@node_initialization(for_node=READ_A0_PINS) +def init(): + d = u3.U3() + d.configIO(FIOAnalog=255, EIOAnalog=0) + + return d diff --git a/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/appendix/hardware.md b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/appendix/hardware.md new file mode 100644 index 0000000000..7f78a555c4 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/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/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/appendix/media.md b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/appendix/media.md new file mode 100644 index 0000000000..8bcee9be90 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/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/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/appendix/notes.md b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/appendix/notes.md new file mode 100644 index 0000000000..04aded2ec9 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/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/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/examples/EX1/app.json b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/examples/EX1/app.json new file mode 100644 index 0000000000..f4cb1fa5ed --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/examples/EX1/app.json @@ -0,0 +1,187 @@ +{ + "name": "LabJack", + "rfInstance": { + "nodes": [ + { + "width": 192, + "height": 192, + "id": "LABJACKU3-f2fffab7-ab79-4fa0-ad33-1fb3825d76d2", + "type": "INSTRUMENTS", + "data": { + "id": "LABJACKU3-f2fffab7-ab79-4fa0-ad33-1fb3825d76d2", + "label": "LABJACKU3", + "func": "LABJACKU3", + "type": "INSTRUMENTS", + "ctrls": { + "sensor_number": { + "type": "int", + "default": 1, + "desc": null, + "functionName": "LABJACKU3", + "param": "sensor_number", + "value": 1 + } + }, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedPair", + "multiple": false, + "desc": null + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedPair", + "desc": null + } + ], + "pip_dependencies": [ + { + "name": "labjackpython", + "v": "2.1.0" + } + ], + "path": "PYTHON/nodes/INSTRUMENTS/LABJACK/LABJACKU3/LABJACKU3.py", + "selected": false + }, + "position": { + "x": 1198.1450498207269, + "y": -251.53956541935366 + }, + "selected": false, + "positionAbsolute": { + "x": 1198.1450498207269, + "y": -251.53956541935366 + }, + "dragging": true + }, + { + "width": 96, + "height": 96, + "id": "LOOP-e4a27070-af07-414b-813a-04282d60bd63", + "type": "LOGIC_GATES", + "data": { + "id": "LOOP-e4a27070-af07-414b-813a-04282d60bd63", + "label": "LOOP", + "func": "LOOP", + "type": "LOGIC_GATES", + "ctrls": { + "num_loops": { + "type": "int", + "default": -1, + "desc": "number of times to iterate through body nodes, default is \"-1\" meaning infinity.", + "functionName": "LOOP", + "param": "num_loops", + "value": -1 + } + }, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "Any", + "multiple": false, + "desc": null + } + ], + "outputs": [ + { + "name": "body", + "id": "body", + "type": "Any", + "desc": null + }, + { + "name": "end", + "id": "end", + "type": "Any", + "desc": null + } + ], + "path": "PYTHON/nodes/LOGIC_GATES/LOOPS/LOOP/LOOP.py", + "selected": false + }, + "position": { + "x": 880.5733928773202, + "y": -179.04616996461596 + }, + "selected": false, + "positionAbsolute": { + "x": 880.5733928773202, + "y": -179.04616996461596 + }, + "dragging": true + }, + { + "width": 225, + "height": 226, + "id": "BAR-c7fcec94-45c8-43e9-b35f-28c98bb21c96", + "type": "VISUALIZERS", + "data": { + "id": "BAR-c7fcec94-45c8-43e9-b35f-28c98bb21c96", + "label": "BAR", + "func": "BAR", + "type": "VISUALIZERS", + "ctrls": {}, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedPair|DataFrame|Matrix|Vector", + "multiple": false, + "desc": "the DataContainer to be visualized in bar chart" + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "Plotly", + "desc": "the DataContainer containing Plotly Bar chart visualization" + } + ], + "path": "PYTHON/nodes/VISUALIZERS/PLOTLY/BAR/BAR.py", + "selected": false + }, + "position": { + "x": 1645.3402278336362, + "y": -274.0554805783094 + }, + "selected": false, + "positionAbsolute": { + "x": 1645.3402278336362, + "y": -274.0554805783094 + }, + "dragging": true + } + ], + "edges": [ + { + "source": "LOOP-e4a27070-af07-414b-813a-04282d60bd63", + "sourceHandle": "body", + "target": "LABJACKU3-f2fffab7-ab79-4fa0-ad33-1fb3825d76d2", + "targetHandle": "default", + "id": "reactflow__edge-LOOP-e4a27070-af07-414b-813a-04282d60bd63body-LABJACKU3-f2fffab7-ab79-4fa0-ad33-1fb3825d76d2default" + }, + { + "source": "LABJACKU3-f2fffab7-ab79-4fa0-ad33-1fb3825d76d2", + "sourceHandle": "default", + "target": "BAR-c7fcec94-45c8-43e9-b35f-28c98bb21c96", + "targetHandle": "default", + "id": "reactflow__edge-LABJACKU3-f2fffab7-ab79-4fa0-ad33-1fb3825d76d2default-BAR-c7fcec94-45c8-43e9-b35f-28c98bb21c96default" + } + ], + "viewport": { + "x": 815.7959874736157, + "y": 352.53461082817995, + "zoom": 0.7476193625116623 + } + } +} \ No newline at end of file diff --git a/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/examples/EX1/example.md b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/examples/EX1/example.md new file mode 100644 index 0000000000..32bd934056 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/examples/EX1/example.md @@ -0,0 +1,16 @@ +--- +title: LABJACKU3 +description: In this example, we show how to record and display temperature measurements with a LABJACK U3 device and update them in a Loop. +keyword: [Python, Instrument, LabJack U3 instrument control, Python integration with LabJack, Measurement and analysis, Python-based instrument control, LabJack U3 integration techniques, Python-based measurement techniques, Enhance measurements with Python, Streamline LabJack usage, Accurate data analysis, Python control of LabJack U3] +image: https://raw.githubusercontent.com/flojoy-ai/docs/main/docs/nodes/INSTRUMENTS/LABJACK/LABJACKU3/examples/EX1/output.jpeg +--- + +In this example, we show how to record and display temperature measurements with a LABJACK U3 device and update them in a Loop. The appendix contains all information about hardware requirements and sensor connections (Images). You'll also need to install the Labjack exodriver to communicate with the U3 device through USB: https://labjack.com/pages/support?doc=/software-driver/installer-downloads/exodriver/. + +When the sensors are connected to the LABJACK U3 device and placed to record temperature, you can prepare your Flojoy app: + +The [`LABJACKU3`](https://github.com/flojoy-io/nodes/blob/main/INSTRUMENTS/LABJACK/LABJACKU3/LABJACKU3.py) node communicates with the LABJACK U3 device to extract temperature measurements from the sensors. This node has only one parameter to fix: the number of sensors (6 in this example). + +The [`BAR`](https://github.com/flojoy-io/nodes/blob/main/VISUALIZERS/PLOTLY/BAR/BAR.py) node displays all temperature measurements on the same figure. + +To update the results with the latest measurements, we use the [`LOOP`](https://github.com/flojoy-io/nodes/blob/main/LOGIC_GATES/LOOPS/LOOP/LOOP.py) node to create a loop around our [`LABJACKU3`](https://github.com/flojoy-io/nodes/blob/main/INSTRUMENTS/LABJACK/LABJACKU3/LABJACKU3.py) and [`BAR`](https://github.com/flojoy-io/nodes/blob/main/VISUALIZERS/PLOTLY/BAR/BAR.py) nodes. (Refer to the `LOOP` node documentation for more information). \ No newline at end of file diff --git a/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/READ_N_PINS.md b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/READ_N_PINS.md new file mode 100644 index 0000000000..b4099dc90b --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/READ_N_PINS.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/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/a1-[autogen]/docstring.txt b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/a1-[autogen]/docstring.txt new file mode 100644 index 0000000000..d307107f60 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/a1-[autogen]/docstring.txt @@ -0,0 +1,7 @@ + +The READ_N_PINS node allows you to measure and output voltages from Flexiforce sensors using a Phidget InterfaceKit. + +Parameters +---------- +n_sensors : int + Defines the number of pressure sensors connected to the Phidget InterfaceKit. diff --git a/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/a1-[autogen]/python_code.txt b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/a1-[autogen]/python_code.txt new file mode 100644 index 0000000000..ffe7fef7a8 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/a1-[autogen]/python_code.txt @@ -0,0 +1,41 @@ +from flojoy import flojoy, OrderedPair +from typing import Optional +from Phidget22.Devices.VoltageRatioInput import VoltageRatioInput + + +def onVoltageRatioChange(self, voltageRatio): + # Declaration of the Event handler, print Voltage variation for a channel. + print("VoltageRatio [" + str(self.getChannel()) + "]: " + str(voltageRatio)) + + +@flojoy(deps={"Phidget22": "1.14.20230331"}) +def READ_N_PINS( + default: Optional[OrderedPair] = None, + n_sensors: int = 1, +) -> OrderedPair: + + + voltage: list[float] = [] + pressions: list[float] = [] + sensor_num: list[int] = [] + + for i in range(0, n_sensors): + sensor_num.append(i + 1) + # Creation of an instance of the VoltageRationInput class + voltage_ratio_input = VoltageRatioInput() + # Set Channel for Communication with the Phidget Interface Kit : + voltage_ratio_input.setChannel(i) + # Assign the handler that will be called when the event occurs : + voltage_ratio_input.setOnVoltageRatioChangeHandler(onVoltageRatioChange) + # Open the Channel after event handler is set : + voltage_ratio_input.openWaitForAttachment(5000) + volt_i: float = ( + voltage_ratio_input.getVoltageRatio() + ) # Measure Voltage from the sensor + voltage.append(volt_i) # Add Voltage to the list of measurements + + # Example of a Calibration to convert Voltage into pressions : + pression_i: float = (volt_i - calibration1) / calibration2 + pressions.append(pression_i) + + return OrderedPair(x=sensor_num, y=voltage) diff --git a/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/appendix/hardware.md b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/appendix/hardware.md new file mode 100644 index 0000000000..7f78a555c4 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/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/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/appendix/media.md b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/appendix/media.md new file mode 100644 index 0000000000..8bcee9be90 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/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/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/appendix/notes.md b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/appendix/notes.md new file mode 100644 index 0000000000..04aded2ec9 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/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/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/examples/EX1/app.json b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/examples/EX1/app.json new file mode 100644 index 0000000000..9e4a225dab --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/examples/EX1/app.json @@ -0,0 +1,138 @@ +{ + "name": "LabJack", + "rfInstance": { + "nodes": [ + { + "width": 225, + "height": 226, + "id": "BAR-c7fcec94-45c8-43e9-b35f-28c98bb21c96", + "type": "VISUALIZERS", + "data": { + "id": "BAR-c7fcec94-45c8-43e9-b35f-28c98bb21c96", + "label": "BAR", + "func": "BAR", + "type": "VISUALIZERS", + "ctrls": {}, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedPair|DataFrame|Matrix|Vector", + "multiple": false, + "desc": "the DataContainer to be visualized in bar chart" + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "Plotly", + "desc": "the DataContainer containing Plotly Bar chart visualization" + } + ], + "path": "PYTHON/nodes/VISUALIZERS/PLOTLY/BAR/BAR.py", + "selected": false + }, + "position": { + "x": 1855.8154876086248, + "y": -302.51832709592355 + }, + "selected": false, + "positionAbsolute": { + "x": 1855.8154876086248, + "y": -302.51832709592355 + }, + "dragging": true + }, + { + "width": 192, + "height": 192, + "id": "PHIDGET22-481eba31-1ee6-41a5-9241-03cc797fa5f4", + "type": "INSTRUMENTS", + "data": { + "id": "PHIDGET22-481eba31-1ee6-41a5-9241-03cc797fa5f4", + "label": "PHIDGET22", + "func": "PHIDGET22", + "type": "INSTRUMENTS", + "ctrls": { + "n_sensors": { + "type": "int", + "default": 1, + "desc": "Defines the number of pressure sensors connected to the Phidget InterfaceKit.", + "functionName": "PHIDGET22", + "param": "n_sensors", + "value": 1 + }, + "calibration1": { + "type": "float", + "default": 0.015, + "desc": "Calibration parameters to convert voltage into pressure.", + "functionName": "PHIDGET22", + "param": "calibration1", + "value": 0.015 + }, + "calibration2": { + "type": "float", + "default": 0.06, + "desc": "Calibration parameters to convert voltage into pressure.", + "functionName": "PHIDGET22", + "param": "calibration2", + "value": 0.06 + } + }, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedPair", + "multiple": false, + "desc": null + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedPair", + "desc": null + } + ], + "pip_dependencies": [ + { + "name": "Phidget22", + "v": "1.14.20230331" + } + ], + "path": "PYTHON/nodes/INSTRUMENTS/PHIDGET/PHIDGET22/PHIDGET22.py", + "selected": true + }, + "position": { + "x": 1501.7006581112141, + "y": -283.8123758873477 + }, + "selected": true, + "positionAbsolute": { + "x": 1501.7006581112141, + "y": -283.8123758873477 + }, + "dragging": true + } + ], + "edges": [ + { + "source": "PHIDGET22-481eba31-1ee6-41a5-9241-03cc797fa5f4", + "sourceHandle": "default", + "target": "BAR-c7fcec94-45c8-43e9-b35f-28c98bb21c96", + "targetHandle": "default", + "id": "reactflow__edge-PHIDGET22-481eba31-1ee6-41a5-9241-03cc797fa5f4default-BAR-c7fcec94-45c8-43e9-b35f-28c98bb21c96default" + } + ], + "viewport": { + "x": 815.7959874736157, + "y": 352.53461082817995, + "zoom": 0.7476193625116623 + } + } +} \ No newline at end of file diff --git a/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/examples/EX1/example.md b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/examples/EX1/example.md new file mode 100644 index 0000000000..e89cb519da --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/examples/EX1/example.md @@ -0,0 +1,23 @@ +--- +title: PHIDGET22 +description: This example shows how to use the PHIDGET22 node to measure pressures from Flexiforce sensors using a Phidget Interface Kit. +keyword: [Python, Instrument, Phidget22 instrument control, Python integration with Phidget, Measurement and analysis, Python-based instrument control, Phidget22 integration techniques, Python-based measurement techniques, Enhance measurements with Python, Streamline Phidget usage, Accurate data analysis, Python control of Phidget22] +image: https://raw.githubusercontent.com/flojoy-ai/docs/main/docs/nodes/INSTRUMENTS/PHIDGET/PHIDGET22/examples/EX1/output.jpeg +--- + +This example shows how to use the `PHIDGET22` node to measure pressures from Flexiforce sensors using a Phidget Interface Kit. The appendix contains all information about hardware requirements and sensor connections (Images). + +After connecting the pressure sensors, the following nodes are placed: + +The [`PHIDGET22`](https://github.com/flojoy-io/nodes/blob/main/INSTRUMENTS/PHIDGET/PHIDGET22/PHIDGET22.py) node communicates with the Phidget Interface Kit. It measures voltages from the sensors and converts them into pressures because of the two calibration parameters (the user has to calibrate his sensors). This node has another parameter, `n_sensors`, the number of pressure sensors in your experiment. + +The [`BAR`](https://github.com/flojoy-io/nodes/blob/main/VISUALIZERS/PLOTLY/BAR/BAR.py) node displays all pressure measurements on the same figure. + +**Calibration:** + +- Apply known pressures (at least 4) and measure sensor voltages with the Phidget control panel. +- Plot the voltage as a function of the forces applied. You can choose the unit of your choice. +- Find the linear equation (y=ax+b) between the voltage measured and the pressure applied on the sensor. +- A and B are the calibration parameters that convert voltage into pressure. + +To update the measurements with time, you can add the [`LOOP`](https://github.com/flojoy-io/nodes/blob/main/LOGIC_GATES/LOOPS/LOOP/LOOP.py) node to create a loop. (Refer to the [`LOOP`](https://github.com/flojoy-io/nodes/blob/main/LOGIC_GATES/LOOPS/LOOP/LOOP.py) node documentation for the loop settings). \ No newline at end of file diff --git a/docs/nodes/IO/INSTRUMENTS/MOCK/WEINSCHEL8320/WEINSCHEL8320.md b/docs/nodes/IO/INSTRUMENTS/MOCK/WEINSCHEL8320/WEINSCHEL8320.md new file mode 100644 index 0000000000..bc9d7e24b5 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/MOCK/WEINSCHEL8320/WEINSCHEL8320.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/MOCK/WEINSCHEL8320/a1-[autogen]/docstring.txt b/docs/nodes/IO/INSTRUMENTS/MOCK/WEINSCHEL8320/a1-[autogen]/docstring.txt new file mode 100644 index 0000000000..4456826041 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/MOCK/WEINSCHEL8320/a1-[autogen]/docstring.txt @@ -0,0 +1,14 @@ +Note this node is for testing purposes only. + + The WEINSCHEL8320 node mocks the instrument WEINSCHEL 8320. + The Weinschel 8320 attenuates the input signal. + + Parameters + ---------- + attenuation : int + Value that the instrument would attenuate the input signal (mocked). + + Returns + ------- + Scalar + c: attenuation value diff --git a/docs/nodes/IO/INSTRUMENTS/MOCK/WEINSCHEL8320/a1-[autogen]/python_code.txt b/docs/nodes/IO/INSTRUMENTS/MOCK/WEINSCHEL8320/a1-[autogen]/python_code.txt new file mode 100644 index 0000000000..139d575d37 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/MOCK/WEINSCHEL8320/a1-[autogen]/python_code.txt @@ -0,0 +1,30 @@ +from flojoy import flojoy, Scalar, DataContainer +from qcodes.instrument_drivers.weinschel import Weinschel8320 +from typing import Optional + + +@flojoy(deps={"qcodes": "0.39.1", "pyvisa-sim": "0.5.1"}) +def WEINSCHEL8320( + default: Optional[DataContainer] = None, + attenuation: int = 10, +) -> Scalar: + + + wein_sim = Weinschel8320( + "wein_sim", + address="GPIB::1::INSTR", + pyvisa_sim_file="Weinschel_8320.yaml", + ) + + idn_dict = wein_sim.IDN() + print(f"Connected to mock instrument: {idn_dict}") + + wein_sim.attenuation(attenuation) + + # Get the current attenuation value + attenuation_value = wein_sim.attenuation() + + # Print the current attenuation value + print(f"Current attenuation: {attenuation_value} dB") + + return Scalar(c=attenuation_value) diff --git a/docs/nodes/IO/INSTRUMENTS/MOCK/WEINSCHEL8320/appendix/hardware.md b/docs/nodes/IO/INSTRUMENTS/MOCK/WEINSCHEL8320/appendix/hardware.md new file mode 100644 index 0000000000..7f78a555c4 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/MOCK/WEINSCHEL8320/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/MOCK/WEINSCHEL8320/appendix/media.md b/docs/nodes/IO/INSTRUMENTS/MOCK/WEINSCHEL8320/appendix/media.md new file mode 100644 index 0000000000..8bcee9be90 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/MOCK/WEINSCHEL8320/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/MOCK/WEINSCHEL8320/appendix/notes.md b/docs/nodes/IO/INSTRUMENTS/MOCK/WEINSCHEL8320/appendix/notes.md new file mode 100644 index 0000000000..04aded2ec9 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/MOCK/WEINSCHEL8320/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/MOCK/WEINSCHEL8320/examples/EX1/app.json b/docs/nodes/IO/INSTRUMENTS/MOCK/WEINSCHEL8320/examples/EX1/app.json new file mode 100644 index 0000000000..0189255f2a --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/MOCK/WEINSCHEL8320/examples/EX1/app.json @@ -0,0 +1,214 @@ +{ + "rfInstance": { + "nodes": [ + { + "width": 192, + "height": 192, + "id": "MOCK_WEINSCHEL8320-e911e4a9-f243-4d9f-897e-6d1daccd43c8", + "type": "INSTRUMENTS", + "data": { + "id": "MOCK_WEINSCHEL8320-e911e4a9-f243-4d9f-897e-6d1daccd43c8", + "label": "MOCK WEINSCHEL8320", + "func": "MOCK_WEINSCHEL8320", + "type": "INSTRUMENTS", + "ctrls": { + "attenuation": { + "type": "int", + "default": 10, + "desc": "Value that the instrument would attenuate the input signal (mocked).", + "functionName": "MOCK_WEINSCHEL8320", + "param": "attenuation", + "value": 10 + } + }, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "Scalar", + "multiple": false, + "desc": null + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "Scalar", + "desc": "c: attenuation value" + } + ], + "pip_dependencies": [ + { + "name": "qcodes", + "v": "0.39.1" + }, + { + "name": "pyvisa-sim", + "v": "0.5.1" + } + ], + "path": "PYTHON/nodes/INSTRUMENTS/MOCK/MOCK_WEINSCHEL8320/MOCK_WEINSCHEL8320.py", + "selected": false + }, + "position": { + "x": -41.116360435642804, + "y": -6.40137677558107 + }, + "selected": false, + "positionAbsolute": { + "x": -41.116360435642804, + "y": -6.40137677558107 + }, + "dragging": true + }, + { + "width": 380, + "height": 293, + "id": "BIG_NUMBER-b00b664d-8fc1-4ad5-bb24-c45fc49db01d", + "type": "VISUALIZERS", + "data": { + "id": "BIG_NUMBER-b00b664d-8fc1-4ad5-bb24-c45fc49db01d", + "label": "BIG NUMBER", + "func": "BIG_NUMBER", + "type": "VISUALIZERS", + "ctrls": { + "suffix": { + "type": "str", + "default": null, + "desc": "any suffix to show with big number", + "functionName": "BIG_NUMBER", + "param": "suffix", + "value": "" + }, + "prefix": { + "type": "str", + "default": null, + "desc": "any prefix to show with big number", + "functionName": "BIG_NUMBER", + "param": "prefix", + "value": "" + }, + "title": { + "type": "str", + "default": null, + "desc": "title of the plot, default \"BIG_NUMBER\"", + "functionName": "BIG_NUMBER", + "param": "title", + "value": "" + }, + "relative_delta": { + "type": "bool", + "default": true, + "desc": "whether to show relative delta from last run along with big number", + "functionName": "BIG_NUMBER", + "param": "relative_delta", + "value": true + } + }, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedPair|Scalar|Vector", + "multiple": false, + "desc": "the DataContainer to be visualized" + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "Plotly", + "desc": "the DataContainer containing Plotly big number visualization" + } + ], + "path": "PYTHON/nodes/VISUALIZERS/PLOTLY/BIG_NUMBER/BIG_NUMBER.py", + "selected": false + }, + "position": { + "x": 297.5557009059977, + "y": -60.78098364763936 + }, + "selected": false, + "positionAbsolute": { + "x": 297.5557009059977, + "y": -60.78098364763936 + }, + "dragging": true + }, + { + "width": 192, + "height": 192, + "id": "CLOSE_ALL-b8097938-6108-4509-bbaa-0375d2b76555", + "type": "INSTRUMENTS", + "data": { + "id": "CLOSE_ALL-b8097938-6108-4509-bbaa-0375d2b76555", + "label": "CLOSE ALL", + "func": "CLOSE_ALL", + "type": "INSTRUMENTS", + "ctrls": {}, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "Any", + "multiple": false, + "desc": null + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "Any", + "desc": null + } + ], + "pip_dependencies": [ + { + "name": "qcodes", + "v": "0.39.1" + } + ], + "path": "PYTHON/nodes/INSTRUMENTS/QCODES/CLOSE_ALL/CLOSE_ALL.py", + "selected": false + }, + "position": { + "x": 881.5105030615465, + "y": 8.43267490744222 + }, + "selected": false, + "positionAbsolute": { + "x": 881.5105030615465, + "y": 8.43267490744222 + }, + "dragging": true + } + ], + "edges": [ + { + "source": "MOCK_WEINSCHEL8320-e911e4a9-f243-4d9f-897e-6d1daccd43c8", + "sourceHandle": "default", + "target": "BIG_NUMBER-b00b664d-8fc1-4ad5-bb24-c45fc49db01d", + "targetHandle": "default", + "id": "reactflow__edge-MOCK_WEINSCHEL8320-e911e4a9-f243-4d9f-897e-6d1daccd43c8default-BIG_NUMBER-b00b664d-8fc1-4ad5-bb24-c45fc49db01ddefault" + }, + { + "source": "BIG_NUMBER-b00b664d-8fc1-4ad5-bb24-c45fc49db01d", + "sourceHandle": "default", + "target": "CLOSE_ALL-b8097938-6108-4509-bbaa-0375d2b76555", + "targetHandle": "default", + "id": "reactflow__edge-BIG_NUMBER-b00b664d-8fc1-4ad5-bb24-c45fc49db01ddefault-CLOSE_ALL-b8097938-6108-4509-bbaa-0375d2b76555default" + } + ], + "viewport": { + "x": 1102.229688012807, + "y": 584.5880790869217, + "zoom": 1.2397346348267997 + } + } +} \ No newline at end of file diff --git a/docs/nodes/IO/INSTRUMENTS/MOCK/WEINSCHEL8320/examples/EX1/example.md b/docs/nodes/IO/INSTRUMENTS/MOCK/WEINSCHEL8320/examples/EX1/example.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/nodes/IO/INSTRUMENTS/QCODES/CLOSE_ALL/CLOSE_ALL.md b/docs/nodes/IO/INSTRUMENTS/QCODES/CLOSE_ALL/CLOSE_ALL.md new file mode 100644 index 0000000000..76a6893e68 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/QCODES/CLOSE_ALL/CLOSE_ALL.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/QCODES/CLOSE_ALL/a1-[autogen]/docstring.txt b/docs/nodes/IO/INSTRUMENTS/QCODES/CLOSE_ALL/a1-[autogen]/docstring.txt new file mode 100644 index 0000000000..dff87e7f98 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/QCODES/CLOSE_ALL/a1-[autogen]/docstring.txt @@ -0,0 +1,7 @@ +The CLOSE_ALL node closes all qcodes instruments and should be ran at + the end of each Flojoy app that uses qcodes (and possibly the beginning). + + Returns + ------- + DataContainer + optional: The input DataContainer is returned. diff --git a/docs/nodes/IO/INSTRUMENTS/QCODES/CLOSE_ALL/a1-[autogen]/python_code.txt b/docs/nodes/IO/INSTRUMENTS/QCODES/CLOSE_ALL/a1-[autogen]/python_code.txt new file mode 100644 index 0000000000..a7ccaa4c21 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/QCODES/CLOSE_ALL/a1-[autogen]/python_code.txt @@ -0,0 +1,14 @@ +from flojoy import flojoy, DataContainer +from qcodes.instrument import Instrument +from typing import Optional + + +@flojoy(deps={"qcodes": "0.39.1"}) +def CLOSE_ALL( + default: Optional[DataContainer] = None, +) -> Optional[DataContainer]: + + + Instrument.close_all() + + return default diff --git a/docs/nodes/IO/INSTRUMENTS/QCODES/CLOSE_ALL/appendix/hardware.md b/docs/nodes/IO/INSTRUMENTS/QCODES/CLOSE_ALL/appendix/hardware.md new file mode 100644 index 0000000000..7f78a555c4 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/QCODES/CLOSE_ALL/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/QCODES/CLOSE_ALL/appendix/media.md b/docs/nodes/IO/INSTRUMENTS/QCODES/CLOSE_ALL/appendix/media.md new file mode 100644 index 0000000000..8bcee9be90 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/QCODES/CLOSE_ALL/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/QCODES/CLOSE_ALL/appendix/notes.md b/docs/nodes/IO/INSTRUMENTS/QCODES/CLOSE_ALL/appendix/notes.md new file mode 100644 index 0000000000..04aded2ec9 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/QCODES/CLOSE_ALL/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/QCODES/CLOSE_ALL/examples/EX1/app.json b/docs/nodes/IO/INSTRUMENTS/QCODES/CLOSE_ALL/examples/EX1/app.json new file mode 100644 index 0000000000..c78327297f --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/QCODES/CLOSE_ALL/examples/EX1/app.json @@ -0,0 +1,61 @@ +{ + "rfInstance": { + "nodes": [ + { + "width": 150, + "height": 180, + "id": "CLOSE_ALL-a770cde6-c679-4fbc-b4a8-e7588996fcac", + "type": "IO", + "data": { + "id": "CLOSE_ALL-a770cde6-c679-4fbc-b4a8-e7588996fcac", + "label": "CLOSE ALL", + "func": "CLOSE_ALL", + "type": "IO", + "ctrls": {}, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "Any", + "multiple": false, + "desc": null + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "Any", + "desc": "optional: The input DataContainer is returned." + } + ], + "pip_dependencies": [ + { + "name": "qcodes", + "v": "0.39.1" + } + ], + "path": "PYTHON/nodes/IO/INSTRUMENTS/QCODES/CLOSE_ALL/CLOSE_ALL.py", + "selected": true + }, + "position": { + "x": -125.5478720355016, + "y": -294.9281149320097 + }, + "selected": true, + "positionAbsolute": { + "x": -125.5478720355016, + "y": -294.9281149320097 + }, + "dragging": true + } + ], + "edges": [], + "viewport": { + "x": 819.7643144890276, + "y": 420.4113108673, + "zoom": 0.8915653288195635 + } + } +} \ No newline at end of file diff --git a/docs/nodes/IO/INSTRUMENTS/QCODES/CLOSE_ALL/examples/EX1/example.md b/docs/nodes/IO/INSTRUMENTS/QCODES/CLOSE_ALL/examples/EX1/example.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/IV_SWEEP.md b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/IV_SWEEP.md new file mode 100644 index 0000000000..1f20f92a9a --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/IV_SWEEP.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/IV_SWEEP/a1-[autogen]/docstring.txt b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/a1-[autogen]/docstring.txt new file mode 100644 index 0000000000..474beb1cb4 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/a1-[autogen]/docstring.txt @@ -0,0 +1,8 @@ +The KEITHLEY2400 node takes a IV curve measurement with a Keithley 2400 source meter, send voltages, and measures currents. + + Parameters + ----------- + comport : string + 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 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 new file mode 100644 index 0000000000..db3b62a4eb --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/a1-[autogen]/python_code.txt @@ -0,0 +1,70 @@ +from flojoy import flojoy, OrderedPair, Vector, node_initialization, NodeInitContainer +import serial + + +@flojoy(deps={"pyserial": "3.5"}) +def IV_SWEEP( + init_container: NodeInitContainer, default: OrderedPair | Vector +) -> OrderedPair: + + + # Start serial communication with the instrument + # ser: serial = serial.Serial() + + 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":SENS:CURR:PROT 1.05\n" + ) # Current protection set at 1.05A (Keithley 2400) + + match default: + case OrderedPair(): + voltages = default.y + case Vector(): + voltages = default.v + + currents_neg: list[float] = [] # measured currents + + for voltage in voltages: + ser.write(b":SOUR:VOLT %f\n" % voltage) # Source Tension (V) + ser.write(b":OUTP ON\n") # Instrument output open + 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 + currents_neg.append(-float(voltage_current_values[1])) + + ser.write(b":OUTP OFF\n") # Close output from Instrument + + # 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 diff --git a/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/appendix/hardware.md b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/appendix/hardware.md new file mode 100644 index 0000000000..7f78a555c4 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/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/IV_SWEEP/appendix/media.md b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/appendix/media.md new file mode 100644 index 0000000000..8bcee9be90 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/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/IV_SWEEP/appendix/notes.md b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/appendix/notes.md new file mode 100644 index 0000000000..04aded2ec9 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/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/IV_SWEEP/examples/EX1/app.json b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/examples/EX1/app.json new file mode 100644 index 0000000000..2617aef0d7 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/examples/EX1/app.json @@ -0,0 +1,204 @@ +{ + "rfInstance": { + "nodes": [ + { + "width": 192, + "height": 192, + "id": "KEITHLEY2400-33053219-7ec1-40d0-9cb9-5d337294a01e", + "type": "INSTRUMENTS", + "data": { + "id": "KEITHLEY2400-33053219-7ec1-40d0-9cb9-5d337294a01e", + "label": "KEITHLEY2400", + "func": "KEITHLEY2400", + "type": "INSTRUMENTS", + "ctrls": {}, + "initCtrls": { + "comport": { + "type": "str", + "default": "/dev/ttyUSB0", + "desc": null, + "functionName": "KEITHLEY2400", + "param": "comport", + "value": "/dev/ttyUSB0" + }, + "baudrate": { + "type": "float", + "default": 9600, + "desc": null, + "functionName": "KEITHLEY2400", + "param": "baudrate", + "value": 9600 + } + }, + "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": "PYTHON/nodes/INSTRUMENTS/KEITHLEY/KEITHLEY2400/KEITHLEY2400.py", + "selected": false + }, + "position": { + "x": 114.41979939902592, + "y": -225.9703888733589 + }, + "selected": false, + "positionAbsolute": { + "x": 114.41979939902592, + "y": -225.9703888733589 + }, + "dragging": true + }, + { + "width": 208, + "height": 96, + "id": "LINSPACE-a3ec55cd-d572-437a-a823-7a8707fc2099", + "type": "GENERATORS", + "data": { + "id": "LINSPACE-a3ec55cd-d572-437a-a823-7a8707fc2099", + "label": "LINSPACE", + "func": "LINSPACE", + "type": "GENERATORS", + "ctrls": { + "start": { + "type": "float", + "default": 10, + "desc": "The start point of the data.", + "functionName": "LINSPACE", + "param": "start", + "value": 10 + }, + "end": { + "type": "float", + "default": 0, + "desc": "The end point of the data.", + "functionName": "LINSPACE", + "param": "end", + "value": 0 + }, + "step": { + "type": "int", + "default": 1000, + "desc": "The number of points in the vector.", + "functionName": "LINSPACE", + "param": "step", + "value": 1000 + } + }, + "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 step number of points." + } + ], + "path": "PYTHON/nodes/GENERATORS/SIMULATIONS/LINSPACE/LINSPACE.py", + "selected": false + }, + "position": { + "x": -220.989828306302, + "y": -177.3419913453396 + }, + "selected": false, + "positionAbsolute": { + "x": -220.989828306302, + "y": -177.3419913453396 + }, + "dragging": true + }, + { + "width": 225, + "height": 226, + "id": "LINE-5ea158cf-c235-4bff-bec2-0714507a1bf0", + "type": "VISUALIZERS", + "data": { + "id": "LINE-5ea158cf-c235-4bff-bec2-0714507a1bf0", + "label": "LINE", + "func": "LINE", + "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 Plotly Line visualization of the input data" + } + ], + "path": "PYTHON/nodes/VISUALIZERS/PLOTLY/LINE/LINE.py", + "selected": true + }, + "position": { + "x": 448.130869654421, + "y": -243.92275361997378 + }, + "selected": true, + "positionAbsolute": { + "x": 448.130869654421, + "y": -243.92275361997378 + }, + "dragging": true + } + ], + "edges": [ + { + "source": "LINSPACE-a3ec55cd-d572-437a-a823-7a8707fc2099", + "sourceHandle": "default", + "target": "KEITHLEY2400-33053219-7ec1-40d0-9cb9-5d337294a01e", + "targetHandle": "default", + "id": "reactflow__edge-LINSPACE-a3ec55cd-d572-437a-a823-7a8707fc2099default-KEITHLEY2400-33053219-7ec1-40d0-9cb9-5d337294a01edefault" + }, + { + "source": "KEITHLEY2400-33053219-7ec1-40d0-9cb9-5d337294a01e", + "sourceHandle": "default", + "target": "LINE-5ea158cf-c235-4bff-bec2-0714507a1bf0", + "targetHandle": "default", + "id": "reactflow__edge-KEITHLEY2400-33053219-7ec1-40d0-9cb9-5d337294a01edefault-LINE-5ea158cf-c235-4bff-bec2-0714507a1bf0default" + } + ], + "viewport": { + "x": 621.1813795484834, + "y": 324.9597014372874, + "zoom": 0.6891413136990774 + } + } +} \ No newline at end of file diff --git a/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/examples/EX1/example.md b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/examples/EX1/example.md new file mode 100644 index 0000000000..11dbc9935a --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/examples/EX1/example.md @@ -0,0 +1,23 @@ +--- +title: KEITHLEY2400 +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. This node has two communication parameters set by the user after connecting the Keithley2400 to his computer: + +- KEITHLEY2400 COMPORT: Define your communication port where the source meter is connected (the default is /dev/tty/USBO for Linux). +- 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. \ No newline at end of file diff --git a/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/SET_VOLTAGE/SET_VOLTAGE.md b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/SET_VOLTAGE/SET_VOLTAGE.md new file mode 100644 index 0000000000..a5d847adc6 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/SET_VOLTAGE/SET_VOLTAGE.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/SET_VOLTAGE/a1-[autogen]/docstring.txt b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/SET_VOLTAGE/a1-[autogen]/docstring.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/SET_VOLTAGE/a1-[autogen]/python_code.txt b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/SET_VOLTAGE/a1-[autogen]/python_code.txt new file mode 100644 index 0000000000..55127434b4 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/SET_VOLTAGE/a1-[autogen]/python_code.txt @@ -0,0 +1,64 @@ +from flojoy import flojoy, OrderedPair, DataContainer +from typing import Optional +from qcodes.instrument.visa import VisaInstrument +from qcodes.instrument_drivers.Keithley.Keithley_2400 import Keithley2400 + + +@flojoy(deps={"qcodes": "0.39.1", "pyvisa-py": "0.6.3", "pyserial": "3.5"}) +def SET_VOLTAGE( + default: Optional[DataContainer] = None, + voltage: int = 2, + voltage_range: int = 10, + current_range: int = 1, +) -> OrderedPair: + # Create an instance of the Keithley2400 instrument + keithley = Keithley2400("keithley", "ASRL/dev/ttyUSB1::INSTR") + + # Connect to the instrument + # keithley.reset() + + # Now you can use the instrument to perform measurements and control the power supply + # For example, you can set the voltage range + # keithley.ask(":SOUR:FUNC:MODE VOLT\n") + keithley.rangev(voltage_range) # Set the voltage range to 10V + + # You can also set the current range + + keithley.rangei(current_range) # Set the current range to 1A + + # Set the voltage compliance + # keithley.compliancev(5) # Set the voltage compliance to 5V + + # Set the current compliance + # keithley.compliancei(0.1) # Set the current compliance to 0.1A + + # Set the output mode to voltage + keithley.mode("VOLT") # Set the mode to voltage + + # Set the sense mode to voltage + keithley.sense("VOLT") # Set the sense mode to voltage + + # Set the voltage level + keithley.volt(voltage) # Set the voltage level to 2V + + # Imprimer le statut de la sortie de l'instrument + output_status = keithley.output() # Lire le statut de la sortie + print(f"Statut de la sortie : {output_status}") + + # Activer la sortie de l'instrument si nécessaire + if output_status != "on": + keithley.output("on") + + # Lire le courant + current = keithley.curr() # Read the current + + # Read the resistance + resistance = keithley.resistance() # Read the resistance + + # Disable the output + keithley.output("off") # Turn off the output + + # Disconnect from the instrument + keithley.disconnect() + + return OrderedPair(voltages_values, current) diff --git a/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/SET_VOLTAGE/appendix/hardware.md b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/SET_VOLTAGE/appendix/hardware.md new file mode 100644 index 0000000000..7f78a555c4 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/SET_VOLTAGE/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/SET_VOLTAGE/appendix/media.md b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/SET_VOLTAGE/appendix/media.md new file mode 100644 index 0000000000..8bcee9be90 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/SET_VOLTAGE/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/SET_VOLTAGE/appendix/notes.md b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/SET_VOLTAGE/appendix/notes.md new file mode 100644 index 0000000000..04aded2ec9 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/SET_VOLTAGE/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/SET_VOLTAGE/examples/EX1/app.json b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/SET_VOLTAGE/examples/EX1/app.json new file mode 100644 index 0000000000..9fe59cd184 --- /dev/null +++ b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/SET_VOLTAGE/examples/EX1/app.json @@ -0,0 +1,97 @@ +{ + "rfInstance": { + "nodes": [ + { + "width": 150, + "height": 180, + "id": "SET_VOLTAGE-12c8036a-06c1-412e-8bf6-2734a57c448e", + "type": "IO", + "data": { + "id": "SET_VOLTAGE-12c8036a-06c1-412e-8bf6-2734a57c448e", + "label": "SET VOLTAGE", + "func": "SET_VOLTAGE", + "type": "IO", + "ctrls": { + "voltage": { + "type": "int", + "default": 2, + "desc": null, + "overload": null, + "functionName": "SET_VOLTAGE", + "param": "voltage", + "value": 2 + }, + "voltage_range": { + "type": "int", + "default": 10, + "desc": null, + "overload": null, + "functionName": "SET_VOLTAGE", + "param": "voltage_range", + "value": 10 + }, + "current_range": { + "type": "int", + "default": 1, + "desc": null, + "overload": null, + "functionName": "SET_VOLTAGE", + "param": "current_range", + "value": 1 + } + }, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "Any", + "multiple": false, + "desc": null + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedPair", + "desc": null + } + ], + "pip_dependencies": [ + { + "name": "qcodes", + "v": "0.39.1" + }, + { + "name": "pyvisa-py", + "v": "0.6.3" + }, + { + "name": "pyserial", + "v": "3.5" + } + ], + "path": "PYTHON/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/SET_VOLTAGE/SET_VOLTAGE.py", + "selected": true + }, + "position": { + "x": -156.9124813518792, + "y": -297.17831907410823 + }, + "selected": true, + "positionAbsolute": { + "x": -156.9124813518792, + "y": -297.17831907410823 + }, + "dragging": true + } + ], + "edges": [], + "viewport": { + "x": 819.7643144890276, + "y": 420.4113108673, + "zoom": 0.8915653288195635 + } + } +} \ No newline at end of file diff --git a/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/SET_VOLTAGE/examples/EX1/example.md b/docs/nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/SET_VOLTAGE/examples/EX1/example.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC/TIC.md b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC/TIC.md new file mode 100644 index 0000000000..33403471b2 --- /dev/null +++ b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC/TIC.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/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC/a1-[autogen]/docstring.txt b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC/a1-[autogen]/docstring.txt new file mode 100644 index 0000000000..fc690317e0 --- /dev/null +++ b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC/a1-[autogen]/docstring.txt @@ -0,0 +1,14 @@ +The STEPPER_DRIVER_TIC node controls a stepper motor movement with a TIC driver. + + The user defines the speed and the sleep time between movements. + + (To choose the position, use the STEPPER_DRIVER_TIC_KNOB.) + + Parameters + ---------- + current_limit : int + Defines the current limitation that the stepper motor will receive. + sleep_time : int + Defines the sleep time after moving to each position. + speed : int + Defines the speed of the motor movement (between 0 and 200000). diff --git a/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC/a1-[autogen]/python_code.txt b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC/a1-[autogen]/python_code.txt new file mode 100644 index 0000000000..d2cfda5213 --- /dev/null +++ b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC/a1-[autogen]/python_code.txt @@ -0,0 +1,37 @@ +from flojoy import flojoy, OrderedPair +from typing import Optional +from ticlib import ( + TicUSB, +) # Import the TicUSB library to send command to Tic drivers with USB connection +from time import sleep + + +@flojoy(deps={"ticlib": "0.2.2"}) +def TIC( + default: Optional[OrderedPair] = None, + current_limit: int = 30, + sleep_time: int = 2, + speed: int = 100000, +) -> OrderedPair: + + + # Setting default positions + positions: list[int] = [50, 100, 150, 200] + + # Declaration of the stepper driver + tic: TicUSB = TicUSB() + tic.halt_and_set_position(0) # Set the position to 0 + # Set the current limit of the TIC driver + tic.set_current_limit(current_limit) + tic.energize() # Turn on the driver + tic.exit_safe_start() # The driver is now ready to receive commands + + for i in range(0, len(positions)): + tic.set_max_speed(speed) # Set motor speed + tic.set_target_position(positions[i]) # Set target positions + sleep(sleep_time) + + tic.deenergize() + tic.enter_safe_start() + + return OrderedPair(x=positions, y=positions) diff --git a/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC/appendix/hardware.md b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC/appendix/hardware.md new file mode 100644 index 0000000000..7f78a555c4 --- /dev/null +++ b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC/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/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC/appendix/media.md b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC/appendix/media.md new file mode 100644 index 0000000000..8bcee9be90 --- /dev/null +++ b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC/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/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC/appendix/notes.md b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC/appendix/notes.md new file mode 100644 index 0000000000..04aded2ec9 --- /dev/null +++ b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC/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/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC/examples/EX1/app.json b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC/examples/EX1/app.json new file mode 100644 index 0000000000..4afb8bd038 --- /dev/null +++ b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC/examples/EX1/app.json @@ -0,0 +1,99 @@ +{ + "rfInstance": { + "nodes": [ + { + "width": 150, + "height": 150, + "id": "STEPPER_DRIVER_TIC-deb4fca7-fc18-443d-bd70-f1455a749eff", + "type": "INSTRUMENTS", + "data": { + "id": "STEPPER_DRIVER_TIC-deb4fca7-fc18-443d-bd70-f1455a749eff", + "label": "STEPPER DRIVER TIC", + "func": "STEPPER_DRIVER_TIC", + "type": "INSTRUMENTS", + "ctrls": { + "current_limit": { + "type": "int", + "default": 30, + "functionName": "STEPPER_DRIVER_TIC", + "param": "current_limit", + "value": 30 + }, + "sleep_time": { + "type": "int", + "default": 2, + "functionName": "STEPPER_DRIVER_TIC", + "param": "sleep_time", + "value": 2 + }, + "speed": { + "type": "int", + "default": 100000, + "functionName": "STEPPER_DRIVER_TIC", + "param": "speed", + "value": 100000 + } + }, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedPair", + "multiple": false + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedPair" + } + ], + "pip_dependencies": [ + { + "name": "ticlib", + "v": "0.2.2" + } + ], + "path": "PYTHON/nodes/INSTRUMENTS/STEPPER_MOTOR/STEPPER_DRIVER_TIC/STEPPER_DRIVER_TIC.py", + "selected": false + }, + "position": { + "x": 883.1245033729516, + "y": -2.309719518942927 + }, + "selected": false, + "positionAbsolute": { + "x": 883.1245033729516, + "y": -2.309719518942927 + }, + "dragging": true + } + ], + "edges": [], + "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" + } + } + ] +} \ No newline at end of file diff --git a/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC/examples/EX1/example.md b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC/examples/EX1/example.md new file mode 100644 index 0000000000..fc3caa95ec --- /dev/null +++ b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC/examples/EX1/example.md @@ -0,0 +1,15 @@ +--- +title: STEPPER_DRIVER_TIC +description: This node controls a stepper motor movement with a TIC driver. The user defines the speed and the sleep time between movements. +keyword: [Python, Instrument, Stepper motor control, Python integration with stepper driver, Motion control and automation, Python"-"based stepper motor control, Stepper motor driver integration, Accurate motor movement with Python, Enhance motion control with Python, Streamline motor automation, Precise motor control using Python, Python control of stepper driver TIC] +image: https://raw.githubusercontent.com/flojoy-ai/docs/main/docs/nodes/INSTRUMENTS/STEPPER_MOTOR/STEPPER_DRIVER_TIC/examples/EX1/output.jpeg +--- + +In this example, the [`STEPPER_DRIVER_TIC`](https://github.com/flojoy-io/nodes/blob/main/INSTRUMENTS/STEPPER_MOTOR/STEPPER_DRIVER_TIC/STEPPER_DRIVER_TIC.py) node controls a stepper motor movement with a TIC driver. + +First, the user must define the current limitation, which depends on the motor's size and model. +After that, he can set the speed and choose the sleep time between movements. + +Then, after clicking the PLAY button, the motor will move between the four default positions. (To choose positions, use the [`STEPPER_DRIVER_TIC_KNOB`](https://github.com/flojoy-io/nodes/blob/main/INSTRUMENTS/STEPPER_MOTOR/STEPPER_DRIVER_TIC_KNOB/STEPPER_DRIVER_TIC_KNOB.py) node.) + +To create a repetitive movement, use the [`LOOP`](https://github.com/flojoy-io/nodes/blob/main/LOGIC_GATES/LOOPS/LOOP/LOOP.py) node. \ No newline at end of file diff --git a/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC_KNOB/TIC_KNOB.md b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC_KNOB/TIC_KNOB.md new file mode 100644 index 0000000000..ddbd451d7c --- /dev/null +++ b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC_KNOB/TIC_KNOB.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/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC_KNOB/a1-[autogen]/docstring.txt b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC_KNOB/a1-[autogen]/docstring.txt new file mode 100644 index 0000000000..447ce525e3 --- /dev/null +++ b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC_KNOB/a1-[autogen]/docstring.txt @@ -0,0 +1,14 @@ +The STEPPER_DRIVER_TIC_KNOB controls a stepper motor movement with a TIC driver. + + The user controls the motor rotation with the knob position in the node's parameters. + + Parameters + ---------- + knob_value : int + Defines the position of the motor (rotational movement). + current_limit : int + Defines the current limitation that the stepper motor will receive. + sleep_time : int + Defines the sleep time after moving to each position. + speed : int + Defines the speed of the motor movement (between 0 and 200000). diff --git a/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC_KNOB/a1-[autogen]/python_code.txt b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC_KNOB/a1-[autogen]/python_code.txt new file mode 100644 index 0000000000..2f98079318 --- /dev/null +++ b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC_KNOB/a1-[autogen]/python_code.txt @@ -0,0 +1,41 @@ +from flojoy import flojoy, OrderedPair +from typing import Optional + +# Import the TicUSB library to send command to Tic drivers with USB connection +from ticlib import TicUSB +from time import sleep + + +@flojoy(deps={"ticlib": "0.2.2"}) +def TIC_KNOB( + default: Optional[OrderedPair] = None, + knob_value: int = 0, + current_limit: int = 30, + sleep_time: int = 2, + speed: int = 200000, +) -> OrderedPair: + + + # Converting the knob value into a position + knob_position: int = 2 * knob_value + + # Declaration of the stepper driver (You can add serial number to specify the driver) + tic: TicUSB = TicUSB() + # Set the current limit for the driver TIC + tic.set_current_limit(current_limit) + tic.energize() # Turn on the driver + tic.exit_safe_start() # The driver is now ready to receive commands + # Set maximum speed for the motor during first movement. + tic.set_max_speed(speed) + + tic.halt_and_set_position(0) # Set initial position to origin + sleep(sleep_time) + + # Set target position for the first movement + tic.set_target_position(knob_position) + sleep(sleep_time) + + tic.deenergize() + tic.enter_safe_start() + + return OrderedPair(x=knob_position, y=speed) diff --git a/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC_KNOB/appendix/hardware.md b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC_KNOB/appendix/hardware.md new file mode 100644 index 0000000000..7f78a555c4 --- /dev/null +++ b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC_KNOB/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/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC_KNOB/appendix/media.md b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC_KNOB/appendix/media.md new file mode 100644 index 0000000000..8bcee9be90 --- /dev/null +++ b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC_KNOB/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/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC_KNOB/appendix/notes.md b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC_KNOB/appendix/notes.md new file mode 100644 index 0000000000..04aded2ec9 --- /dev/null +++ b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC_KNOB/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/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC_KNOB/examples/EX1/app.json b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC_KNOB/examples/EX1/app.json new file mode 100644 index 0000000000..e0a12da8f6 --- /dev/null +++ b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC_KNOB/examples/EX1/app.json @@ -0,0 +1,106 @@ +{ + "rfInstance": { + "nodes": [ + { + "width": 150, + "height": 150, + "id": "STEPPER_DRIVER_TIC_KNOB-3b234e79-4648-4661-a8e8-3e14b3d0e72b", + "type": "INSTRUMENTS", + "data": { + "id": "STEPPER_DRIVER_TIC_KNOB-3b234e79-4648-4661-a8e8-3e14b3d0e72b", + "label": "STEPPER DRIVER TIC KNOB", + "func": "STEPPER_DRIVER_TIC_KNOB", + "type": "INSTRUMENTS", + "ctrls": { + "knob_value": { + "type": "int", + "default": 0, + "functionName": "STEPPER_DRIVER_TIC_KNOB", + "param": "knob_value", + "value": 0 + }, + "current_limit": { + "type": "int", + "default": 30, + "functionName": "STEPPER_DRIVER_TIC_KNOB", + "param": "current_limit", + "value": 30 + }, + "sleep_time": { + "type": "int", + "default": 2, + "functionName": "STEPPER_DRIVER_TIC_KNOB", + "param": "sleep_time", + "value": 2 + }, + "speed": { + "type": "int", + "default": 200000, + "functionName": "STEPPER_DRIVER_TIC_KNOB", + "param": "speed", + "value": 200000 + } + }, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedPair", + "multiple": false + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedPair" + } + ], + "pip_dependencies": [ + { + "name": "ticlib", + "v": "0.2.2" + } + ], + "path": "PYTHON/nodes/INSTRUMENTS/STEPPER_MOTOR/STEPPER_DRIVER_TIC_KNOB/STEPPER_DRIVER_TIC_KNOB.py", + "selected": false + }, + "position": { + "x": 934.1949826356821, + "y": -1.452956731347598 + }, + "selected": false, + "positionAbsolute": { + "x": 934.1949826356821, + "y": -1.452956731347598 + }, + "dragging": true + } + ], + "edges": [], + "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" + } + } + ] +} \ No newline at end of file diff --git a/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC_KNOB/examples/EX1/example.md b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC_KNOB/examples/EX1/example.md new file mode 100644 index 0000000000..fdb3688444 --- /dev/null +++ b/docs/nodes/IO/MOTION/MOTOR_DRIVER/STEPPER/POLULU/TIC_KNOB/examples/EX1/example.md @@ -0,0 +1,14 @@ +--- +title: STEPPER_DRIVER_TIC_KNOB +description: In this example, the STEPPER_DRIVER_TIC_KNOB node controls a stepper motor movement with a TIC driver. It allows you to control the motor's rotation with a KNOB button. From 0 to 100 corresponds to a rotation between 0 and 360 degrees. +keyword: [Python, Instrument, Stepper motor control with knob, Python integration with stepper driver, Motion control and automation, Python"-"based stepper motor control, Stepper motor driver integration, Accurate motor movement with Python, Enhance motion control with knob, Streamline motor automation, Precise motor control using Python, Python control of stepper driver TIC with knob] +image: https://raw.githubusercontent.com/flojoy-ai/docs/main/docs/nodes/INSTRUMENTS/STEPPER_MOTOR/STEPPER_DRIVER_TIC_KNOB/examples/EX1/output.jpeg +--- + +In this example, the [`STEPPER_DRIVER_TIC_KNOB`](https://github.com/flojoy-io/nodes/blob/main/INSTRUMENTS/STEPPER_MOTOR/STEPPER_DRIVER_TIC_KNOB/STEPPER_DRIVER_TIC_KNOB.py) node controls a stepper motor movement with a TIC driver. It allows you to control the motor's rotation with a KNOB button. (From 0 to 100 corresponds to a rotation between 0 and 360 degrees.) + +First, the user must define the current limitation, which depends on the motor's size and model. After that, he can set the speed, the rotation, and the sleep time to create a specific movement for different applications. Then, after clicking the PLAY button, the motor will start moving. + +After updating the knob position, click on PLAY again to initiate a new movement. + +To create a repetitive movement, use the [`LOOP`](https://github.com/flojoy-io/nodes/blob/main/LOGIC_GATES/LOOPS/LOOP/LOOP.py) and [`GOTO`](https://github.com/flojoy-io/nodes/blob/main/LOGIC_GATES/LOOPS/GOTO/GOTO.py) nodes. \ No newline at end of file diff --git a/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/SINGLE_MEASUREMENT.md b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/SINGLE_MEASUREMENT.md new file mode 100644 index 0000000000..a1fd2999e1 --- /dev/null +++ b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/SINGLE_MEASUREMENT.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/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/a1-[autogen]/docstring.txt b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/a1-[autogen]/docstring.txt new file mode 100644 index 0000000000..a21e3b24af --- /dev/null +++ b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/a1-[autogen]/docstring.txt @@ -0,0 +1,8 @@ +The SERIAL_SINGLE_MEASUREMENT node takes a single reading of data from an Ardunio or a similar serial device. + + Parameters + ---------- + baudrate : int + Baud rate for the serial communication. + comport : string + Defines the comunication port on which the serial device is connected. diff --git a/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/a1-[autogen]/python_code.txt b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/a1-[autogen]/python_code.txt new file mode 100644 index 0000000000..570b2b9946 --- /dev/null +++ b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/a1-[autogen]/python_code.txt @@ -0,0 +1,25 @@ +from flojoy import flojoy, OrderedPair +from typing import Optional +import serial +import numpy as np + + +@flojoy(deps={"pyserial": "3.5"}) +def SINGLE_MEASUREMENT( + default: Optional[OrderedPair] = None, + comport: str = "/dev/ttyUSB0", + baudrate: int = 9600, +) -> OrderedPair: + + + ser = serial.Serial(comport, timeout=1, baudrate=baudrate) + s = "" + while s == "": + s = ser.readline().decode() + + reading = s[:-2].split(",") + reading = np.array(reading) # Create an array + reading = reading.astype("float64") # Convert the array to float + x = np.arange(0, reading.size) # Create a second array + + return OrderedPair(x=x, y=reading) diff --git a/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/appendix/hardware.md b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/appendix/hardware.md new file mode 100644 index 0000000000..7f78a555c4 --- /dev/null +++ b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/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/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/appendix/media.md b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/appendix/media.md new file mode 100644 index 0000000000..8bcee9be90 --- /dev/null +++ b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/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/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/appendix/notes.md b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/appendix/notes.md new file mode 100644 index 0000000000..04aded2ec9 --- /dev/null +++ b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/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/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/examples/EX1/app.json b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/examples/EX1/app.json new file mode 100644 index 0000000000..66ab70fb0a --- /dev/null +++ b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/examples/EX1/app.json @@ -0,0 +1,213 @@ +{ + "rfInstance": { + "nodes": [ + { + "width": 192, + "height": 192, + "id": "SERIAL_SINGLE_MEASUREMENT-06ada52e-5ac9-4554-abbc-3c0de62b9658", + "type": "INSTRUMENTS", + "data": { + "id": "SERIAL_SINGLE_MEASUREMENT-06ada52e-5ac9-4554-abbc-3c0de62b9658", + "label": "SERIAL SINGLE MEASUREMENT", + "func": "SERIAL_SINGLE_MEASUREMENT", + "type": "INSTRUMENTS", + "ctrls": { + "comport": { + "type": "str", + "default": "/dev/ttyUSB0", + "desc": "Defines the comunication port on which the serial device is connected.", + "functionName": "SERIAL_SINGLE_MEASUREMENT", + "param": "comport", + "value": "/dev/ttyACM0" + }, + "baudrate": { + "type": "int", + "default": 9600, + "desc": "Baud rate for the serial communication.", + "functionName": "SERIAL_SINGLE_MEASUREMENT", + "param": "baudrate", + "value": 9600 + } + }, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedPair", + "multiple": false, + "desc": null + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedPair", + "desc": null + } + ], + "pip_dependencies": [ + { + "name": "pyserial", + "v": "3.5" + } + ], + "path": "PYTHON/nodes/INSTRUMENTS/SERIAL/SERIAL_SINGLE_MEASUREMENT/SERIAL_SINGLE_MEASUREMENT.py", + "selected": false + }, + "position": { + "x": 337.2943004768793, + "y": -102.49963457468456 + }, + "selected": false, + "positionAbsolute": { + "x": 337.2943004768793, + "y": -102.49963457468456 + }, + "dragging": true + }, + { + "width": 96, + "height": 96, + "id": "LOOP-713bb2c3-787f-497d-a15a-5ceb4d2dad92", + "type": "LOGIC_GATES", + "data": { + "id": "LOOP-713bb2c3-787f-497d-a15a-5ceb4d2dad92", + "label": "LOOP", + "func": "LOOP", + "type": "LOGIC_GATES", + "ctrls": { + "num_loops": { + "type": "int", + "default": -1, + "desc": "number of times to iterate through body nodes, default is \"-1\" meaning infinity.", + "functionName": "LOOP", + "param": "num_loops", + "value": -1 + } + }, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "Any", + "multiple": false, + "desc": null + } + ], + "outputs": [ + { + "name": "body", + "id": "body", + "type": "Any", + "desc": null + }, + { + "name": "end", + "id": "end", + "type": "Any", + "desc": null + } + ], + "path": "PYTHON/nodes/LOGIC_GATES/LOOPS/LOOP/LOOP.py", + "selected": false + }, + "position": { + "x": 61.929002037770914, + "y": -25.79247882166105 + }, + "selected": false, + "positionAbsolute": { + "x": 61.929002037770914, + "y": -25.79247882166105 + }, + "dragging": true + }, + { + "width": 225, + "height": 226, + "id": "TABLE-915065a2-936c-4c61-a1d4-b4600fed1930", + "type": "VISUALIZERS", + "data": { + "id": "TABLE-915065a2-936c-4c61-a1d4-b4600fed1930", + "label": "TABLE", + "func": "TABLE", + "type": "VISUALIZERS", + "ctrls": {}, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedTriple|OrderedPair|DataFrame|Vector", + "multiple": false, + "desc": "the DataContainer to be visualized" + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "Plotly", + "desc": "the DataContainer containing Plotly Table visualization" + } + ], + "path": "PYTHON/nodes/VISUALIZERS/PLOTLY/TABLE/TABLE.py", + "selected": true + }, + "position": { + "x": 699.5415786140495, + "y": -122.4081124323938 + }, + "selected": true, + "positionAbsolute": { + "x": 699.5415786140495, + "y": -122.4081124323938 + }, + "dragging": true + } + ], + "edges": [ + { + "source": "LOOP-713bb2c3-787f-497d-a15a-5ceb4d2dad92", + "sourceHandle": "body", + "target": "SERIAL_SINGLE_MEASUREMENT-06ada52e-5ac9-4554-abbc-3c0de62b9658", + "targetHandle": "default", + "id": "reactflow__edge-LOOP-713bb2c3-787f-497d-a15a-5ceb4d2dad92body-SERIAL_SINGLE_MEASUREMENT-06ada52e-5ac9-4554-abbc-3c0de62b9658default" + }, + { + "source": "SERIAL_SINGLE_MEASUREMENT-06ada52e-5ac9-4554-abbc-3c0de62b9658", + "sourceHandle": "default", + "target": "TABLE-915065a2-936c-4c61-a1d4-b4600fed1930", + "targetHandle": "default", + "id": "reactflow__edge-SERIAL_SINGLE_MEASUREMENT-06ada52e-5ac9-4554-abbc-3c0de62b9658default-TABLE-915065a2-936c-4c61-a1d4-b4600fed1930default" + } + ], + "viewport": { + "x": 815.7959874736157, + "y": 352.53461082817995, + "zoom": 0.7476193625116623 + } + }, + "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" + } + } + ] +} \ No newline at end of file diff --git a/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/examples/EX1/example.md b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/examples/EX1/example.md new file mode 100644 index 0000000000..fa35be3518 --- /dev/null +++ b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/examples/EX1/example.md @@ -0,0 +1,37 @@ +--- +title: SERIAL_SINGLE_MEASUREMENT +description: In this example, we use the SERIAL_SINGLE_MEASUREMENT node to extract some measurements received from an Arduino microcontroller and visualize the output. +keyword: [Python, Instrument, Serial communication measurement, Python serial instrument integration, Data acquisition and analysis, Python"-"based serial measurement, Serial instrument integration techniques, Accurate measurement with Python, Enhance measurement with serial communication, Streamline data acquisition, Precise measurement using Python, Python control of serial single measurement] +image: https://raw.githubusercontent.com/flojoy-ai/docs/main/docs/nodes/INSTRUMENTS/SERIAL/SERIAL_SINGLE_MEASUREMENT/examples/EX1/output.jpeg +--- + +In this example, we use the `SERIAL_SINGLE_MEASUREMENT` node to extract some measurements +received from an Arduino microcontroller and visualize the output. + +First, you need to connect the Arduino to your computer. Then, you'll need to upload an Arduino script to your board to define its behavior (with the Arduino IDE software). When your Arduino sends data to the serial monitor of the Arduino IDE, you can start using the [`SERIAL_SINGLE_MEASUREMENT`](https://github.com/flojoy-io/nodes/blob/main/INSTRUMENTS/SERIAL/SERIAL_SINGLE_MEASUREMENT/SERIAL_SINGLE_MEASUREMENT.py) node. After placing the node on Flojoy, you must specify the communication port to which the Arduino is connected. This port is found in the Arduino IDE software under _Tools/Port_. + +The [`SERIAL_SINGLE_MEASUREMENT`](https://github.com/flojoy-io/nodes/blob/main/INSTRUMENTS/SERIAL/SERIAL_SINGLE_MEASUREMENT/SERIAL_SINGLE_MEASUREMENT.py) node receives data through serial communication with the Arduino, and stores the measured values in a table called `reading`. The Arduino then prints new values on the serial console for each loop. The [`SERIAL_SINGLE_MEASUREMENT`](https://github.com/flojoy-io/nodes/blob/main/INSTRUMENTS/SERIAL/SERIAL_SINGLE_MEASUREMENT/SERIAL_SINGLE_MEASUREMENT.py) node extracts a measurement (which can contain single or multiple values, as seen in the output). + +The [`TABLE`](https://github.com/flojoy-io/nodes/blob/main/VISUALIZERS/PLOTLY/TABLE/TABLE.py) node displays all values stored in the single measurement. + +**Remarks about the Arduino code:** + +This example works with the `arduino_example.ino` Arduino code (see Appendix). + +The last line that the Arduino should return, is the data with a new line at the end (i.e. `println()`). + +For example: + + print(reading0) + print(",") + println(reading1) + +The [`SERIAL_SINGLE_MEASUREMENT`](https://github.com/flojoy-io/nodes/blob/main/INSTRUMENTS/SERIAL/SERIAL_SINGLE_MEASUREMENT/SERIAL_SINGLE_MEASUREMENT.py) node receives data from the Arduino serial console as a string and splits it using "," as a separator. It then returns the values measured in a list called `reading`. + +**Update the Single Measurement with a Loop:** + +To update the values received from the Arduino, use the [`LOOP`](https://github.com/flojoy-io/nodes/blob/main/LOGIC_GATES/LOOPS/LOOP/LOOP.py) node to create a loop around the [`SERIAL_SINGLE_MEASUREMENT`](https://github.com/flojoy-io/nodes/blob/main/INSTRUMENTS/SERIAL/SERIAL_SINGLE_MEASUREMENT/SERIAL_SINGLE_MEASUREMENT.py) and [`TABLE`](https://github.com/flojoy-io/nodes/blob/main/VISUALIZERS/PLOTLY/TABLE/TABLE.py) nodes. + +The loop allows the user to update measurements, but only the last measurement will be saved and displayed. + +To record all the measurements for a given period, use the [`SERIAL_TIMESERIES`](https://github.com/flojoy-io/nodes/blob/main/INSTRUMENTS/SERIAL/SERIAL_TIMESERIES/SERIAL_TIMESERIES.py) node. diff --git a/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/TIMESERIES1.md b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/TIMESERIES1.md new file mode 100644 index 0000000000..8b1239f1d0 --- /dev/null +++ b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/TIMESERIES1.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/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/a1-[autogen]/docstring.txt b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/a1-[autogen]/docstring.txt new file mode 100644 index 0000000000..660071c9eb --- /dev/null +++ b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/a1-[autogen]/docstring.txt @@ -0,0 +1,15 @@ +The SERIAL_TIMESERIES node extracts simple time-dependent 1D data from an Ardunio or a similar serial device. + + Parameters + ---------- + num_readings : int + Number of points to record. + record_period : float + Length between two recordings in seconds. + baudrate : int + Baud rate for the serial device. + comport : string + COM port of the serial device. + + num_readings * record_period : + Is roughly the run length in seconds. diff --git a/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/a1-[autogen]/python_code.txt b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/a1-[autogen]/python_code.txt new file mode 100644 index 0000000000..c1697f9641 --- /dev/null +++ b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/a1-[autogen]/python_code.txt @@ -0,0 +1,60 @@ +from flojoy import flojoy, OrderedPair +from time import sleep +from typing import Optional +import serial +import numpy as np +from datetime import datetime + + +@flojoy(deps={"pyserial": "3.5"}) +def TIMESERIES1( + default: Optional[OrderedPair] = None, + comport: str = "/dev/ttyUSB0", + baudrate: int = 9600, + num_readings: int = 100, + record_period: int = 1, +) -> OrderedPair: + + + ser = serial.Serial(comport, timeout=1, baudrate=baudrate) + readings = [] + times = [] + # The first reading is commonly empty. + s = ser.readline().decode() + + for i in range(num_readings): + ts = datetime.now() + s = ser.readline().decode() + # Some readings may be empty. + if s != "": + reading = s[:-2].split(",") + if len(reading) == 1: + reading = reading[0] + readings.append(reading) + + ts = datetime.now() + seconds = float( + ts.hour * 3600 + ts.minute * 60 + ts.second + ts.microsecond / 10**6 + ) + + times.append(seconds) + + if len(times) > 0: + time1 = seconds - times[i] + else: + # Estimate execution time. + time1 = 0.1 + + if time1 < record_period: + sleep(record_period - time1) + + times = np.array(times) + try: + times -= times[0] + except IndexError: + raise IndexError("No data detected from the Arduino") + + readings = np.array(readings) + readings = readings.astype("float64") + + return OrderedPair(x=times, y=readings) diff --git a/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/appendix/hardware.md b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/appendix/hardware.md new file mode 100644 index 0000000000..7f78a555c4 --- /dev/null +++ b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/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/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/appendix/media.md b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/appendix/media.md new file mode 100644 index 0000000000..8bcee9be90 --- /dev/null +++ b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/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/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/appendix/notes.md b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/appendix/notes.md new file mode 100644 index 0000000000..04aded2ec9 --- /dev/null +++ b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/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/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/examples/EX1/app.json b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/examples/EX1/app.json new file mode 100644 index 0000000000..60e250d56f --- /dev/null +++ b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/examples/EX1/app.json @@ -0,0 +1,154 @@ +{ + "rfInstance": { + "nodes": [ + { + "width": 150, + "height": 150, + "id": "SERIAL_TIMESERIES-d9520c8e-120d-488b-a042-dac8b39b294c", + "type": "INSTRUMENTS", + "data": { + "id": "SERIAL_TIMESERIES-d9520c8e-120d-488b-a042-dac8b39b294c", + "label": "SERIAL TIMESERIES", + "func": "SERIAL_TIMESERIES", + "type": "INSTRUMENTS", + "ctrls": { + "comport": { + "type": "str", + "default": "/dev/ttyUSB0", + "functionName": "SERIAL_TIMESERIES", + "param": "comport", + "value": "/dev/ttyUSB0" + }, + "baudrate": { + "type": "int", + "default": 9600, + "functionName": "SERIAL_TIMESERIES", + "param": "baudrate", + "value": 9600 + }, + "num_readings": { + "type": "int", + "default": 100, + "functionName": "SERIAL_TIMESERIES", + "param": "num_readings", + "value": 100 + }, + "record_period": { + "type": "int", + "default": 1, + "functionName": "SERIAL_TIMESERIES", + "param": "record_period", + "value": 1 + } + }, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedPair", + "multiple": false + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedPair" + } + ], + "pip_dependencies": [ + { + "name": "pyserial", + "v": "3.5" + } + ], + "path": "PYTHON/nodes/INSTRUMENTS/SERIAL/SERIAL_TIMESERIES/SERIAL_TIMESERIES.py", + "selected": false + }, + "position": { + "x": 353.0843053074072, + "y": 1.629899261204912 + }, + "selected": false, + "positionAbsolute": { + "x": 353.0843053074072, + "y": 1.629899261204912 + }, + "dragging": true + }, + { + "width": 225, + "height": 226, + "id": "TABLE-e0ba3b06-fcc8-40a5-bb12-14370fe009e9", + "type": "VISUALIZERS", + "data": { + "id": "TABLE-e0ba3b06-fcc8-40a5-bb12-14370fe009e9", + "label": "TABLE", + "func": "TABLE", + "type": "VISUALIZERS", + "ctrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedTriple|OrderedPair|DataFrame", + "multiple": false + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "Plotly" + } + ], + "path": "PYTHON/nodes/VISUALIZERS/PLOTLY/TABLE/TABLE.py", + "selected": false + }, + "position": { + "x": 815.4592095712483, + "y": -29.91266050320587 + }, + "selected": false, + "positionAbsolute": { + "x": 815.4592095712483, + "y": -29.91266050320587 + }, + "dragging": true + } + ], + "edges": [ + { + "source": "SERIAL_TIMESERIES-d9520c8e-120d-488b-a042-dac8b39b294c", + "sourceHandle": "default", + "target": "TABLE-e0ba3b06-fcc8-40a5-bb12-14370fe009e9", + "targetHandle": "default", + "id": "reactflow__edge-SERIAL_TIMESERIES-d9520c8e-120d-488b-a042-dac8b39b294cdefault-TABLE-e0ba3b06-fcc8-40a5-bb12-14370fe009e9default" + } + ], + "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" + } + } + ] +} \ No newline at end of file diff --git a/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/examples/EX1/example.md b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/examples/EX1/example.md new file mode 100644 index 0000000000..15facff381 --- /dev/null +++ b/docs/nodes/IO/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/examples/EX1/example.md @@ -0,0 +1,22 @@ +--- +title: SERIAL_TIMESERIES +description: In this example, we use the SERIAL_TIMESERIES node to extract some time-dependent measurements received from an Arduino microcontroller and visualize the output. +keyword: [Python, Instrument, Serial communication timeseries, Python serial data acquisition, Time"-"series data analysis, Python-based serial data collection, Serial data acquisition techniques, Accurate timeseries recording with Python, Enhance data analysis with serial communication, Streamline timeseries data acquisition, Precise data collection using Python, Python control of serial timeseries data] +image: https://raw.githubusercontent.com/flojoy-ai/docs/main/docs/nodes/INSTRUMENTS/SERIAL/SERIAL_TIMESERIES/examples/EX1/output.jpeg +--- + +In this example, we use the `SERIAL_TIMESERIES` node to extract some time-dependent measurements received from an Arduino microcontroller, and visualize the output. + +First, you need to connect the Arduino to your computer. Then, you'll need to upload an Arduino script to your board to define its behavior (with the Arduino IDE software). When your Arduino sends data to the serial monitor of the Arduino IDE, you can start using the [`SERIAL_TIMESERIES`](https://github.com/flojoy-io/nodes/blob/main/INSTRUMENTS/SERIAL/SERIAL_TIMESERIES/SERIAL_TIMESERIES.py) node. After placing the node on Flojoy, you must specify the communication port to which the Arduino is connected. This port is found in the Arduino IDE software under _Tools/Port_. + +The [`SERIAL_TIMESERIES`](https://github.com/flojoy-ai/nodes/blob/main/INSTRUMENTS/SERIAL/SERIAL_TIMESERIES/SERIAL_TIMESERIES.py) node receives data through serial communication with the Arduino, and stores the measured values in a table named `readings`. The Arduino prints new values on the serial console for each loop. The [`SERIAL_TIMESERIES`](https://github.com/flojoy-ai/nodes/blob/main/INSTRUMENTS/SERIAL/SERIAL_TIMESERIES/SERIAL_TIMESERIES.py) node then extracts a single measurement (for this node, each time dependant measurement must contain only one value). + +The [`TABLE`](https://github.com/flojoy-io/nodes/blob/main/VISUALIZERS/PLOTLY/TABLE/TABLE.py) node displays all values stored in the timeseries measurement. + +**Remarks about the Arduino code:** + +In order to use this node properly, you need to print one value per line using the command (i.e. `println()`). + +For example: + + println(reading) 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..cd2065d1f1 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 @@ -1,4 +1,4 @@ -from flojoy import flojoy, Image, DataFrame, Grayscale, TextBlob +from flojoy import flojoy, Image, DataFrame, TextBlob from typing import Literal, Optional import numpy as np from PIL import Image as PIL_Image @@ -78,3 +78,8 @@ def LOCAL_FILE( file_path = get_file_path(file_path) df = pd.read_excel(file_path) return DataFrame(df=df) + case "mp3" | "wav": + file_path = get_file_path(file_path) + with open(file_path, "rb") as inp: + audio_bytes_stream = inp.read() + return Bytes(b=audio_bytes_stream) diff --git a/docs/nodes/LOGIC_GATES/LOOPS/APPEND/a1-[autogen]/python_code.txt b/docs/nodes/LOGIC_GATES/LOOPS/APPEND/a1-[autogen]/python_code.txt index 4e80c92b7c..a7b4574ac3 100644 --- a/docs/nodes/LOGIC_GATES/LOOPS/APPEND/a1-[autogen]/python_code.txt +++ b/docs/nodes/LOGIC_GATES/LOOPS/APPEND/a1-[autogen]/python_code.txt @@ -1,4 +1,4 @@ -import numpy as np +from numpy import append from flojoy import flojoy, OrderedPair, Matrix, DataFrame, Vector, Scalar @@ -25,41 +25,41 @@ def APPEND( ) ) - x = np.append(x0, x1) - y = np.append(y0, y1) + x = append(x0, x1) + y = append(y0, y1) return OrderedPair(x=x, y=y) elif isinstance(primary_dp, Matrix) and isinstance(secondary_dp, Matrix): m0 = primary_dp.m m1 = secondary_dp.m - m = np.append(m0, m1, axis=0) + m = append(m0, m1, axis=0) return Matrix(m=m) elif isinstance(primary_dp, Vector) and isinstance(secondary_dp, Vector): v0 = primary_dp.v v1 = secondary_dp.v - v = np.append(v0, v1, axis=0) + v = append(v0, v1, axis=0) return Vector(v=v) elif isinstance(primary_dp, Vector) and isinstance(secondary_dp, Scalar): v0 = primary_dp.v v1 = secondary_dp.c - v = np.append(v0, [v1], axis=0) + v = append(v0, [v1], axis=0) return Vector(v=v) elif isinstance(primary_dp, Scalar) and isinstance(secondary_dp, Scalar): c0 = primary_dp.c c1 = secondary_dp.c - v = np.append([c0], [c1], axis=0) + v = append([c0], [c1], axis=0) return Vector(v=v) else: df0 = primary_dp.m df1 = secondary_dp.m - df = np.append(df0, df1, axis=0) + df = append(df0, df1, axis=0) return DataFrame(df=df) diff --git a/docs/nodes/TRANSFORMERS/ORDERED_PAIR_MANIPULATION/ORDERED_PAIR_XY_INVERT/ORDERED_PAIR_XY_INVERT.md b/docs/nodes/TRANSFORMERS/ORDERED_PAIR_MANIPULATION/ORDERED_PAIR_XY_INVERT/ORDERED_PAIR_XY_INVERT.md new file mode 100644 index 0000000000..dfe7b7113b --- /dev/null +++ b/docs/nodes/TRANSFORMERS/ORDERED_PAIR_MANIPULATION/ORDERED_PAIR_XY_INVERT/ORDERED_PAIR_XY_INVERT.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/TRANSFORMERS/ORDERED_PAIR_MANIPULATION/ORDERED_PAIR_XY_INVERT/a1-[autogen]/docstring.txt b/docs/nodes/TRANSFORMERS/ORDERED_PAIR_MANIPULATION/ORDERED_PAIR_XY_INVERT/a1-[autogen]/docstring.txt new file mode 100644 index 0000000000..833af5506e --- /dev/null +++ b/docs/nodes/TRANSFORMERS/ORDERED_PAIR_MANIPULATION/ORDERED_PAIR_XY_INVERT/a1-[autogen]/docstring.txt @@ -0,0 +1,12 @@ +The ORDERED_PAIR_XY_INVERT node returns the OrderedPair + where the axes are inverted + + Inputs + ------ + default : OrderedPair + The input OrderedPair that we would like to invert the axes + + Returns + ------- + OrderedPair + The OrderedPair that is inverted diff --git a/docs/nodes/TRANSFORMERS/ORDERED_PAIR_MANIPULATION/ORDERED_PAIR_XY_INVERT/a1-[autogen]/python_code.txt b/docs/nodes/TRANSFORMERS/ORDERED_PAIR_MANIPULATION/ORDERED_PAIR_XY_INVERT/a1-[autogen]/python_code.txt new file mode 100644 index 0000000000..4343abd502 --- /dev/null +++ b/docs/nodes/TRANSFORMERS/ORDERED_PAIR_MANIPULATION/ORDERED_PAIR_XY_INVERT/a1-[autogen]/python_code.txt @@ -0,0 +1,10 @@ +from flojoy import flojoy, OrderedPair + + +@flojoy +def ORDERED_PAIR_XY_INVERT( + default: OrderedPair, +) -> OrderedPair: + + + return OrderedPair(x=default.y, y=default.x) diff --git a/docs/nodes/TRANSFORMERS/ORDERED_PAIR_MANIPULATION/ORDERED_PAIR_XY_INVERT/appendix/hardware.md b/docs/nodes/TRANSFORMERS/ORDERED_PAIR_MANIPULATION/ORDERED_PAIR_XY_INVERT/appendix/hardware.md new file mode 100644 index 0000000000..7f78a555c4 --- /dev/null +++ b/docs/nodes/TRANSFORMERS/ORDERED_PAIR_MANIPULATION/ORDERED_PAIR_XY_INVERT/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/TRANSFORMERS/ORDERED_PAIR_MANIPULATION/ORDERED_PAIR_XY_INVERT/appendix/media.md b/docs/nodes/TRANSFORMERS/ORDERED_PAIR_MANIPULATION/ORDERED_PAIR_XY_INVERT/appendix/media.md new file mode 100644 index 0000000000..8bcee9be90 --- /dev/null +++ b/docs/nodes/TRANSFORMERS/ORDERED_PAIR_MANIPULATION/ORDERED_PAIR_XY_INVERT/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/TRANSFORMERS/ORDERED_PAIR_MANIPULATION/ORDERED_PAIR_XY_INVERT/appendix/notes.md b/docs/nodes/TRANSFORMERS/ORDERED_PAIR_MANIPULATION/ORDERED_PAIR_XY_INVERT/appendix/notes.md new file mode 100644 index 0000000000..04aded2ec9 --- /dev/null +++ b/docs/nodes/TRANSFORMERS/ORDERED_PAIR_MANIPULATION/ORDERED_PAIR_XY_INVERT/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/TRANSFORMERS/ORDERED_PAIR_MANIPULATION/ORDERED_PAIR_XY_INVERT/examples/EX1/app.json b/docs/nodes/TRANSFORMERS/ORDERED_PAIR_MANIPULATION/ORDERED_PAIR_XY_INVERT/examples/EX1/app.json new file mode 100644 index 0000000000..4a0cae53b8 --- /dev/null +++ b/docs/nodes/TRANSFORMERS/ORDERED_PAIR_MANIPULATION/ORDERED_PAIR_XY_INVERT/examples/EX1/app.json @@ -0,0 +1,369 @@ +{ + "rfInstance": { + "nodes": [ + { + "width": 160, + "height": 160, + "id": "ORDERED_PAIR_XY_INVERT-2792706c-8d3b-4d14-ab86-25b7b02afbff", + "type": "TRANSFORMERS", + "data": { + "id": "ORDERED_PAIR_XY_INVERT-2792706c-8d3b-4d14-ab86-25b7b02afbff", + "label": "ORDERED PAIR XY INVERT", + "func": "ORDERED_PAIR_XY_INVERT", + "type": "TRANSFORMERS", + "ctrls": {}, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedPair", + "multiple": false, + "desc": "The input OrderedPair that we would like to invert the axis" + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedPair", + "desc": "The OrderedPair that is inverted" + } + ], + "path": "PYTHON/nodes\\TRANSFORMERS\\ORDERED_PAIR_MANIPULATION\\ORDERED_PAIR_XY_INVERT\\ORDERED_PAIR_XY_INVERT.py", + "selected": false + }, + "position": { + "x": 150.97310141564193, + "y": 176.2485798315949 + }, + "selected": false, + "positionAbsolute": { + "x": 150.97310141564193, + "y": 176.2485798315949 + }, + "dragging": true + }, + { + "width": 208, + "height": 96, + "id": "LINSPACE-a4763e5c-fbf5-4e75-b292-7ea368d7c42c", + "type": "GENERATORS", + "data": { + "id": "LINSPACE-a4763e5c-fbf5-4e75-b292-7ea368d7c42c", + "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": 1000 + } + }, + "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 step number of points." + } + ], + "path": "PYTHON/nodes\\GENERATORS\\SIMULATIONS\\LINSPACE\\LINSPACE.py", + "selected": false + }, + "position": { + "x": -473.6771271573732, + "y": -126.59799740553947 + }, + "selected": false, + "positionAbsolute": { + "x": -473.6771271573732, + "y": -126.59799740553947 + }, + "dragging": true + }, + { + "width": 208, + "height": 96, + "id": "LINSPACE-bdc206ef-b69b-40e2-8f38-f6eaeb9f1314", + "type": "GENERATORS", + "data": { + "id": "LINSPACE-bdc206ef-b69b-40e2-8f38-f6eaeb9f1314", + "label": "LINSPACE 1", + "func": "LINSPACE", + "type": "GENERATORS", + "ctrls": { + "start": { + "type": "float", + "default": 10, + "desc": "The start point of the data.", + "overload": null, + "functionName": "LINSPACE", + "param": "start", + "value": 20 + }, + "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": 2000 + } + }, + "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 step number of points." + } + ], + "path": "PYTHON/nodes\\GENERATORS\\SIMULATIONS\\LINSPACE\\LINSPACE.py", + "selected": false + }, + "position": { + "x": -469.41122388328694, + "y": 10.150456437007108 + }, + "selected": false, + "positionAbsolute": { + "x": -469.41122388328694, + "y": 10.150456437007108 + }, + "dragging": true + }, + { + "width": 225, + "height": 226, + "id": "SCATTER-b778eb21-99a8-44f8-9694-07ac47d7b2a0", + "type": "VISUALIZERS", + "data": { + "id": "SCATTER-b778eb21-99a8-44f8-9694-07ac47d7b2a0", + "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 Plotly Scatter visualization" + } + ], + "path": "PYTHON/nodes\\VISUALIZERS\\PLOTLY\\SCATTER\\SCATTER.py", + "selected": false + }, + "position": { + "x": 141.87732476050604, + "y": -114.2086779722151 + }, + "selected": false, + "positionAbsolute": { + "x": 141.87732476050604, + "y": -114.2086779722151 + }, + "dragging": true + }, + { + "width": 225, + "height": 226, + "id": "SCATTER-011cf3e2-6c48-41f8-b600-1d344e28ad61", + "type": "VISUALIZERS", + "data": { + "id": "SCATTER-011cf3e2-6c48-41f8-b600-1d344e28ad61", + "label": "SCATTER 1", + "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 Plotly Scatter visualization" + } + ], + "path": "PYTHON/nodes\\VISUALIZERS\\PLOTLY\\SCATTER\\SCATTER.py", + "selected": false + }, + "position": { + "x": 423.8168712785772, + "y": 141.8525453524494 + }, + "selected": false, + "positionAbsolute": { + "x": 423.8168712785772, + "y": 141.8525453524494 + }, + "dragging": true + }, + { + "width": 160, + "height": 160, + "id": "VECTOR_2_ORDERED_PAIR-00a791c3-063f-4218-9c64-b67d7631398e", + "type": "TRANSFORMERS", + "data": { + "id": "VECTOR_2_ORDERED_PAIR-00a791c3-063f-4218-9c64-b67d7631398e", + "label": "VECTOR 2 ORDERED PAIR", + "func": "VECTOR_2_ORDERED_PAIR", + "type": "TRANSFORMERS", + "ctrls": {}, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "Vector", + "multiple": false, + "desc": "The input vector that will be the x axis of OrderedPair." + }, + { + "name": "y", + "id": "y", + "type": "Vector", + "multiple": false, + "desc": "The input vector that will be the y axis of OrderedPair." + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedPair", + "desc": "The OrderedPair that is generated from the input vectors" + } + ], + "path": "PYTHON/nodes\\TRANSFORMERS\\TYPE_CASTING\\VECTOR_2_ORDERED_PAIR\\VECTOR_2_ORDERED_PAIR.py", + "selected": false + }, + "position": { + "x": -95.64923043132146, + "y": -74.11331295449935 + }, + "selected": false, + "positionAbsolute": { + "x": -95.64923043132146, + "y": -74.11331295449935 + }, + "dragging": true + } + ], + "edges": [ + { + "source": "LINSPACE-a4763e5c-fbf5-4e75-b292-7ea368d7c42c", + "sourceHandle": "default", + "target": "VECTOR_2_ORDERED_PAIR-00a791c3-063f-4218-9c64-b67d7631398e", + "targetHandle": "default", + "id": "reactflow__edge-LINSPACE-a4763e5c-fbf5-4e75-b292-7ea368d7c42cdefault-VECTOR_2_ORDERED_PAIR-00a791c3-063f-4218-9c64-b67d7631398edefault" + }, + { + "source": "LINSPACE-bdc206ef-b69b-40e2-8f38-f6eaeb9f1314", + "sourceHandle": "default", + "target": "VECTOR_2_ORDERED_PAIR-00a791c3-063f-4218-9c64-b67d7631398e", + "targetHandle": "y", + "id": "reactflow__edge-LINSPACE-bdc206ef-b69b-40e2-8f38-f6eaeb9f1314default-VECTOR_2_ORDERED_PAIR-00a791c3-063f-4218-9c64-b67d7631398ey" + }, + { + "source": "VECTOR_2_ORDERED_PAIR-00a791c3-063f-4218-9c64-b67d7631398e", + "sourceHandle": "default", + "target": "SCATTER-b778eb21-99a8-44f8-9694-07ac47d7b2a0", + "targetHandle": "default", + "id": "reactflow__edge-VECTOR_2_ORDERED_PAIR-00a791c3-063f-4218-9c64-b67d7631398edefault-SCATTER-b778eb21-99a8-44f8-9694-07ac47d7b2a0default" + }, + { + "source": "VECTOR_2_ORDERED_PAIR-00a791c3-063f-4218-9c64-b67d7631398e", + "sourceHandle": "default", + "target": "ORDERED_PAIR_XY_INVERT-2792706c-8d3b-4d14-ab86-25b7b02afbff", + "targetHandle": "default", + "id": "reactflow__edge-VECTOR_2_ORDERED_PAIR-00a791c3-063f-4218-9c64-b67d7631398edefault-ORDERED_PAIR_XY_INVERT-2792706c-8d3b-4d14-ab86-25b7b02afbffdefault" + }, + { + "source": "ORDERED_PAIR_XY_INVERT-2792706c-8d3b-4d14-ab86-25b7b02afbff", + "sourceHandle": "default", + "target": "SCATTER-011cf3e2-6c48-41f8-b600-1d344e28ad61", + "targetHandle": "default", + "id": "reactflow__edge-ORDERED_PAIR_XY_INVERT-2792706c-8d3b-4d14-ab86-25b7b02afbffdefault-SCATTER-011cf3e2-6c48-41f8-b600-1d344e28ad61default" + } + ], + "viewport": { + "x": 856.9726609784543, + "y": 419.56285211681103, + "zoom": 0.8897660042407147 + } + } +} \ No newline at end of file diff --git a/docs/nodes/TRANSFORMERS/ORDERED_PAIR_MANIPULATION/ORDERED_PAIR_XY_INVERT/examples/EX1/example.md b/docs/nodes/TRANSFORMERS/ORDERED_PAIR_MANIPULATION/ORDERED_PAIR_XY_INVERT/examples/EX1/example.md new file mode 100644 index 0000000000..2f1e919a9d --- /dev/null +++ b/docs/nodes/TRANSFORMERS/ORDERED_PAIR_MANIPULATION/ORDERED_PAIR_XY_INVERT/examples/EX1/example.md @@ -0,0 +1,5 @@ +In this example, generate a OrderedPair type using `VECTOR_2_ORDERED_PAIR` node. + +Use `ORDERED_PAIR_XY_INVERT` to invert the X and Y axes of the generated output. + +Compare the nodes that is not inverted and inverted using visualization node. \ No newline at end of file diff --git a/docs/nodes/TRANSFORMERS/SIGNAL_PROCESSING/PID/a1-[autogen]/python_code.txt b/docs/nodes/TRANSFORMERS/SIGNAL_PROCESSING/PID/a1-[autogen]/python_code.txt index 962014c832..c0b86e488d 100644 --- a/docs/nodes/TRANSFORMERS/SIGNAL_PROCESSING/PID/a1-[autogen]/python_code.txt +++ b/docs/nodes/TRANSFORMERS/SIGNAL_PROCESSING/PID/a1-[autogen]/python_code.txt @@ -1,4 +1,4 @@ -import numpy as np +from numpy import zeros, append, ndarray from flojoy import flojoy, Scalar, DefaultParams, SmallMemory memory_key = "pid-info" @@ -22,12 +22,12 @@ def PID( data = SmallMemory().read_memory(node_id, memory_key) if data is None: initialize = True - elif type(data) == np.ndarray: + elif type(data) == ndarray: initialize = False else: raise TypeError("Issue reading memory from REDIS.") integral: int = 0 if initialize else data[0] - regulation_error_primes = np.zeros(3) if initialize else data[1:] + regulation_error_primes = zeros(3) if initialize else data[1:] regulation_error = single_input.c integral: float = integral + 0.5 * Ki * ( @@ -50,7 +50,7 @@ def PID( # Now write to memory ... SmallMemory().write_to_memory( - node_id, memory_key, np.append(integral, regulation_error_primes) + node_id, memory_key, append(integral, regulation_error_primes) ) # ... and return the result diff --git a/docs/nodes/TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/TEXT_CONCAT.md b/docs/nodes/TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/TEXT_CONCAT.md new file mode 100644 index 0000000000..6e89750190 --- /dev/null +++ b/docs/nodes/TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/TEXT_CONCAT.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/TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/a1-[autogen]/docstring.txt b/docs/nodes/TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/a1-[autogen]/docstring.txt new file mode 100644 index 0000000000..2c24e7fe8c --- /dev/null +++ b/docs/nodes/TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/a1-[autogen]/docstring.txt @@ -0,0 +1,19 @@ +The TEXT_CONCAT node takes in two TextBlob DataContainer type and concatenates the text string. + + Inputs + ------ + a: TextBlob + The input text to be concatenated to input b + + b: TextBlob + The input text to be concatenated to input a + + Parameters + ---------- + delimiter: "space" | "comma" | "semicolon" | "colon" | "new line" | "none", default="space" + Select the delimiter to place between two text. + + Returns + ------- + TextBlob + The text result from concatenation. diff --git a/docs/nodes/TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/a1-[autogen]/python_code.txt b/docs/nodes/TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/a1-[autogen]/python_code.txt new file mode 100644 index 0000000000..21395acbdb --- /dev/null +++ b/docs/nodes/TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/a1-[autogen]/python_code.txt @@ -0,0 +1,30 @@ +from flojoy import TextBlob, flojoy +from typing import Literal + + +@flojoy +def TEXT_CONCAT( + a: TextBlob, + b: TextBlob, + delimiter: Literal[ + "space", "comma", "semicolon", "colon", "new line", "none" + ] = "space", +) -> TextBlob: + + + delim: str = None + match delimiter: + case "space": + delim = " " + case "comma": + delim = "," + case "semicolon": + delim = ";" + case "colon": + delim = ":" + case "new line": + delim = "\n" + case "none": + delim = "" + + return TextBlob(text_blob=delim.join([a.text_blob, b.text_blob])) diff --git a/docs/nodes/TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/appendix/hardware.md b/docs/nodes/TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/appendix/hardware.md new file mode 100644 index 0000000000..7f78a555c4 --- /dev/null +++ b/docs/nodes/TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/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/TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/appendix/media.md b/docs/nodes/TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/appendix/media.md new file mode 100644 index 0000000000..8bcee9be90 --- /dev/null +++ b/docs/nodes/TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/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/TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/appendix/notes.md b/docs/nodes/TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/appendix/notes.md new file mode 100644 index 0000000000..04aded2ec9 --- /dev/null +++ b/docs/nodes/TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/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/TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/examples/EX1/app.json b/docs/nodes/TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/examples/EX1/app.json new file mode 100644 index 0000000000..e30dc8d301 --- /dev/null +++ b/docs/nodes/TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/examples/EX1/app.json @@ -0,0 +1,326 @@ +{ + "rfInstance": { + "nodes": [ + { + "width": 208, + "height": 96, + "id": "TEXT-227089e5-8fbd-4a73-980d-339ba726dae4", + "type": "GENERATORS", + "data": { + "id": "TEXT-227089e5-8fbd-4a73-980d-339ba726dae4", + "label": "TEXT", + "func": "TEXT", + "type": "GENERATORS", + "ctrls": { + "value": { + "type": "str", + "default": "Hello World!", + "desc": "The value set in Parameters", + "overload": null, + "functionName": "TEXT", + "param": "value", + "value": "This app is an example of how" + } + }, + "initCtrls": {}, + "inputs": [ + { + "name": "_", + "id": "_", + "type": "Any", + "multiple": false, + "desc": null + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "TextBlob", + "desc": "text_blob: return the value being set in Parameters" + } + ], + "path": "GENERATORS/SIMULATIONS/TEXT/TEXT.py", + "selected": false + }, + "position": { + "x": -211.32231151327338, + "y": -89.70082843401013 + }, + "selected": false, + "positionAbsolute": { + "x": -211.32231151327338, + "y": -89.70082843401013 + }, + "dragging": true + }, + { + "width": 208, + "height": 96, + "id": "TEXT-928dd912-2512-4c96-9dd7-23e27a3dd2d3", + "type": "GENERATORS", + "data": { + "id": "TEXT-928dd912-2512-4c96-9dd7-23e27a3dd2d3", + "label": "TEXT 1", + "func": "TEXT", + "type": "GENERATORS", + "ctrls": { + "value": { + "type": "str", + "default": "Hello World!", + "desc": "The value set in Parameters", + "overload": null, + "functionName": "TEXT", + "param": "value", + "value": "text concatenation can be done when text concat node receives two texts." + } + }, + "initCtrls": {}, + "inputs": [ + { + "name": "_", + "id": "_", + "type": "Any", + "multiple": false, + "desc": null + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "TextBlob", + "desc": "text_blob: return the value being set in Parameters" + } + ], + "path": "GENERATORS/SIMULATIONS/TEXT/TEXT.py", + "selected": false + }, + "position": { + "x": -213.8881079257544, + "y": 70.98356991895969 + }, + "selected": false, + "positionAbsolute": { + "x": -213.8881079257544, + "y": 70.98356991895969 + }, + "dragging": true + }, + { + "width": 384, + "height": 288, + "id": "TEXT_VIEW-15aa085c-94d2-4cfb-b1b7-8aa8f7a419c8", + "type": "VISUALIZERS", + "data": { + "id": "TEXT_VIEW-15aa085c-94d2-4cfb-b1b7-8aa8f7a419c8", + "label": "TEXT VIEW", + "func": "TEXT_VIEW", + "type": "VISUALIZERS", + "ctrls": {}, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "TextBlob", + "multiple": false, + "desc": "the DataContainer to be visualized in text format" + } + ], + "path": "VISUALIZERS/DATA_STRUCTURE/TEXT_VIEW/TEXT_VIEW.py", + "selected": false + }, + "position": { + "x": 78.82218180901118, + "y": 168.52634688615888 + }, + "selected": false, + "positionAbsolute": { + "x": 78.82218180901118, + "y": 168.52634688615888 + }, + "dragging": true + }, + { + "width": 384, + "height": 288, + "id": "TEXT_VIEW-e388f14f-a67c-4576-becf-c18e5a3c1351", + "type": "VISUALIZERS", + "data": { + "id": "TEXT_VIEW-e388f14f-a67c-4576-becf-c18e5a3c1351", + "label": "TEXT VIEW 1", + "func": "TEXT_VIEW", + "type": "VISUALIZERS", + "ctrls": {}, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "TextBlob", + "multiple": false, + "desc": "the DataContainer to be visualized in text format" + } + ], + "path": "VISUALIZERS/DATA_STRUCTURE/TEXT_VIEW/TEXT_VIEW.py", + "selected": false + }, + "position": { + "x": 108.6949072989687, + "y": -375.6105365940835 + }, + "selected": false, + "positionAbsolute": { + "x": 108.6949072989687, + "y": -375.6105365940835 + }, + "dragging": true + }, + { + "width": 160, + "height": 160, + "id": "TEXT_CONCAT-5d342d7b-056d-4c32-9434-b4250ad211f1", + "type": "TRANSFORMERS", + "data": { + "id": "TEXT_CONCAT-5d342d7b-056d-4c32-9434-b4250ad211f1", + "label": "TEXT CONCAT", + "func": "TEXT_CONCAT", + "type": "TRANSFORMERS", + "ctrls": { + "delimiter": { + "type": "select", + "options": [ + "space", + "comma", + "semicolon", + "colon", + "new line" + ], + "default": "space", + "desc": "Select the delimiter to place between two text.", + "overload": null, + "functionName": "TEXT_CONCAT", + "param": "delimiter", + "value": "space" + } + }, + "initCtrls": {}, + "inputs": [ + { + "name": "a", + "id": "a", + "type": "TextBlob", + "multiple": false, + "desc": "The input text to be concatenated to input b" + }, + { + "name": "b", + "id": "b", + "type": "TextBlob", + "multiple": false, + "desc": "The input text to be concatenated to input a" + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "TextBlob", + "desc": "The text result from concatenation." + } + ], + "path": "TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/TEXT_CONCAT.py", + "selected": false + }, + "position": { + "x": 146.05490307299712, + "y": -59.34707208249702 + }, + "selected": false, + "positionAbsolute": { + "x": 146.05490307299712, + "y": -59.34707208249702 + }, + "dragging": true + }, + { + "width": 384, + "height": 288, + "id": "TEXT_VIEW-eb9c6467-0268-4e66-8962-ee86675224c3", + "type": "VISUALIZERS", + "data": { + "id": "TEXT_VIEW-eb9c6467-0268-4e66-8962-ee86675224c3", + "label": "TEXT VIEW 2", + "func": "TEXT_VIEW", + "type": "VISUALIZERS", + "ctrls": {}, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "TextBlob", + "multiple": false, + "desc": "the DataContainer to be visualized in text format" + } + ], + "path": "VISUALIZERS/DATA_STRUCTURE/TEXT_VIEW/TEXT_VIEW.py", + "selected": false + }, + "position": { + "x": 443.4362187780466, + "y": -92.2740632689061 + }, + "selected": false, + "positionAbsolute": { + "x": 443.4362187780466, + "y": -92.2740632689061 + }, + "dragging": true + } + ], + "edges": [ + { + "source": "TEXT-227089e5-8fbd-4a73-980d-339ba726dae4", + "sourceHandle": "default", + "target": "TEXT_VIEW-e388f14f-a67c-4576-becf-c18e5a3c1351", + "targetHandle": "default", + "id": "reactflow__edge-TEXT-227089e5-8fbd-4a73-980d-339ba726dae4default-TEXT_VIEW-e388f14f-a67c-4576-becf-c18e5a3c1351default" + }, + { + "source": "TEXT-928dd912-2512-4c96-9dd7-23e27a3dd2d3", + "sourceHandle": "default", + "target": "TEXT_VIEW-15aa085c-94d2-4cfb-b1b7-8aa8f7a419c8", + "targetHandle": "default", + "id": "reactflow__edge-TEXT-928dd912-2512-4c96-9dd7-23e27a3dd2d3default-TEXT_VIEW-15aa085c-94d2-4cfb-b1b7-8aa8f7a419c8default" + }, + { + "source": "TEXT-227089e5-8fbd-4a73-980d-339ba726dae4", + "sourceHandle": "default", + "target": "TEXT_CONCAT-5d342d7b-056d-4c32-9434-b4250ad211f1", + "targetHandle": "a", + "id": "reactflow__edge-TEXT-227089e5-8fbd-4a73-980d-339ba726dae4default-TEXT_CONCAT-5d342d7b-056d-4c32-9434-b4250ad211f1a" + }, + { + "source": "TEXT-928dd912-2512-4c96-9dd7-23e27a3dd2d3", + "sourceHandle": "default", + "target": "TEXT_CONCAT-5d342d7b-056d-4c32-9434-b4250ad211f1", + "targetHandle": "b", + "id": "reactflow__edge-TEXT-928dd912-2512-4c96-9dd7-23e27a3dd2d3default-TEXT_CONCAT-5d342d7b-056d-4c32-9434-b4250ad211f1b" + }, + { + "source": "TEXT_CONCAT-5d342d7b-056d-4c32-9434-b4250ad211f1", + "sourceHandle": "default", + "target": "TEXT_VIEW-eb9c6467-0268-4e66-8962-ee86675224c3", + "targetHandle": "default", + "id": "reactflow__edge-TEXT_CONCAT-5d342d7b-056d-4c32-9434-b4250ad211f1default-TEXT_VIEW-eb9c6467-0268-4e66-8962-ee86675224c3default" + } + ], + "viewport": { + "x": 637.654905587641, + "y": 370.10612546109087, + "zoom": 0.7111497425822767 + } + } +} \ No newline at end of file diff --git a/docs/nodes/TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/examples/EX1/example.md b/docs/nodes/TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/examples/EX1/example.md new file mode 100644 index 0000000000..54a879ca6f --- /dev/null +++ b/docs/nodes/TRANSFORMERS/TEXT_MANIPULATION/TEXT_CONCAT/examples/EX1/example.md @@ -0,0 +1 @@ +In this example, we generate two texts using `TEXT` node. Then the texts are concatenated using the `TEXT_CONCAT` node with a delimiter specified that has space set as the default. The new text is visualized with `TEXT_VIEW` node. \ No newline at end of file diff --git a/docs/nodes/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/VECTOR_2_ORDERED_PAIR.md b/docs/nodes/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/VECTOR_2_ORDERED_PAIR.md new file mode 100644 index 0000000000..f7cb3d0f54 --- /dev/null +++ b/docs/nodes/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/VECTOR_2_ORDERED_PAIR.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/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/a1-[autogen]/docstring.txt b/docs/nodes/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/a1-[autogen]/docstring.txt new file mode 100644 index 0000000000..8cde12fbeb --- /dev/null +++ b/docs/nodes/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/a1-[autogen]/docstring.txt @@ -0,0 +1,14 @@ +The VECTOR_2_ORDERED_PAIR node returns the OrderedPair + where x and y axes are the input nodes + + Inputs + ------ + default : Vector + The input vector that will be the x axis of OrderedPair. + y : Vector + The input vector that will be the y axis of OrderedPair. + + Returns + ------- + OrderedPair + The OrderedPair that is generated from the input vectors diff --git a/docs/nodes/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/a1-[autogen]/python_code.txt b/docs/nodes/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/a1-[autogen]/python_code.txt new file mode 100644 index 0000000000..34aac4e4ff --- /dev/null +++ b/docs/nodes/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/a1-[autogen]/python_code.txt @@ -0,0 +1,8 @@ +from flojoy import flojoy, Vector, OrderedPair + + +@flojoy +def VECTOR_2_ORDERED_PAIR(default: Vector, y: Vector) -> OrderedPair: + + + return OrderedPair(x=default.v, y=y.v) diff --git a/docs/nodes/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/appendix/hardware.md b/docs/nodes/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/appendix/hardware.md new file mode 100644 index 0000000000..7f78a555c4 --- /dev/null +++ b/docs/nodes/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/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/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/appendix/media.md b/docs/nodes/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/appendix/media.md new file mode 100644 index 0000000000..8bcee9be90 --- /dev/null +++ b/docs/nodes/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/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/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/appendix/notes.md b/docs/nodes/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/appendix/notes.md new file mode 100644 index 0000000000..04aded2ec9 --- /dev/null +++ b/docs/nodes/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/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/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/examples/EX1/app.json b/docs/nodes/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/examples/EX1/app.json new file mode 100644 index 0000000000..43a1bb7268 --- /dev/null +++ b/docs/nodes/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/examples/EX1/app.json @@ -0,0 +1,269 @@ +{ + "rfInstance": { + "nodes": [ + { + "width": 208, + "height": 96, + "id": "LINSPACE-2ed49441-b754-466d-83ed-a67759f7f6c0", + "type": "GENERATORS", + "data": { + "id": "LINSPACE-2ed49441-b754-466d-83ed-a67759f7f6c0", + "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": 30 + }, + "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": 3000 + } + }, + "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 step number of points." + } + ], + "path": "PYTHON/nodes/GENERATORS/SIMULATIONS/LINSPACE/LINSPACE.py", + "selected": false + }, + "position": { + "x": -428.6956890539163, + "y": -103.1951662915236 + }, + "selected": false, + "positionAbsolute": { + "x": -428.6956890539163, + "y": -103.1951662915236 + }, + "dragging": true + }, + { + "width": 208, + "height": 96, + "id": "LINSPACE-c5667d98-8d34-4f79-9157-51d036bb3d53", + "type": "GENERATORS", + "data": { + "id": "LINSPACE-c5667d98-8d34-4f79-9157-51d036bb3d53", + "label": "LINSPACE 1", + "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": 1000 + } + }, + "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 step number of points." + } + ], + "path": "PYTHON/nodes\\GENERATORS\\SIMULATIONS\\LINSPACE\\LINSPACE.py", + "selected": false + }, + "position": { + "x": -429.97907265044006, + "y": 55.685599181173615 + }, + "selected": false, + "positionAbsolute": { + "x": -429.97907265044006, + "y": 55.685599181173615 + }, + "dragging": true + }, + { + "width": 225, + "height": 226, + "id": "SCATTER-f6d0bc5a-5c95-466b-973d-42a1a8dd69e5", + "type": "VISUALIZERS", + "data": { + "id": "SCATTER-f6d0bc5a-5c95-466b-973d-42a1a8dd69e5", + "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 Plotly Scatter visualization" + } + ], + "path": "PYTHON/nodes\\VISUALIZERS\\PLOTLY\\SCATTER\\SCATTER.py", + "selected": false + }, + "position": { + "x": 136.16319682068846, + "y": -89.97535403861903 + }, + "selected": false, + "positionAbsolute": { + "x": 136.16319682068846, + "y": -89.97535403861903 + }, + "dragging": true + }, + { + "width": 160, + "height": 160, + "id": "VECTOR_2_ORDERED_PAIR-a5c62c36-bcd0-40b6-8944-e641bbb86f80", + "type": "TRANSFORMERS", + "data": { + "id": "VECTOR_2_ORDERED_PAIR-a5c62c36-bcd0-40b6-8944-e641bbb86f80", + "label": "VECTOR 2 ORDERED PAIR", + "func": "VECTOR_2_ORDERED_PAIR", + "type": "TRANSFORMERS", + "ctrls": {}, + "initCtrls": {}, + "inputs": [ + { + "name": "default", + "id": "default", + "type": "Vector", + "multiple": false, + "desc": null + }, + { + "name": "y", + "id": "y", + "type": "Vector", + "multiple": false, + "desc": "The input vector that will be the y axis of OrderedPair." + } + ], + "outputs": [ + { + "name": "default", + "id": "default", + "type": "OrderedPair", + "desc": "The ordered pair that is generated from the input vectors" + } + ], + "path": "PYTHON/nodes\\TRANSFORMERS\\TYPE_CASTING\\VECTOR_2_ORDERED_PAIR\\VECTOR_2_ORDERED_PAIR.py", + "selected": false + }, + "position": { + "x": -120.42527902479573, + "y": -45.91111870555173 + }, + "selected": false, + "positionAbsolute": { + "x": -120.42527902479573, + "y": -45.91111870555173 + }, + "dragging": true + } + ], + "edges": [ + { + "source": "LINSPACE-2ed49441-b754-466d-83ed-a67759f7f6c0", + "sourceHandle": "default", + "target": "VECTOR_2_ORDERED_PAIR-a5c62c36-bcd0-40b6-8944-e641bbb86f80", + "targetHandle": "default", + "id": "reactflow__edge-LINSPACE-2ed49441-b754-466d-83ed-a67759f7f6c0default-VECTOR_2_ORDERED_PAIR-a5c62c36-bcd0-40b6-8944-e641bbb86f80default" + }, + { + "source": "LINSPACE-c5667d98-8d34-4f79-9157-51d036bb3d53", + "sourceHandle": "default", + "target": "VECTOR_2_ORDERED_PAIR-a5c62c36-bcd0-40b6-8944-e641bbb86f80", + "targetHandle": "y", + "id": "reactflow__edge-LINSPACE-c5667d98-8d34-4f79-9157-51d036bb3d53default-VECTOR_2_ORDERED_PAIR-a5c62c36-bcd0-40b6-8944-e641bbb86f80y" + }, + { + "source": "VECTOR_2_ORDERED_PAIR-a5c62c36-bcd0-40b6-8944-e641bbb86f80", + "sourceHandle": "default", + "target": "SCATTER-f6d0bc5a-5c95-466b-973d-42a1a8dd69e5", + "targetHandle": "default", + "id": "reactflow__edge-VECTOR_2_ORDERED_PAIR-a5c62c36-bcd0-40b6-8944-e641bbb86f80default-SCATTER-f6d0bc5a-5c95-466b-973d-42a1a8dd69e5default" + } + ], + "viewport": { + "x": 856.9726609784543, + "y": 419.56285211681103, + "zoom": 0.8897660042407147 + } + } +} \ No newline at end of file diff --git a/docs/nodes/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/examples/EX1/example.md b/docs/nodes/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/examples/EX1/example.md new file mode 100644 index 0000000000..6621a44c87 --- /dev/null +++ b/docs/nodes/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/examples/EX1/example.md @@ -0,0 +1,5 @@ +In this example, we generate two Vector nodes using `Linspace` node. + +Using `VECTOR_2_ORDERED_PAIR`, let one of the Vector nodes to be x axis and the other to be y axis. + +Visualize the OrderedPair type output using `Scatter` node \ No newline at end of file diff --git a/docs/nodes/VISUALIZERS/PLOTLY/BIG_NUMBER/a1-[autogen]/python_code.txt b/docs/nodes/VISUALIZERS/PLOTLY/BIG_NUMBER/a1-[autogen]/python_code.txt index 646ea0e572..96a1a2792d 100644 --- a/docs/nodes/VISUALIZERS/PLOTLY/BIG_NUMBER/a1-[autogen]/python_code.txt +++ b/docs/nodes/VISUALIZERS/PLOTLY/BIG_NUMBER/a1-[autogen]/python_code.txt @@ -21,6 +21,7 @@ def BIG_NUMBER( prefix: str, title: str, relative_delta: bool = True, + scientific_notation: bool = False, ) -> Plotly: @@ -37,19 +38,24 @@ def BIG_NUMBER( big_num = default.c case Vector(): big_num = default.v[-1] - val_format = ".1%" if relative_delta is True else ".1f" + case _: + raise ValueError(f"Invalid input type {type(default)} for node {node_name}") + + delta_val_format = ".1%" if relative_delta is True else ".1f" + val_format = "%g" if scientific_notation is False else ".4e" + fig.add_trace( go.Indicator( mode="number+delta", - value=int(float(big_num)), + value=big_num, domain={"y": [0, 1], "x": [0, 1]}, - number={"prefix": prefix, "suffix": suffix}, + number={"prefix": prefix, "suffix": suffix, "valueformat": val_format}, delta=None if prev_num is None else { - "reference": int(float(prev_num)), + "reference": prev_num, "relative": relative_delta, - "valueformat": val_format, + "valueformat": delta_val_format, }, ) ) diff --git a/docs/nodes/VISUALIZERS/PLOTLY/LINE/a1-[autogen]/python_code.txt b/docs/nodes/VISUALIZERS/PLOTLY/LINE/a1-[autogen]/python_code.txt index 88ed85e680..81c9facba2 100644 --- a/docs/nodes/VISUALIZERS/PLOTLY/LINE/a1-[autogen]/python_code.txt +++ b/docs/nodes/VISUALIZERS/PLOTLY/LINE/a1-[autogen]/python_code.txt @@ -1,13 +1,14 @@ from flojoy import flojoy, Plotly, OrderedPair, DataFrame, Matrix, Vector -import numpy as np +from numpy import arange import plotly.graph_objects as go -import pandas as pd +from pandas.api.types import is_datetime64_any_dtype from nodes.VISUALIZERS.template import plot_layout @flojoy def LINE(default: OrderedPair | DataFrame | Matrix | Vector) -> Plotly: + layout = plot_layout(title="LINE") fig = go.Figure(layout=layout) @@ -23,7 +24,7 @@ def LINE(default: OrderedPair | DataFrame | Matrix | Vector) -> Plotly: df = default.m first_col = df.iloc[:, 0] is_timeseries = False - if pd.api.types.is_datetime64_any_dtype(first_col): + if is_datetime64_any_dtype(first_col): is_timeseries = True if is_timeseries: for col in df.columns: @@ -52,7 +53,7 @@ def LINE(default: OrderedPair | DataFrame | Matrix | Vector) -> Plotly: num_rows, num_cols = m.shape - x_ticks = np.arange(num_cols) + x_ticks = arange(num_cols) for i in range(num_rows): fig.add_trace( @@ -62,7 +63,7 @@ def LINE(default: OrderedPair | DataFrame | Matrix | Vector) -> Plotly: fig.update_layout(xaxis_title="Column", yaxis_title="Value") case Vector(): y = default.v - x = np.arange(len(y)) + x = arange(len(y)) fig.add_trace(go.Scatter(x=x, y=y, mode="lines")) return Plotly(fig=fig) diff --git a/nodeSidebar.json b/nodeSidebar.json index aaeb822254..a5ac13e223 100644 --- a/nodeSidebar.json +++ b/nodeSidebar.json @@ -126,7 +126,8 @@ "nodes/TRANSFORMERS/TYPE_CASTING/DF_2_ORDERED_TRIPLE/DF_2_ORDERED_TRIPLE", "nodes/TRANSFORMERS/TYPE_CASTING/MAT_2_DF/MAT_2_DF", "nodes/TRANSFORMERS/TYPE_CASTING/NP_2_DF/NP_2_DF", - "nodes/TRANSFORMERS/TYPE_CASTING/ORDERED_TRIPLE_2_SURFACE/ORDERED_TRIPLE_2_SURFACE" + "nodes/TRANSFORMERS/TYPE_CASTING/ORDERED_TRIPLE_2_SURFACE/ORDERED_TRIPLE_2_SURFACE", + "nodes/TRANSFORMERS/TYPE_CASTING/VECTOR_2_ORDERED_PAIR/VECTOR_2_ORDERED_PAIR" ], "Flow": [ "nodes/LOGIC_GATES/CONDITIONALS/CONDITIONAL/CONDITIONAL", @@ -140,13 +141,17 @@ "nodes/INSTRUMENTS/WEB_CAM/CAMERA/CAMERA" ], "I/O > Instruments > Keithley": [ - "nodes/INSTRUMENTS/KEITHLEY/KEITHLEY2400/KEITHLEY2400" + "nodes/INSTRUMENTS/KEITHLEY/KEITHLEY2400/KEITHLEY2400", + "nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/IV_SWEEP/IV_SWEEP", + "nodes/IO/INSTRUMENTS/SOURCEMETERS/KEITHLEY/24XX/BASIC/SET_VOLTAGE/SET_VOLTAGE" ], "I/O > Instruments > LabJack": [ - "nodes/INSTRUMENTS/LABJACK/LABJACKU3/LABJACKU3" + "nodes/INSTRUMENTS/LABJACK/LABJACKU3/LABJACKU3", + "nodes/IO/INSTRUMENTS/DAQ_BOARDS/LABJACK/U3/BASIC/READ_A0_PINS/READ_A0_PINS" ], "I/O > Instruments > Phidget": [ - "nodes/INSTRUMENTS/PHIDGET/PHIDGET22/PHIDGET22" + "nodes/INSTRUMENTS/PHIDGET/PHIDGET22/PHIDGET22", + "nodes/IO/INSTRUMENTS/DAQ_BOARDS/PHIDGET/INTERFACEKIT/BASIC/READ_N_PINS/READ_N_PINS" ], "I/O > Motion > Stepper Motor Drivers": [ "nodes/INSTRUMENTS/STEPPER_MOTOR/STEPPER_DRIVER_TIC/STEPPER_DRIVER_TIC", @@ -154,7 +159,9 @@ ], "I/O > Protocols > Serial": [ "nodes/INSTRUMENTS/SERIAL/SERIAL_SINGLE_MEASUREMENT/SERIAL_SINGLE_MEASUREMENT", - "nodes/INSTRUMENTS/SERIAL/SERIAL_TIMESERIES/SERIAL_TIMESERIES" + "nodes/INSTRUMENTS/SERIAL/SERIAL_TIMESERIES/SERIAL_TIMESERIES", + "nodes/IO/PROTOCOLS/SERIAL/BASIC/SINGLE_MEASUREMENT/SINGLE_MEASUREMENT", + "nodes/IO/PROTOCOLS/SERIAL/BASIC/TIMESERIES1/TIMESERIES1" ], "NUMerical PYthon (NumPy) > Linalg": [ "nodes/NUMPY/LINALG/CHOLESKY/CHOLESKY",