Skip to content

Commit

Permalink
update task.py | add more docs
Browse files Browse the repository at this point in the history
  • Loading branch information
idocx committed Jul 8, 2024
1 parent 5ba2cc0 commit a5bf24b
Show file tree
Hide file tree
Showing 35 changed files with 307 additions and 476 deletions.
2 changes: 1 addition & 1 deletion alab_management/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import os

__version__ = "0.4.1"
__version__ = "1.0.1"
from .builders import ExperimentBuilder
from .device_view.dbattributes import value_in_database
from .device_view.device import BaseDevice, add_device
Expand Down
43 changes: 41 additions & 2 deletions alab_management/_default/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,41 @@
from .devices import * # noqa
from .tasks import * # noqa
"""
This is the entry point for the alab_management package. This package is used to manage the ALab project.
You will need to import all the device and task definitions in the project and register them using the `add_device`
and `add_task` functions.
"""

# import helper functions from alabos package
from alab_management.device_view import add_device
from alab_management.sample_view import SamplePosition, add_standalone_sample_position
from alab_management.task_view import add_task

# import all the device and task definitions here
# relative imports are recommended (starts with a dot)
from .devices.default_device import DefaultDevice
from .tasks.default_task import DefaultTask

# you can add the devices here. If they are the same type,
# you can use the same class and just change the name.
#
# For example, if you have 3 devices under different IP addresses,
# you can use the same class and just change the IP address and name.
# AlabOS will autoamtically decide which device to run an experiment
# based on their availability.
add_device(DefaultDevice(name="device_1", ip_address="192.168.1.11"))
add_device(DefaultDevice(name="device_2", ip_address="192.168.1.12"))
add_device(DefaultDevice(name="device_3", ip_address="192.168.1.13"))

# you can add all the tasks here
add_task(DefaultTask)

# When defining a device, you can define the sample positions related to that device,
# where the sample positions are bound to the device.
# AlabOS also provides a way to define standalone sample positions that are not bound to any device.
add_standalone_sample_position(
SamplePosition(
"default_standalone_sample_position",
description="Default sample position",
number=8,
)
)
24 changes: 20 additions & 4 deletions alab_management/_default/config.toml
Original file line number Diff line number Diff line change
@@ -1,19 +1,35 @@
[general]
name = 'default_lab'
working_dir = "."
name = 'default_lab' # 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]
[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]
[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 = " "
4 changes: 1 addition & 3 deletions alab_management/_default/devices/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
# from alab_management import import_device_definitions

# import_device_definitions(__file__, __name__)
"""You don't have to modify this file. It is used to make Python treat the directory as containing packages."""
38 changes: 31 additions & 7 deletions alab_management/_default/devices/default_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,22 @@


class DefaultDevice(BaseDevice):
"""Default device definition, refer to https://idocx.github.io/alab_management/device_definition.html."""
"""Default device definition, refer to https://idocx.github.io/alab_management/device_definition.html. # TODO"""

# You can add a description to the device.
description: ClassVar[str] = "Default device"

def __init__(self, *args, **kwargs):
def __init__(self, ip_address: str, *args, **kwargs):
"""
You can customize this method to store more information about the device. For example,
if the device is communicated through a serial port, you can store the serial port information here.
Args:
ip_address: IP address of the device. This is just an example, you can change it to any other information.
*args:
**kwargs:
"""
self.ip_address = ip_address
super().__init__(*args, **kwargs)

@property
Expand All @@ -24,16 +35,29 @@ def sample_positions(self):
]

def connect(self):
"""
Connect to the device.
In this method, you can define the connection to the device with various protocols. After calling
this method, the instance should be able to communicate with the device.
"""
pass

def disconnect(self):
pass
"""
Disconnect from the device.
def emergent_stop(self):
In this method, you can define the disconnection from the device. Although the instance
may still exist, it should not be able to communicate with the device after this method is called.
"""
pass

def is_running(self):
return False
"""
Check if the device is running.

default_device_1 = DefaultDevice(name="default_device_1")
Returns:
-------
bool: True if the device is running, False otherwise.
"""
return False
4 changes: 1 addition & 3 deletions alab_management/_default/tasks/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
# from alab_management import import_task_definitions

