The flexible interactive automation ReST API.
pip install .[all]
You may need to escape the square brackets e.g. [all]
The required env vars to run are:
- FIA_API_API_KEY - This sets the api key needed to use the specification endpoints
- DB_USERNAME - the database username - default: postgres
- DB_PASSWORD - The database password - default: password
- DB_IP - The database host - default: localhost:5432
- DEV_MODE - When true will disable auth - default: False
uvicorn fia_api.fia_api:app --reload
The reload option will reload the api on code changes.
To run the API with no authentication for development, the DEV_MODE env var must be set to True
Build using this command in the root of this repository:
docker build . -f ./container/fia_api.D -t ghcr.io/fiaisis/fia-api
Run on port 8080, by binding port 80 to port 8080 with a built container:
docker run -p 8080:80 ghcr.io/fiaisis/fia-api
How to push the container to the Github container registry:
docker push ghcr.io/fiaisis/fia-api -a
Once deployed the auto generated api documentation is available at /docs
. These can be used to inspect the API, and
can be used to try out each endpoint, which is useful for some manual testing and verification.
To run the integration and e2e tests, a postgres database is expected at localhost:5432 with user: postgres password:password
The endpoint functions are in the routers.py
module. If this module grows to an unmanageable size this can be split up
into a package and seperate router
objects can be created with different rules such as path prefixes. More on this can
be found in the FastAPI documentation
By default if an exception is not handled the API will return a 500 - internal server error. It is possible to define
custom exception handlers to prevent 500 status codes for certain exceptions. These handlers are defined in the
exception_handlers.py
module, and must be registered to the app in the ir_api.py
module.
Transforms are used to apply modifications to instrument scripts based on reduction input parameters. They enable you to dynamically adapt the script depending on specific requirements, such as changing configuration settings, altering input data, or modifying the processing flow.
To add a new transform for a different instrument, follow these steps:
- Create a new class that inherits from the Transform abstract base class, and implement the apply method. This method takes a PreScript object and a Reduction entity as arguments, and modifies the script as needed.
For example:
class YourInstrumentTransform(Transform):
def apply(self, script: PreScript, reduction: Reduction) -> None:
# Your script modification logic here e.g.
script.script = f"print('hello {reduction.reduction_inputs.get('user', 'world')}')"
- Update the get_transform_for_instrument factory function to return an instance of your new transform class when the appropriate instrument is provided as input by adding a new case for your instrument in the match statement:
def get_transform_for_instrument(instrument: str) -> Transform:
match instrument.lower():
case "mari":
return MariTransform()
case "your_instrument":
return YourInstrumentTransform()
case _:
raise MissingTransformError(f"No transform for instrument {instrument}")
The api is implementing a repository and specification pattern.
All queries are defined within specifications, basic ordering is available in the base specification module via a func
and a @paginate
decorator is available to provide pagination to any specification.
This script is designed to generate a mock database for the development environment. It populates the database with random but realistic data related to a set of instruments and their associated runs, reductions, and scripts. This allows developers to easily simulate a real-world scenario, thereby making local development and testing more efficient and effective.
With a postgres database running, execute the script, navigate to the script’s directory and run it using Python:
python db_generator.py
When executed, the script performs the following actions:
- Database Reset: It first clears the existing tables in the database, ensuring a clean slate.
- Instrument Generation: Populates the database with a predefined list of instruments.
- Data Generation: For each instrument, it generates:
- Random runs with various attributes like start and end times, number of frames, experiment number, and associated users.
- Reduction entries with various states, input parameters, and (optionally) output parameters.
- Script entries with a SHA-1 hash and a simple script content.
- Data Insertion: Inserts 10,000 of these randomly generated 'reduction' entries, each associated with random instrument entries, into the database.
The script is seeded with a constant seed value (in this case 1), which means that every time you run the script, it will generate the same random data. If you want different random data each time, you can remove or change the seed value.