Skip to content

Commit

Permalink
initial commit for clade-light
Browse files Browse the repository at this point in the history
  • Loading branch information
jkitchin committed Oct 9, 2024
1 parent b5618d2 commit d500fce
Show file tree
Hide file tree
Showing 9 changed files with 564 additions and 0 deletions.
17 changes: 17 additions & 0 deletions examples/claude-light/claude_alab/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import os
from pathlib import Path

# keep this line at the top of the file
os.putenv("ALABOS_CONFIG_PATH", Path(__file__).parent.absolute() / "config.toml")

from alab_management import add_device, add_task

from .devices.claude import ClaudeLight
from .tasks.claude import MeasureRGB

# set the config path to the default config file


add_device(ClaudeLight(name="rgb"))
add_task(MeasureRGB)

43 changes: 43 additions & 0 deletions examples/claude-light/claude_alab/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
[general]
name = 'claude_alab' # Put the name of the lab here, it will be used as the DB name
working_dir = "." # the working directory of the lab, where the device and task definitions are stored

[mongodb] # the MongoDB configuration
host = 'localhost'
password = ''
port = 27017
username = ''

# all the completed experiments are stored in this database
# the db name will be the lab name + '_completed'
[mongodb_completed]
host = "localhost"
password = ""
port = 27017
username = ""

[rabbitmq] # the RabbitMQ configuration
host = "localhost"
port = 5672

# the user notification configuration, currently only email and slack are supported
# if you don't want to use them, just leave them empty
[alarm]
# the email configuration. All the user notification will be sent to all the email_receivers in the list
# the email_sender is the email address of the sender, e.g. [email protected]
email_receivers = []
email_sender = " "
email_password = " "

# the slack configuration. All the user notification will be sent to the slack_channel_id
# the slack_bot_token is the token of the slack bot, you can get it from https://api.slack.com/apps
slack_bot_token = " "
slack_channel_id = " "

[large_result_storage]
# the default storage configuration for tasks that generate large results
# (>16 MB, cannot be contained in MongoDB)
# currently only gridfs is supported
# storage_type is defined by using LargeResult class located in alab_management/task_view/task.py
# you can override this default configuration by setting the storage_type in the task definition
default_storage_type = "gridfs"
1 change: 1 addition & 0 deletions examples/claude-light/claude_alab/devices/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""You don't have to modify this file. It is used to make Python treat the directory as containing packages."""
44 changes: 44 additions & 0 deletions examples/claude-light/claude_alab/devices/claude.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import json
import requests
from typing import ClassVar

from alab_management.device_view import BaseDevice
from alab_management.sample_view import SamplePosition


class ClaudeLight(BaseDevice):
"""Claude Light definition"""
description: ClassVar[str] = "Claude-Light device"

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.running = None

def __str__(self):
return 'An RGB Claude Light'

@property
def sample_positions(self):
"""Sample positions define the sample positions related to this device."""
return [
SamplePosition(
name="DefaultSamplePosition",
number=1,
description="Default sample position",
)
]

def connect(self):
self.running = True

def disconnect(self):
self.running = False

def is_running(self):
return self.running

def measure(self, R=0, G=0, B=0):
resp = requests.get('https://claude-light.cheme.cmu.edu/api',
params={'R': R, 'G': G, 'B': B})
data = resp.json()
return data
1 change: 1 addition & 0 deletions examples/claude-light/claude_alab/tasks/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""You don't have to modify this file. It is used to make Python treat the directory as containing packages."""
20 changes: 20 additions & 0 deletions examples/claude-light/claude_alab/tasks/claude.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from bson import ObjectId # type: ignore
from pydantic import BaseModel

from alab_management.task_view.task import BaseTask
from claude_alab.devices.claude import ClaudeLight


class MeasureRGB(BaseTask):
"""Measurement task definition."""
def __init__(self, R=0, G=0, B=0, **kwargs):
super().__init__(**kwargs)
self.R = R
self.G = G
self.B = B

