sqapi


Namesqapi JSON
Version 0.58 PyPI version JSON
download
home_pagehttps://bitbucket.org/ariell/pysq
SummaryA python package that simplifies interactions with the SQUIDLE+ API. It can be used to integrate automated labelling from machine learning algorithms and plenty other cool things.
upload_time2024-10-01 10:35:36
maintainerNone
docs_urlNone
authorGreybits Engineering
requires_pythonNone
licenseMIT
keywords squidle+ api sq machine learning
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # SQAPI

`sqapi` is a python package that simplifies interactions with the 
[SQUIDLE+ API](https://squidle.org/api/help?template=api_help_page.html).
It can be used for everything from creating simple queries through to integrating automated 
labelling from machine learning algorithms and plenty other cool things.

### Installation
To install the `sqapi` module, you can use `pip`
```shell
pip install sqapi 
```

### What is this?
The `sqapi` module helps to build the `HTTP` requests that are sent to the [SQUIDLE+](squidle.org) `API`. These are 
`GET`, `POST`, `PATCH` or `DELETE` requests. Setting `verbosity=2` on the `sqapi` module will print the `HTTP` 
requests that are being made.

`sqapi` takes care of authentication, and simplifies the creation of API queries. 
For example:

```python
from sqapi.api import SQAPI

api = SQAPI(host=<HOST>, api_key=<API_KEY>, verbosity=2)  # instantiate the sqapi module
r=api.get(<ENDPOINT>)              # define a get request using a specific endpoint
r.filter(<NAME>,<OPERATORE>,<VALUE>) # define a filter to compare a property with a value using an operator
data = r.execute().json()            # perform the request & return result as JSON dict (don't set template)
```

For more information about structuring queries, check out the [Making API queries](https://squidle.org/api/help?template=api_help_page.html#api_query)
section of the SQ+ API documentation page.

Instantiating `sqapi` without an API key argument will prompt for a user login, i.e.:
```python
sqapi = SQAPI(host=<HOST>, verbosity=2)  # instantiate the sqapi module
```

You can also use it to apply built-in templates to the data that comes out of the API:
```python
r.template(<TEMPLATE>)               # format the output of the request using an inbuilt HTML template
html = r.execute().text              # perform the request & return result as text (eg: for html)
```

> **IMPORTANT:** in order to proceed, you will need a user account on [SQUIDLE+](https://squidle.org). You will also 
> need to activate your API key.

## Examples
### Creating queries
This is by no means an extensive list of possible API queries. The API is extensive and the models are documented
[here](https://squidle.org/api/help?template=api_help_page.html) and the creation of queries is documented 
[here](https://squidle.org/api/help?template=api_help_page.html#api_query). `SQAPI` enables a convenient mechanism 
for creating these queries inside of Python. For example, a basic API query to list all the annotations that have valid 
labels starting with 'ecklonia' within a spatially constrained bounding box would be:
```json
{
   "filters": [
      {
         "name": "label",
         "op": "has",
         "val": {
            "name": "name",
            "op": "ilike",
            "val": "ecklonia%"
         }
      },
      {
         "name": "point",
         "op": "has",
         "val": {
            "name": "media",
            "op": "has",
            "val": {
               "name": "poses",
               "op": "any",
               "val": {
                  "name": "geom",
                  "op": "geo_in_bbox",
                  "val": [
                     {
                        "lat": -32.020013585799155,
                        "lon": 115.49980113118502
                     },
                     {
                        "lat": -32.01995006531625,
                        "lon": 115.49987604949759
                     }
                  ]
               }
            }
         }
      }
   ]
}
```
The result of that query can be accessed dynamically through 
[here as pretty JSON](https://squidle.org/api/annotation?template=json.html&q={"filters":[{"name":"point","op":"has","val":{"name":"has_xy","op":"eq","val":true}},{"name":"point","op":"has","val":{"name":"media","op":"has","val":{"name":"poses","op":"any","val":{"name":"geom","op":"geo_in_bbox","val":[{"lat":-32.020013585799155,"lon":115.49980113118502},{"lat":-32.01995006531625,"lon":115.49987604949759}]}}}}]}) or
[here as raw JSON](https://squidle.org/api/annotation?q={"filters":[{"name":"point","op":"has","val":{"name":"has_xy","op":"eq","val":true}},{"name":"point","op":"has","val":{"name":"media","op":"has","val":{"name":"poses","op":"any","val":{"name":"geom","op":"geo_in_bbox","val":[{"lat":-32.020013585799155,"lon":115.49980113118502},{"lat":-32.01995006531625,"lon":115.49987604949759}]}}}}]}) or 
[here with a template](https://squidle.org/iframe/api/annotation?template=models/annotation/list_thumbnails.html&q={"filters":[{"name":"point","op":"has","val":{"name":"has_xy","op":"eq","val":true}},{"name":"point","op":"has","val":{"name":"media","op":"has","val":{"name":"poses","op":"any","val":{"name":"geom","op":"geo_in_bbox","val":[{"lat":-32.020013585799155,"lon":115.49980113118502},{"lat":-32.01995006531625,"lon":115.49987604949759}]}}}}]}&include_link=true).
Note with a logged in browser session, that link will extract cropped thumbnails around each annotation, but without logging in,
you'll just see a thumbnail the whole image associated with that annotation.
The Python code required to build that query could be something like:
```python
from sqapi.api import SQAPI, query_filter as qf
api = SQAPI(host="https://squidle.org", )   # optionally pass in api_key to avoid log in prompt
r = api.get("/api/annotation")
r.filter("label", "has", qf("name","ilike","ecklonia%"))   # filter for label name, % here is a wildcard matching anything
bbox = [{"lat": -32.020013585799155,"lon": 115.49980113118502},{"lat": -32.01995006531625,"lon": 115.49987604949759}]
r.filter("point", "has", qf("media", "has", qf("poses", "any", qf("geom", "geo_in_bbox", bbox))))  # filter within bounding box
```

### Random annotation BOT
This is an example of an automated labelling bot that selects random class labels to assign to points.
It provides terrible suggestions, however it provides a simple boiler-plate example of how to integrate a
Machine Learning algorithm for label suggestions.

Set up the environment and a mini project. Creating a virtual environment, is optional, but recommended.
```shell
mkdir sqbot_demo && cd sqbot_demo   # make a directory
virtualenv -p python3 env           # create a virtual environment
source env/bin/activate             # activate it
pip install sqapi                   # install sqapi
```

#### 1. Create a bot class
In this example, we'll create an automated classifier that suggests random label suggestions for an annotation_set. 
It uses the `Annotator` class from the `sqapi.annotate` module, which does most of the heavy-lifting. The implementation
of the classifier is relatively straight forward.
In your project directory, create a file named `run_bot.py`:

```python
# run_bot.py
import random
from sqapi.annotate import Annotator
from sqapi.helpers import cli_init
from sqapi.media import SQMediaObject


class RandoBOT(Annotator):
    """
    An example of an automated labelling bot that selects random class labels to assign to points.
    It provides terrible suggestions, however it provides a simple boiler-plate example of how to integrate a
    Machine Learning algorithm for label suggestions.
    """       
    def classify_point(self, mediaobj: SQMediaObject, x, y, t):
       # This method is used to generate a point prediction
       # TODO: use the mediaobj, x and y point position to generate a real classifier_code and prob
       classifier_code = random.randint(0,3)  # get a random code (0-3) to match with label_map_file
       prob = round(random.random(), 2)  # generate a random probability
       return classifier_code, prob


if __name__ == '__main__':
    # Instantiate the bot from the default CLI arguments
    bot = cli_init(RandoBOT)  
    
    # Build the annotation_set query (this can be far more complex, see examples for more)
    annotation_set_id = input("Enter the ID of the annotation_set that you want to classify: ")
    r = bot.sqapi.get("/api/annotation_set").filter(name="id", op="eq", val=annotation_set_id)  
    
    # Run the classifier with the annotation_set query
    bot.start(r)
```

The `create_parser` method is a convenience tool that allows you to build a command line parser from the  
signature of the `__init__` methods for the RandoBot class and all inherited base classes (ie: `Annotator`).

This allows you to pass arguments from the command line, and helps to show how to use it:
```shell
# from the command line, run:
python run_bot.py --help
```

It will show you all the required parameters from the base class `Annotator` as well as any extra arguments added to the 
`__init__` method of the `RandoBot` class. Parameter descriptions come from the comment block.

It is necessary to build an `annotation_set` query that will tell the `RandoBot` instance which datasets to classify.
The example above prompts for an `annotation_set_id`, however, it is possible to define much more complex queries to run
the automated classifier. 

```python
from sqapi.api import query_filter as qf
r = bot.sqapi.get("/api/annotation_set")  # create the query, as above

# Only return annotation_sets that do not already have suggestions from this user
# This is necessary to avoid repeating suggestions each time the process runs
r.filter_not(qf("children", "any", val=qf("user_id", "eq", bot.sqapi.current_user.get("id"))))

# Filter annotation sets based on ID, as above
r.filter("id", "eq", ANNOTATION_SET_ID)

# Constrain date ranges to annotation_sets ceated after a specific date
r.filter("created_at", "gt", AFTER_DATE)

# Filter annotation_sets based on a user group
r.filter("usergroups", "any", val=qf("id", "eq", USER_GROUP_ID))

# Filter annotation_sets based on the users' affiliation
r.filter("user", "has", val=qf("affiliations_usergroups", "any", val=qf("group_id", "eq", AFFILIATION_GROUP_ID)))

# Filter annotation_sets based on the number of images in the media_collection
r.filter("media_count", "lte", MEDIA_COUNT_MAX)
```

In order to add these additional parameters, you can add arguments to the command-line parser.
For examples on how to do that, checkout the [sqbot](https://bitbucket.org/ariell/sqbot/) repository.

#### 2. Create a Label Mapper File
Before you run it, you also need to create a label map file to pass into the `--label_map_file` argument. 
This maps the outputs from your classifier to real class labels in the system.

In your project directory, create a file named `rando_bot_label_map.json` 
with the following content:
```json
[
  [{"name":"vocab_elements","op":"any","val":{"name":"key","op":"eq","val":"214344"}}],
  [{"name":"vocab_elements","op":"any","val":{"name":"key","op":"eq","val":"1839"}}],
  [{"name":"vocab_elements","op":"any","val":{"name":"key","op":"eq","val":"82001000"}}],
  null 
]
```
The example above, shows a label_map file for a classifier that outputs an integer value classifier code, where `0-2` 
would be a Label class that uses the vocab_element to lookup a Label across the Label Schemes. `3` would output nothing, 
which won't be submitted.

Note: if your classifier outputs a string code instead of an integer, you can define a similar 
mapping file using a dict lookup, like:
```json
{
  "ECK": [{"name":"vocab_elements","op":"any","val":{"name":"key","op":"eq","val":"214344"}}],
  "ASC": [{"name":"vocab_elements","op":"any","val":{"name":"key","op":"eq","val":"1839"}}],
  "SUB": [{"name":"vocab_elements","op":"any","val":{"name":"key","op":"eq","val":"82001000"}}]
}
```
That will attempt to map the classifier outputs `ECK`, `ASC` and `SUB` to a Label in SQ+.

#### 3. Run your bot
Now you're ready to run your classifier `RandoBot`, by simply executing this from the command line:
```shell
# bash
# Install sqapi module using pip
pip install sqapi
# See help to show all arguments
python run_bot.py --help
# Run automated labeler algorithm with selected arguments
python run_bot.py --host https://staging.squidle.org --label_map_file rando_bot_label_map.json --prob_thresh 0.5 --email_results
```

This will prompt you for a annotation_set id and attempt to provide automated suggestions on the labels it contains 
using random class allocations and probabilities. It will only submit suggestions with a probability > 0.5 and 
it will run once (as defined by the `--poll_delay=-1` parameter) 
and it will send an email to the owner the annotation_set once complete.

Now all that's left is for you to make the labels and probabilities real, and bob's your uncle,
you've made an automated classifier.

The [sqbot](https://bitbucket.org/ariell/sqbot/) library has some examples that you can use and/or adapt for 
your purposes. Specifically with regard to classifiers:

            

Raw data

            {
    "_id": null,
    "home_page": "https://bitbucket.org/ariell/pysq",
    "name": "sqapi",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": "SQUIDLE+, API, SQ, Machine Learning",
    "author": "Greybits Engineering",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/28/2c/14a1fe81aeef85734466d66c0da41eb33891fbf0d9d1e48b8cc57ca3494e/sqapi-0.58.tar.gz",
    "platform": null,
    "description": "# SQAPI\n\n`sqapi` is a python package that simplifies interactions with the \n[SQUIDLE+ API](https://squidle.org/api/help?template=api_help_page.html).\nIt can be used for everything from creating simple queries through to integrating automated \nlabelling from machine learning algorithms and plenty other cool things.\n\n### Installation\nTo install the `sqapi` module, you can use `pip`\n```shell\npip install sqapi \n```\n\n### What is this?\nThe `sqapi` module helps to build the `HTTP` requests that are sent to the [SQUIDLE+](squidle.org) `API`. These are \n`GET`, `POST`, `PATCH` or `DELETE` requests. Setting `verbosity=2` on the `sqapi` module will print the `HTTP` \nrequests that are being made.\n\n`sqapi` takes care of authentication, and simplifies the creation of API queries. \nFor example:\n\n```python\nfrom sqapi.api import SQAPI\n\napi = SQAPI(host=<HOST>, api_key=<API_KEY>, verbosity=2)  # instantiate the sqapi module\nr=api.get(<ENDPOINT>)              # define a get request using a specific endpoint\nr.filter(<NAME>,<OPERATORE>,<VALUE>) # define a filter to compare a property with a value using an operator\ndata = r.execute().json()            # perform the request & return result as JSON dict (don't set template)\n```\n\nFor more information about structuring queries, check out the [Making API queries](https://squidle.org/api/help?template=api_help_page.html#api_query)\nsection of the SQ+ API documentation page.\n\nInstantiating `sqapi` without an API key argument will prompt for a user login, i.e.:\n```python\nsqapi = SQAPI(host=<HOST>, verbosity=2)  # instantiate the sqapi module\n```\n\nYou can also use it to apply built-in templates to the data that comes out of the API:\n```python\nr.template(<TEMPLATE>)               # format the output of the request using an inbuilt HTML template\nhtml = r.execute().text              # perform the request & return result as text (eg: for html)\n```\n\n> **IMPORTANT:** in order to proceed, you will need a user account on [SQUIDLE+](https://squidle.org). You will also \n> need to activate your API key.\n\n## Examples\n### Creating queries\nThis is by no means an extensive list of possible API queries. The API is extensive and the models are documented\n[here](https://squidle.org/api/help?template=api_help_page.html) and the creation of queries is documented \n[here](https://squidle.org/api/help?template=api_help_page.html#api_query). `SQAPI` enables a convenient mechanism \nfor creating these queries inside of Python. For example, a basic API query to list all the annotations that have valid \nlabels starting with 'ecklonia' within a spatially constrained bounding box would be:\n```json\n{\n   \"filters\": [\n      {\n         \"name\": \"label\",\n         \"op\": \"has\",\n         \"val\": {\n            \"name\": \"name\",\n            \"op\": \"ilike\",\n            \"val\": \"ecklonia%\"\n         }\n      },\n      {\n         \"name\": \"point\",\n         \"op\": \"has\",\n         \"val\": {\n            \"name\": \"media\",\n            \"op\": \"has\",\n            \"val\": {\n               \"name\": \"poses\",\n               \"op\": \"any\",\n               \"val\": {\n                  \"name\": \"geom\",\n                  \"op\": \"geo_in_bbox\",\n                  \"val\": [\n                     {\n                        \"lat\": -32.020013585799155,\n                        \"lon\": 115.49980113118502\n                     },\n                     {\n                        \"lat\": -32.01995006531625,\n                        \"lon\": 115.49987604949759\n                     }\n                  ]\n               }\n            }\n         }\n      }\n   ]\n}\n```\nThe result of that query can be accessed dynamically through \n[here as pretty JSON](https://squidle.org/api/annotation?template=json.html&q={\"filters\":[{\"name\":\"point\",\"op\":\"has\",\"val\":{\"name\":\"has_xy\",\"op\":\"eq\",\"val\":true}},{\"name\":\"point\",\"op\":\"has\",\"val\":{\"name\":\"media\",\"op\":\"has\",\"val\":{\"name\":\"poses\",\"op\":\"any\",\"val\":{\"name\":\"geom\",\"op\":\"geo_in_bbox\",\"val\":[{\"lat\":-32.020013585799155,\"lon\":115.49980113118502},{\"lat\":-32.01995006531625,\"lon\":115.49987604949759}]}}}}]}) or\n[here as raw JSON](https://squidle.org/api/annotation?q={\"filters\":[{\"name\":\"point\",\"op\":\"has\",\"val\":{\"name\":\"has_xy\",\"op\":\"eq\",\"val\":true}},{\"name\":\"point\",\"op\":\"has\",\"val\":{\"name\":\"media\",\"op\":\"has\",\"val\":{\"name\":\"poses\",\"op\":\"any\",\"val\":{\"name\":\"geom\",\"op\":\"geo_in_bbox\",\"val\":[{\"lat\":-32.020013585799155,\"lon\":115.49980113118502},{\"lat\":-32.01995006531625,\"lon\":115.49987604949759}]}}}}]}) or \n[here with a template](https://squidle.org/iframe/api/annotation?template=models/annotation/list_thumbnails.html&q={\"filters\":[{\"name\":\"point\",\"op\":\"has\",\"val\":{\"name\":\"has_xy\",\"op\":\"eq\",\"val\":true}},{\"name\":\"point\",\"op\":\"has\",\"val\":{\"name\":\"media\",\"op\":\"has\",\"val\":{\"name\":\"poses\",\"op\":\"any\",\"val\":{\"name\":\"geom\",\"op\":\"geo_in_bbox\",\"val\":[{\"lat\":-32.020013585799155,\"lon\":115.49980113118502},{\"lat\":-32.01995006531625,\"lon\":115.49987604949759}]}}}}]}&include_link=true).\nNote with a logged in browser session, that link will extract cropped thumbnails around each annotation, but without logging in,\nyou'll just see a thumbnail the whole image associated with that annotation.\nThe Python code required to build that query could be something like:\n```python\nfrom sqapi.api import SQAPI, query_filter as qf\napi = SQAPI(host=\"https://squidle.org\", )   # optionally pass in api_key to avoid log in prompt\nr = api.get(\"/api/annotation\")\nr.filter(\"label\", \"has\", qf(\"name\",\"ilike\",\"ecklonia%\"))   # filter for label name, % here is a wildcard matching anything\nbbox = [{\"lat\": -32.020013585799155,\"lon\": 115.49980113118502},{\"lat\": -32.01995006531625,\"lon\": 115.49987604949759}]\nr.filter(\"point\", \"has\", qf(\"media\", \"has\", qf(\"poses\", \"any\", qf(\"geom\", \"geo_in_bbox\", bbox))))  # filter within bounding box\n```\n\n### Random annotation BOT\nThis is an example of an automated labelling bot that selects random class labels to assign to points.\nIt provides terrible suggestions, however it provides a simple boiler-plate example of how to integrate a\nMachine Learning algorithm for label suggestions.\n\nSet up the environment and a mini project. Creating a virtual environment, is optional, but recommended.\n```shell\nmkdir sqbot_demo && cd sqbot_demo   # make a directory\nvirtualenv -p python3 env           # create a virtual environment\nsource env/bin/activate             # activate it\npip install sqapi                   # install sqapi\n```\n\n#### 1. Create a bot class\nIn this example, we'll create an automated classifier that suggests random label suggestions for an annotation_set. \nIt uses the `Annotator` class from the `sqapi.annotate` module, which does most of the heavy-lifting. The implementation\nof the classifier is relatively straight forward.\nIn your project directory, create a file named `run_bot.py`:\n\n```python\n# run_bot.py\nimport random\nfrom sqapi.annotate import Annotator\nfrom sqapi.helpers import cli_init\nfrom sqapi.media import SQMediaObject\n\n\nclass RandoBOT(Annotator):\n    \"\"\"\n    An example of an automated labelling bot that selects random class labels to assign to points.\n    It provides terrible suggestions, however it provides a simple boiler-plate example of how to integrate a\n    Machine Learning algorithm for label suggestions.\n    \"\"\"       \n    def classify_point(self, mediaobj: SQMediaObject, x, y, t):\n       # This method is used to generate a point prediction\n       # TODO: use the mediaobj, x and y point position to generate a real classifier_code and prob\n       classifier_code = random.randint(0,3)  # get a random code (0-3) to match with label_map_file\n       prob = round(random.random(), 2)  # generate a random probability\n       return classifier_code, prob\n\n\nif __name__ == '__main__':\n    # Instantiate the bot from the default CLI arguments\n    bot = cli_init(RandoBOT)  \n    \n    # Build the annotation_set query (this can be far more complex, see examples for more)\n    annotation_set_id = input(\"Enter the ID of the annotation_set that you want to classify: \")\n    r = bot.sqapi.get(\"/api/annotation_set\").filter(name=\"id\", op=\"eq\", val=annotation_set_id)  \n    \n    # Run the classifier with the annotation_set query\n    bot.start(r)\n```\n\nThe `create_parser` method is a convenience tool that allows you to build a command line parser from the  \nsignature of the `__init__` methods for the RandoBot class and all inherited base classes (ie: `Annotator`).\n\nThis allows you to pass arguments from the command line, and helps to show how to use it:\n```shell\n# from the command line, run:\npython run_bot.py --help\n```\n\nIt will show you all the required parameters from the base class `Annotator` as well as any extra arguments added to the \n`__init__` method of the `RandoBot` class. Parameter descriptions come from the comment block.\n\nIt is necessary to build an `annotation_set` query that will tell the `RandoBot` instance which datasets to classify.\nThe example above prompts for an `annotation_set_id`, however, it is possible to define much more complex queries to run\nthe automated classifier. \n\n```python\nfrom sqapi.api import query_filter as qf\nr = bot.sqapi.get(\"/api/annotation_set\")  # create the query, as above\n\n# Only return annotation_sets that do not already have suggestions from this user\n# This is necessary to avoid repeating suggestions each time the process runs\nr.filter_not(qf(\"children\", \"any\", val=qf(\"user_id\", \"eq\", bot.sqapi.current_user.get(\"id\"))))\n\n# Filter annotation sets based on ID, as above\nr.filter(\"id\", \"eq\", ANNOTATION_SET_ID)\n\n# Constrain date ranges to annotation_sets ceated after a specific date\nr.filter(\"created_at\", \"gt\", AFTER_DATE)\n\n# Filter annotation_sets based on a user group\nr.filter(\"usergroups\", \"any\", val=qf(\"id\", \"eq\", USER_GROUP_ID))\n\n# Filter annotation_sets based on the users' affiliation\nr.filter(\"user\", \"has\", val=qf(\"affiliations_usergroups\", \"any\", val=qf(\"group_id\", \"eq\", AFFILIATION_GROUP_ID)))\n\n# Filter annotation_sets based on the number of images in the media_collection\nr.filter(\"media_count\", \"lte\", MEDIA_COUNT_MAX)\n```\n\nIn order to add these additional parameters, you can add arguments to the command-line parser.\nFor examples on how to do that, checkout the [sqbot](https://bitbucket.org/ariell/sqbot/) repository.\n\n#### 2. Create a Label Mapper File\nBefore you run it, you also need to create a label map file to pass into the `--label_map_file` argument. \nThis maps the outputs from your classifier to real class labels in the system.\n\nIn your project directory, create a file named `rando_bot_label_map.json` \nwith the following content:\n```json\n[\n  [{\"name\":\"vocab_elements\",\"op\":\"any\",\"val\":{\"name\":\"key\",\"op\":\"eq\",\"val\":\"214344\"}}],\n  [{\"name\":\"vocab_elements\",\"op\":\"any\",\"val\":{\"name\":\"key\",\"op\":\"eq\",\"val\":\"1839\"}}],\n  [{\"name\":\"vocab_elements\",\"op\":\"any\",\"val\":{\"name\":\"key\",\"op\":\"eq\",\"val\":\"82001000\"}}],\n  null \n]\n```\nThe example above, shows a label_map file for a classifier that outputs an integer value classifier code, where `0-2` \nwould be a Label class that uses the vocab_element to lookup a Label across the Label Schemes. `3` would output nothing, \nwhich won't be submitted.\n\nNote: if your classifier outputs a string code instead of an integer, you can define a similar \nmapping file using a dict lookup, like:\n```json\n{\n  \"ECK\": [{\"name\":\"vocab_elements\",\"op\":\"any\",\"val\":{\"name\":\"key\",\"op\":\"eq\",\"val\":\"214344\"}}],\n  \"ASC\": [{\"name\":\"vocab_elements\",\"op\":\"any\",\"val\":{\"name\":\"key\",\"op\":\"eq\",\"val\":\"1839\"}}],\n  \"SUB\": [{\"name\":\"vocab_elements\",\"op\":\"any\",\"val\":{\"name\":\"key\",\"op\":\"eq\",\"val\":\"82001000\"}}]\n}\n```\nThat will attempt to map the classifier outputs `ECK`, `ASC` and `SUB` to a Label in SQ+.\n\n#### 3. Run your bot\nNow you're ready to run your classifier `RandoBot`, by simply executing this from the command line:\n```shell\n# bash\n# Install sqapi module using pip\npip install sqapi\n# See help to show all arguments\npython run_bot.py --help\n# Run automated labeler algorithm with selected arguments\npython run_bot.py --host https://staging.squidle.org --label_map_file rando_bot_label_map.json --prob_thresh 0.5 --email_results\n```\n\nThis will prompt you for a annotation_set id and attempt to provide automated suggestions on the labels it contains \nusing random class allocations and probabilities. It will only submit suggestions with a probability > 0.5 and \nit will run once (as defined by the `--poll_delay=-1` parameter) \nand it will send an email to the owner the annotation_set once complete.\n\nNow all that's left is for you to make the labels and probabilities real, and bob's your uncle,\nyou've made an automated classifier.\n\nThe [sqbot](https://bitbucket.org/ariell/sqbot/) library has some examples that you can use and/or adapt for \nyour purposes. Specifically with regard to classifiers:\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A python package that simplifies interactions with the SQUIDLE+ API. It can be used to integrate automated labelling from machine learning algorithms and plenty other cool things.",
    "version": "0.58",
    "project_urls": {
        "Homepage": "https://bitbucket.org/ariell/pysq"
    },
    "split_keywords": [
        "squidle+",
        " api",
        " sq",
        " machine learning"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "282c14a1fe81aeef85734466d66c0da41eb33891fbf0d9d1e48b8cc57ca3494e",
                "md5": "52e52940ed7bb6b77ea5cb939c224937",
                "sha256": "d251b5d4245e0275b73cdbdd5ca54740c8c7126663cfb4444797579c1f234a85"
            },
            "downloads": -1,
            "filename": "sqapi-0.58.tar.gz",
            "has_sig": false,
            "md5_digest": "52e52940ed7bb6b77ea5cb939c224937",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 21026,
            "upload_time": "2024-10-01T10:35:36",
            "upload_time_iso_8601": "2024-10-01T10:35:36.905758Z",
            "url": "https://files.pythonhosted.org/packages/28/2c/14a1fe81aeef85734466d66c0da41eb33891fbf0d9d1e48b8cc57ca3494e/sqapi-0.58.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-10-01 10:35:36",
    "github": false,
    "gitlab": false,
    "bitbucket": true,
    "codeberg": false,
    "bitbucket_user": "ariell",
    "bitbucket_project": "pysq",
    "lcname": "sqapi"
}
        
Elapsed time: 0.96574s