-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add Sweep example fibonacci model (#43)
- Loading branch information
1 parent
ee429b7
commit 29f5ebf
Showing
7 changed files
with
300 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# Use the official Python 3.8 image from Dockerhub to provide a Python environment | ||
FROM python:3.8 | ||
|
||
# Copy the contents from the local ./src/ directory to the output container's /src/ directory | ||
COPY ./src /src | ||
|
||
# Tell Docker how to run the Model when it starts the container. | ||
CMD ["python", "/src/main.py"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
# Fibonacci Model | ||
|
||
This is an example model. Here you should describe what the model does. | ||
|
||
This particular model generates a Fibonacci sequence and saves it to a file. e.g.: | ||
|
||
``` | ||
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...] | ||
``` | ||
|
||
The model has been modified slightly when compared with the simple fibonacci model | ||
to allow this Model to function with Sweep steps | ||
|
||
You can set three inputs: | ||
|
||
- SEQUENCE_LENGTH - Dictates the count of numbers in the generated sequence | ||
- SEQUENCE_F0 - The first number to start the Fibonacci sequence with. | ||
- SEQUENCE_F1 - The second number to start the Fibonacci sequence with. | ||
|
||
The model generates a JSON file containing the sequence, the name of the JSON file will | ||
be prefixed with the sequence length, f0 start number and f1 start number. This modification | ||
to the files name such that it depends upon the parameters is what allows the Model to work | ||
with the Sweep step: | ||
|
||
Filename - `{SEQUENCE_LENGTH}-{SEQUENCE_F0}-{SEQUENCE_F1}-sequence.json` | ||
```json | ||
{ | ||
"sequence": [0, 1, 1, 2, 3, 5] | ||
} | ||
``` | ||
|
||
## Technical Info | ||
|
||
This model pulls in several environment variables and passes them into a piece of Python | ||
code. The Python code is built into a Docker image using the | ||
[provided Dockerfile](./Dockerfile). | ||
|
||
There are five files here: | ||
|
||
- _[main.py](./src/main.py)_ - This is the file initially called by DAFNI. It is referenced in the | ||
Dockerfile. | ||
- _[work.py](./src/work.py)_ - This contains the main code for the model. Here, as an example, it is a | ||
simple Fibonacci generator | ||
- _[Dockerfile](./Dockerfile)_ - Builds the container that will be run by DAFNI | ||
- _[model_definition.yaml](./model_definition.yaml)_ - A machine-readable file used to define the model. | ||
This information will be shown to other users who may wish to use your model. | ||
- _README.md_ - This helpful file. It should contain detailed information about the model. | ||
|
||
## Dependencies | ||
|
||
This model requires [Python](https://www.python.org/) and | ||
[Docker](https://www.docker.com/) to be installed in order to build and run locally. | ||
|
||
## Running the Model | ||
|
||
You can run this example model from within the "simple-example" folder by doing the | ||
following: | ||
|
||
```bash | ||
python ./src/main.py | ||
``` | ||
|
||
You can also run this model using Docker from within the same folder by doing: | ||
|
||
```bash | ||
docker build -t fibonacci-model . | ||
docker run fibonacci-model | ||
``` | ||
|
||
You don't need to run the build step every time you want to run the model, you only need | ||
to re-run it if changes are made to the Dockerfile or any of the files that go into the | ||
Docker image. | ||
|
||
You can adjust the way it runs with the environment variables: | ||
|
||
```bash | ||
docker run -e SEQUENCE_LENGTH=50 fibonacci-model | ||
``` | ||
|
||
or | ||
|
||
```bash | ||
docker run -e SEQUENCE_LENGTH=50 -e SEQUENCE_F0=1 -e SEQUENCE_F1=3 fibonacci-model | ||
``` | ||
|
||
## Uploading to DAFNI | ||
|
||
You will need to create a file from your docker image to upload it. Check out the detailed instructions online at [Docs](https://docs.secure.dafni.rl.ac.uk/docs/how-to/models/how-to-upload-a-model/) but you can create it with: | ||
|
||
```bash | ||
docker save -o fibonacci-model.tar finbonacci-model | ||
``` | ||
|
||
You can then also compress it before uploading: | ||
|
||
```bash | ||
gzip example-model.tar | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
kind: M | ||
api_version: v1beta3 | ||
metadata: | ||
display_name: Fibonacci for Sweep Steps | ||
name: fibonacci-sweep | ||
publisher: DAFNI Example Models | ||
contact_point_name: DAFNI | ||
contact_point_email: [email protected] | ||
summary: Generates a Fibonacci sequence | ||
description: > | ||
An example Model designed for use with DAFNI Sweep Steps. | ||
This generates a Fibonacci sequence and saves it to a json file. | ||
The name of the json file will be prefixed in the following way: | ||
{sequence length}-{f0 start number}-{f1 start number}-sequence.json | ||
this is to allow this Model to work in Sweep steps. | ||
licence: https://creativecommons.org/licenses/by/4.0/ | ||
rights: open | ||
spec: | ||
command: ["python", "/src/main.py"] | ||
inputs: | ||
parameters: | ||
- name: SEQUENCE_LENGTH | ||
title: Sequence length | ||
description: The number of items in the sequence. | ||
type: integer | ||
default: 20 | ||
min: 2 | ||
required: true | ||
- name: SEQUENCE_F0 | ||
title: F0 start number | ||
description: The initial start value for the sequence. | ||
type: integer | ||
default: 0 | ||
required: true | ||
- name: SEQUENCE_F1 | ||
title: F1 start number | ||
description: The second start value for the sequence. | ||
type: integer | ||
default: 1 | ||
required: true | ||
outputs: | ||
datasets: | ||
- name: sequence.json | ||
type: json | ||
description: A Fibonacci sequence output from the Fibonacci Example Model. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import json | ||
import os | ||
import sys | ||
from pathlib import Path | ||
|
||
from work import do_work | ||
|
||
SEQUENCE_LENGTH_DEFAULT = 20 | ||
SEQUENCE_LENGTH_MINIMUM = 2 | ||
SEQUENCE_F0_DEFAULT = 0 | ||
SEQUENCE_F1_DEFAULT = 1 | ||
|
||
output_folder = Path("/data/outputs/") | ||
output_file_name = "sequence.json" | ||
|
||
|
||
def main(): | ||
|
||
print("Starting fibonacci model") | ||
|
||
# Read values from environment variables but use default values if they don't exist | ||
sequence_length = os.getenv("SEQUENCE_LENGTH", SEQUENCE_LENGTH_DEFAULT) | ||
sequence_f0 = os.getenv("SEQUENCE_F0", SEQUENCE_F0_DEFAULT) | ||
sequence_f1 = os.getenv("SEQUENCE_F1", SEQUENCE_F1_DEFAULT) | ||
|
||
# Check each of the values are in an acceptable format for this model | ||
if not is_int(sequence_length): | ||
sys.exit("Error: SEQUENCE_LENGTH must be a whole number") | ||
|
||
sequence_length = int(sequence_length) | ||
if sequence_length < SEQUENCE_LENGTH_MINIMUM: | ||
sys.exit( | ||
f"Error: SEQUENCE_LENGTH must be a minimum of {SEQUENCE_LENGTH_MINIMUM}" | ||
) | ||
|
||
if not is_int(sequence_f0): | ||
sys.exit("Error: SEQUENCE_F0 must be whole number") | ||
|
||
if not is_int(sequence_f1): | ||
sys.exit("Error: SEQUENCE_F1 must be whole number") | ||
|
||
# Call main work | ||
sequence = do_work(sequence_length, int(sequence_f0), int(sequence_f1)) | ||
|
||
# Output the results to a file | ||
output_folder.mkdir(parents=True, exist_ok=True) | ||
output_file = output_folder.joinpath( | ||
f"{sequence_length}-{sequence_f0}-{sequence_f1}-{output_file_name}" | ||
) | ||
output_file.write_text(json.dumps({"sequence": sequence})) | ||
|
||
print("Finished fibonacci model") | ||
|
||
|
||
def is_int(value): | ||
try: | ||
int(value) | ||
return True | ||
except ValueError: | ||
return False | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
{ | ||
"@context": [ | ||
"metadata-v1" | ||
], | ||
"@type": "dcat:Dataset", | ||
"dct:title": "Published from file", | ||
"dct:description": "Dataset-description", | ||
"dct:identifier": [], | ||
"dct:subject": "Biota", | ||
"dcat:theme": [], | ||
"dct:language": "en", | ||
"dcat:keyword": [ | ||
"At least one needed" | ||
], | ||
"dct:conformsTo": { | ||
"@id": null, | ||
"@type": "dct:Standard", | ||
"label": null | ||
}, | ||
"dct:spatial": { | ||
"@id": null, | ||
"@type": "dct:Location", | ||
"rdfs:label": null | ||
}, | ||
"geojson": {}, | ||
"dct:PeriodOfTime": { | ||
"type": "dct:PeriodOfTime", | ||
"time:hasBeginning": null, | ||
"time:hasEnd": null | ||
}, | ||
"dct:accrualPeriodicity": null, | ||
"dct:created": "2021-01-18T09:51:56.096719Z", | ||
"dct:creator": [ | ||
{ | ||
"@type": "foaf:Organization", | ||
"@id": null, | ||
"foaf:name": "smile", | ||
"internalID": null | ||
} | ||
], | ||
"dct:publisher": { | ||
"@id": null, | ||
"@type": "foaf:Organization", | ||
"foaf:name": null, | ||
"internalID": null | ||
}, | ||
"dcat:contactPoint": { | ||
"@type": "vcard:Organization", | ||
"vcard:fn": null, | ||
"vcard:hasEmail": null | ||
}, | ||
"dct:license": { | ||
"@type": "LicenseDocument", | ||
"@id": "https: //creativecommons.org/licences/by/4.0/", | ||
"rdfs:label": null | ||
}, | ||
"dct:rights": null, | ||
"dafni_version_note": "Initial Dataset version" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
def do_work(number, first, second): | ||
""" | ||
Call the main processing part of the model | ||
""" | ||
|
||
print("Generating Fibonacci sequence.") | ||
print(f"Using: length={number}, first={first}, second={second}") | ||
|
||
sequence = fibonacci_sequence(number, first, second) | ||
|
||
print("Sequence: ", sequence) | ||
|
||
return sequence | ||
|
||
|
||
def fibonacci_sequence(length, f0=0, f1=1): | ||
""" | ||
Simple Fibonacci sequence generator | ||
""" | ||
sequence = [f0, f1] | ||
for pos in range(0, length - 2): | ||
sequence.append(sequence[pos] + sequence[pos + 1]) | ||
|
||
return sequence |