def run(self):
print('Running a job')
with self.lab_view.request_resources({"rgb": {}}) as (devices, _):
print(devices)
return devices["rgb"].measure(self.R, self.G, self.B)
256 changes: 256 additions & 0 deletions examples/claude-light/example.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "07e6b35b-6fde-4bb8-961e-2f2cd7faee16",
"metadata": {},
"source": [
"# Setting up\n",
"\n",
"Run these commands in this directory. This will install the lab and setup your database .\n",
"\n",
"\n",
" pip install -e .\n",
"\n",
"To start the server, run these commands.\n",
"\n",
"\n",
" export ALABOS_CONFIG_PATH=`pwd`/claude_alab/config.toml\n",
" export SIM_MODE_FLAG=FALSE\n",
" alabos setup\n",
" alabos launch &\n",
" alabos launch_worker &"
]
},
{
"cell_type": "markdown",
"id": "0fa7bd38-8367-41b7-a372-53165592f32e",
"metadata": {},
"source": [
"# setup and submit an experiment"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "63d09232-7f62-4182-8483-d7cd62729aa8",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"ObjectId('6705d63f9fa06af11c9361bc')"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from alab_management.builders import ExperimentBuilder\n",
"from claude_alab.tasks.claude import MeasureRGB\n",
"\n",
"# you need a name for the experiment\n",
"# you can also provide tags for better organization\n",
"# You can also provide arbitrary kwargs to the builder\n",
"# it will be stored as metadata (e.g., description)\n",
"exp = ExperimentBuilder(name=\"MyExperiment\",\n",
" tags=[\"tag1\", \"tag2\"],\n",
" description=\"My first experiment\")\n",
"\n",
"sample = exp.add_sample(name=\"my_sample_1\",\n",
" tags=[\"project\"],\n",
" description=\"My first sample\")\n",
"\n",
"\n",
"task1 = MeasureRGB(R=0, G=0, B=0)\n",
"task2 = MeasureRGB(R=0, G=1, B=0)\n",
"# you can also do task.add_to([sample1, sample2, ...]) to add multiple samples to the task\n",
"task1.add_to(sample)\n",
"task2.add_to(sample)\n",
"exp_id = exp.submit(address=\"http://localhost:8895\")\n",
"exp_id"
]
},
{
"cell_type": "markdown",
"id": "549ffdc6-7141-4a3c-9b5b-2009a5cce382",
"metadata": {},
"source": [
"# get the experiment status"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "1f9d8e48-af24-4282-9bd0-8ec7375b50ef",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'id': '6705d63f9fa06af11c9361bc',\n",
" 'name': 'MyExperiment',\n",
" 'progress': 1.0,\n",
" 'samples': [{'id': '6705d63f9fa06af11c9361bd',\n",
" 'name': 'my_sample_1',\n",
" 'position': None}],\n",
" 'status': 'COMPLETED',\n",
" 'submitted_at': 'Tue, 08 Oct 2024 21:02:55 GMT',\n",
" 'tasks': [{'id': '6705d63f9fa06af11c9361be',\n",
" 'message': '',\n",
" 'status': 'COMPLETED',\n",
" 'type': 'MeasureRGB'},\n",
" {'id': '6705d63f9fa06af11c9361bf',\n",
" 'message': '',\n",
" 'status': 'COMPLETED',\n",
" 'type': 'MeasureRGB'}]}"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from alab_management import get_experiment_status, get_experiment_result\n",
"\n",
"get_experiment_status(exp_id)"
]
},
{
"cell_type": "markdown",
"id": "de0259e5-8b27-4be9-a1e4-dcff28aa2e3e",
"metadata": {},
"source": [
"# Get the results"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "60d4cced-f55b-4c30-93e1-4b3c49e9bba3",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'completed_at': '2024-10-08T21:03:00.003000',\n",
" 'id': '6705d63f9fa06af11c9361bc',\n",
" 'metadata': {'description': 'My first experiment'},\n",
" 'name': 'MyExperiment',\n",
" 'progress': 1.0,\n",
" 'samples': [{'id': '6705d63f9fa06af11c9361bd',\n",
" 'metadata': {'description': 'My first sample'},\n",
" 'name': 'my_sample_1',\n",
" 'tags': ['project']}],\n",
" 'status': 'COMPLETED',\n",
" 'submitted_at': '2024-10-08T21:02:55.943000',\n",
" 'tags': ['tag1', 'tag2'],\n",
" 'tasks': [{'completed_at': '2024-10-08T21:02:57.863000',\n",
" 'id': '6705d63f9fa06af11c9361be',\n",
" 'message': '',\n",
" 'parameters': {'B': 0, 'G': 0, 'R': 0},\n",
" 'result': {'in': [0.0, 0.0, 0.0],\n",
" 'out': {'415nm': 0,\n",
" '445nm': 0,\n",
" '480nm': 0,\n",
" '515nm': 2,\n",
" '555nm': 5,\n",
" '590nm': 2,\n",
" '630nm': 5,\n",
" '680nm': 0,\n",
" 'clear': 18,\n",
" 'nir': 0}},\n",
" 'samples': ['my_sample_1'],\n",
" 'started_at': '2024-10-08T21:02:56.118000',\n",
" 'status': 'COMPLETED',\n",
" 'type': 'MeasureRGB'},\n",
" {'completed_at': '2024-10-08T21:02:59.847000',\n",
" 'id': '6705d63f9fa06af11c9361bf',\n",
" 'message': '',\n",
" 'parameters': {'B': 0, 'G': 1, 'R': 0},\n",
" 'result': {'in': [0.0, 1.0, 0.0],\n",
" 'out': {'415nm': 923,\n",
" '445nm': 329,\n",
" '480nm': 11541,\n",
" '515nm': 62894,\n",
" '555nm': 9972,\n",
" '590nm': 1298,\n",
" '630nm': 1305,\n",
" '680nm': 1243,\n",
" 'clear': 50552,\n",
" 'nir': 1294}},\n",
" 'samples': ['my_sample_1'],\n",
" 'started_at': '2024-10-08T21:02:58.103000',\n",
" 'status': 'COMPLETED',\n",
" 'type': 'MeasureRGB'}]}"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"results = get_experiment_result(exp_id)\n",
"results"
]
},
{
"cell_type": "markdown",
"id": "9be8cdd2-81dc-4363-9f18-1ee498f90112",
"metadata": {},
"source": [
"Here we subtract the background from the measurement. Maybe there is a better way to do this?"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "a39fda51-2ea7-4ada-8589-7ebd379a273c",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"62892"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"r0 = results['tasks'][0]['result']['out']['515nm']\n",
"r1 = results['tasks'][1]['result']['out']['515nm']\n",
"r1 - r0"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.5"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Loading

0 comments on commit d500fce

Please sign in to comment.