Metadata-Version: 2.4
Name: experimaestro
Version: 2.0.4
Summary: Experimaestro is a computer science experiment manager
Project-URL: Homepage, https://github.com/experimaestro/experimaestro-python
Project-URL: Documentation, https://experimaestro-python.readthedocs.io/
Project-URL: Repository, https://github.com/experimaestro/experimaestro-python
Project-URL: Bug Tracker, https://github.com/experimaestro/experimaestro-python/issues
Author-email: Benjamin Piwowarski <benjamin@piwowarski.fr>
License: GPL-3.0-or-later
License-File: LICENSE
Keywords: experiment manager
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: arpeggio<3,>=2
Requires-Dist: attrs<24,>=23.1.0
Requires-Dist: click>=8
Requires-Dist: decorator<6,>=5
Requires-Dist: docstring-parser<1,>=0.15
Requires-Dist: fastapi<1,>=0.109
Requires-Dist: filelock<4,>=3.16
Requires-Dist: httpx<1,>=0.26
Requires-Dist: huggingface-hub>0.17
Requires-Dist: humanfriendly>=10
Requires-Dist: jinja2>=3
Requires-Dist: marshmallow<4,>=3.20
Requires-Dist: omegaconf<3,>=2.3
Requires-Dist: psutil<8,>=7
Requires-Dist: pyparsing<4,>=3.1
Requires-Dist: pyperclip<2,>=1.8
Requires-Dist: pytools<2024,>=2023.1.1
Requires-Dist: pyyaml<7,>=6.0.1
Requires-Dist: requests<3,>=2.31
Requires-Dist: rpyc<7,>=5
Requires-Dist: sortedcontainers<3,>=2.4
Requires-Dist: termcolor<3,>=2.3
Requires-Dist: textual-fspicker>=0.0.11
Requires-Dist: textual>=6
Requires-Dist: tqdm<5,>=4.66.1
Requires-Dist: typing-extensions>=4.2; python_version < '3.12'
Requires-Dist: uvicorn[standard]<1,>=0.27
Requires-Dist: watchdog>=2
Provides-Extra: carbon
Requires-Dist: codecarbon>=2.0; (sys_platform != 'darwin') and extra == 'carbon'
Requires-Dist: zeus[apple]>=0.10.0; (sys_platform == 'darwin') and extra == 'carbon'
Provides-Extra: dev
Requires-Dist: docutils>=0.18; extra == 'dev'
Requires-Dist: mypy>=1.0; extra == 'dev'
Requires-Dist: pygments>=2.15; extra == 'dev'
Requires-Dist: pytest-dependency>=0.6.0; extra == 'dev'
Requires-Dist: pytest-order>=1.0.0; extra == 'dev'
Requires-Dist: pytest-timeout>=2.4.0; extra == 'dev'
Requires-Dist: pytest>=8.4.1; extra == 'dev'
Requires-Dist: textual-dev>=1.8.0; extra == 'dev'
Provides-Extra: docs
Requires-Dist: myst-parser>=2.0; extra == 'docs'
Requires-Dist: sphinx-codeautolink>=0.15; extra == 'docs'
Requires-Dist: sphinx-copybutton>=0.5; extra == 'docs'
Requires-Dist: sphinx-rtd-theme>=2.0; extra == 'docs'
Requires-Dist: sphinx>=6; extra == 'docs'
Provides-Extra: ssh
Requires-Dist: fabric>=3; extra == 'ssh'
Requires-Dist: paramiko>=3.3; extra == 'ssh'
Description-Content-Type: text/markdown

[![PyPI version](https://badge.fury.io/py/experimaestro.svg)](https://badge.fury.io/py/experimaestro)
[![RTD](https://readthedocs.org/projects/experimaestro-python/badge/?version=latest)](https://experimaestro-python.readthedocs.io)

Experimaestro helps in designing and managing **complex experimental plans**. It allows for the definition of tasks and their dependencies, ensuring that each step in a workflow is executed in the correct order. Some key aspects of Experimaestro are:

- **Task Automation**: The tool automates repetitive tasks, making it easier to run large-scale experiments. It's particularly useful in scenarios where experiments need to be repeated with different parameters or datasets.
- **Resource Management**: It efficiently manages computational resources, which is critical when dealing with data-intensive tasks or when running multiple experiments in parallel.
- **Reproducibility**: By keeping a detailed record of experiments (the experimental plan in python), including parameters and environments, it aids in ensuring the reproducibility of scientific experiments, which is a fundamental requirement in research.
- **User Interface**: While primarily a back-end tool, Experimaestro also offers a user interface to help in managing and visualizing workflows (web and text-based).

The full documentation can be read by going to the following URL: [https://experimaestro-python.readthedocs.io](https://experimaestro-python.readthedocs.io). A tutorial (training a CNN on MNIST) is [available on github](https://github.com/experimaestro/experimaestro-demo).

# Screenshots

## Textual interface (new in v2)

![Experiment screen](docs/source/img/tui-experiments.png)

![Jobs screen](docs/source/img/tui-jobs.png)

![Log screen](docs/source/img/tui-logs.png)

# Install

## With pip

You can then install the package using `pip install experimaestro`

## Develop

Checkout the git directory, then

```
pip install -e .
```

# Example

This very simple example shows how to submit two tasks that concatenate two strings.
Under the curtain,

- A directory is created for each task (in `workdir/jobs/helloworld.add/HASHID`)
  based on a unique ID computed from the parameters
- Two processes for `Say` are launched (there are no dependencies, so they will be run in parallel)
- A tag `y` is created for the main task

<!-- SNIPPET: MAIN ARGS[%WORKDIR% --port 0 --sleeptime=0.0001] -->

```python
# --- Task and types definitions

import logging
logging.basicConfig(level=logging.DEBUG)
from pathlib import Path
from experimaestro import Task, Param, experiment, progress
import click
import time
import os
from typing import List

# --- Just to be able to monitor the tasks

def slowdown(sleeptime: int, N: int):
    logging.info("Sleeping %ds after each step", sleeptime)
    for i in range(N):
        time.sleep(sleeptime)
        progress((i+1)/N)


# --- Define the tasks

class Say(Task):
    word: Param[str]
    sleeptime: Param[float]

    def execute(self):
        slowdown(self.sleeptime, len(self.word))
        print(self.word.upper(),)

class Concat(Task):
    strings: Param[List[Say]]
    sleeptime: Param[float]

    def execute(self):
        says = []
        slowdown(self.sleeptime, len(self.strings))
        for string in self.strings:
            with open(string.__xpm_stdout__) as fp:
                says.append(fp.read().strip())
        print(" ".join(says))


# --- Defines the experiment

@click.option("--port", type=int, default=12345, help="Port for monitoring")
@click.option("--sleeptime", type=float, default=2, help="Sleep time")
@click.argument("workdir", type=Path)
@click.command()
def cli(port, workdir, sleeptime):
    """Runs an experiment"""
    # Sets the working directory and the name of the xp
    with experiment(workdir, "helloworld", port=port) as xp:
        # Submit the tasks
        hello = Say.C(word="hello", sleeptime=sleeptime).submit()
        world = Say.C(word="world", sleeptime=sleeptime).submit()

        # Concat will depend on the two first tasks
        Concat.C(strings=[hello, world], sleeptime=sleeptime).tag("y", 1).submit()


if __name__ == "__main__":
    cli()
```

which can be launched with `python test.py /tmp/helloworld-workdir`