# import_task_definitions(__file__, __name__)
"""You don't have to modify this file. It is used to make Python treat the directory as containing packages."""
7 changes: 6 additions & 1 deletion alab_management/_default/tasks/default_task.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from bson import ObjectId # type: ignore
from pydantic import BaseModel

from alab_management.task_view.task import BaseTask


class DefaultTask(BaseTask):
"""The default task, refer to https://idocx.github.io/alab_management/task_definition.html for more details."""
"""The default task, refer to https://idocx.github.io/alab_management/task_definition.html for more details. #TODO"""

def __init__(self, sample: ObjectId, *args, **kwargs):
super().__init__(*args, **kwargs)
Expand All @@ -21,3 +22,7 @@ def run(self):

def validate(self):
return True

@property
def result_specification(self) -> BaseModel:
pass
69 changes: 0 additions & 69 deletions alab_management/builders/samplebuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,72 +83,3 @@ def __eq__(self, other):
def __repr__(self):
"""Return a string representation of the sample."""
return f"<Sample: {self.name}>"


# ## Format checking for API inputs


# class TaskInputFormat(BaseModel):
# id: Optional[Any] = Field(None, alias="id")
# task_type: str
# parameters: Dict[str, Any]
# capacity: int
# prev_tasks: List[str]
# samples: List[Union[str, Any]]

# @validator("id")
# def must_be_valid_objectid(cls, v):
# try:
# ObjectId(v)
# except:
# raise ValueError(f"Received invalid _id: {v} is not a valid ObjectId!")
# return v

# @validator("capacity")
# def must_be_positive(cls, v):
# if v < 0:
# raise ValueError(f"Capacity must be positive, received {v}")
# return v

# @validator("samples")
# def samples_must_be_valid_objectid(cls, v):
# for sample_id in v:
# try:
# ObjectId(sample_id)
# except:
# raise ValueError(
# f"Received invalid sample_id: {sample_id} is not a valid ObjectId!"
# )
# return v

# @validator("prev_tasks")
# def prevtasks_must_be_valid_objectid(cls, v):
# for task_id in v:
# try:
# ObjectId(task_id)
# except:
# raise ValueError(
# f"Received invalid sample_id: {task_id} is not a valid ObjectId!"
# )
# return v


# class SampleInputFormat(BaseModel):
# """
# Format check for API for Sample submission.
# Sample's must follow this format to be accepted into the batching queue.
# """

# id: Optional[Any] = Field(None, alias="id")
# name: constr(regex=r"^[^$.]+$") # type: ignore
# tags: List[str]
# tasks: List[TaskInputFormat]
# metadata: Dict[str, Any]

# @validator("id")
# def must_be_valid_objectid(cls, v):
# try:
# ObjectId(v)
# except:
# raise ValueError(f"Received invalid _id: {v} is not a valid ObjectId!")
# return v
5 changes: 0 additions & 5 deletions alab_management/device_view/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,11 +287,6 @@ def sample_positions(self):
"""
raise NotImplementedError()

@abstractmethod
def emergent_stop(self): # TODO rename this to emergency stop
"""Specify how the device should stop when emergency."""
raise NotImplementedError()

@abstractmethod
def is_running(self) -> bool:
"""Check whether this device is running."""
Expand Down
6 changes: 4 additions & 2 deletions alab_management/scripts/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import click

from alab_management.__init__ import __version__
from alab_management.config import AlabOSConfig

from .cleanup_lab import cleanup_lab
from .init_project import init_project
Expand All @@ -25,7 +24,6 @@ def cli():
/_/ \_\_|\__,_|_.__/ \___/|____/
---- Alab OS v{__version__} -- Alab Project Team ----
Simulation mode: {"ON" if AlabOSConfig().is_sim_mode() else "OFF"}
"""
)

Expand Down Expand Up @@ -57,7 +55,11 @@ def setup_lab_cli():
@click.option("--debug", default=False, is_flag=True)
def launch_lab_cli(host, port, debug):
"""Start to run the lab."""
from alab_management.config import AlabOSConfig

click.echo(f'Simulation mode: {"ON" if AlabOSConfig().is_sim_mode() else "OFF"}')
click.echo(f"The dashboard will be served on http://{host}:{port}")

launch_lab(host, port, debug)


Expand Down
Loading

0 comments on commit a5bf24b

Please sign in to comment.