sqapi


Namesqapi JSON
Version 0.59 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_time2025-08-28 13:37:19
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
```

### Exporting a dataset
Coming soon...

### Uploading a Media Item
```python
from sqapi.api import SQAPI
import json
api = SQAPI(host="http://localhost:5000", )
data = {
  "key": "20101010101010100_CAMID",
  "deployment_id": 15640,
  "timestamp_start": "2010-10-10T10:10:10.100",
  "pose": {
    "lat": -43.2,
    "lon": 150.5,
    "dep": 10.4,
    "alt": 2.0,
    "data": {        # optional data to attach to pose (key-value pair, where val is float)
      "test": 123,
      "field": 321
    }
  },
  "data": {}   # optional data to attach to frame (JSON)
}

r=api.upload_file("/api/media/save", file_path="path/to/image.jpg", data=dict(json=json.dumps(data))).execute()
print(r.json())
```

### Adding an Annotation to a Media Object
This involves a few operations, which are typically done in separate steps:

1. Add the `media` object to the `media_collection` 
2. Add the annotation `point` with an empty `annotation` to the `annotation_set`
3. Set the `label_id` of the `annotation` to associate the `label`

If you're building up an annotation set directly from a list of media, that can be a bit cumbersome
and here is a shortcut, which allows you to do all of this in a single API call:
```python
from sqapi.api import SQAPI
api = SQAPI(host="http://localhost:5000", )

MEDIA_ID=8230624
ANNOTATION_SET_ID=12488
LABEL_ID=13308
IMG_WIDTH=640
IMG_HEIGHT=480

payload = {
    "annotation_set_id":ANNOTATION_SET_ID,
    "set_media": {"id": MEDIA_ID},
    "annotation_label": {"id":LABEL_ID,"comment":"something","likelihood":1.0,"needs_review":True},
    "pixels": {"polygon":[[50, 50],[250, 50],[250, 250],[50, 250],[50, 50]],"width":IMG_WIDTH,"height":IMG_HEIGHT},
    # "x":0.5, "y":0.5, "polygon":[[p1x, p1y],...],
    "is_targeted":True
}
r = api.post('/api/point', json_data=payload).execute()
print(r.json())
```



### Machine learning integration
The [sqbot](https://bitbucket.org/ariell/sqbot/) repository, which is based on this module (`sqapi`) has has tools and 
templates for deploying ML allgorithms in Squidle+.

            

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/4b/73/830611c95eb25387de14a6d9f1b9e65f5c0d4eabf31589d6f8e879d1cbd2/sqapi-0.59.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### Exporting a dataset\nComing soon...\n\n### Uploading a Media Item\n```python\nfrom sqapi.api import SQAPI\nimport json\napi = SQAPI(host=\"http://localhost:5000\", )\ndata = {\n  \"key\": \"20101010101010100_CAMID\",\n  \"deployment_id\": 15640,\n  \"timestamp_start\": \"2010-10-10T10:10:10.100\",\n  \"pose\": {\n    \"lat\": -43.2,\n    \"lon\": 150.5,\n    \"dep\": 10.4,\n    \"alt\": 2.0,\n    \"data\": {        # optional data to attach to pose (key-value pair, where val is float)\n      \"test\": 123,\n      \"field\": 321\n    }\n  },\n  \"data\": {}   # optional data to attach to frame (JSON)\n}\n\nr=api.upload_file(\"/api/media/save\", file_path=\"path/to/image.jpg\", data=dict(json=json.dumps(data))).execute()\nprint(r.json())\n```\n\n### Adding an Annotation to a Media Object\nThis involves a few operations, which are typically done in separate steps:\n\n1. Add the `media` object to the `media_collection` \n2. Add the annotation `point` with an empty `annotation` to the `annotation_set`\n3. Set the `label_id` of the `annotation` to associate the `label`\n\nIf you're building up an annotation set directly from a list of media, that can be a bit cumbersome\nand here is a shortcut, which allows you to do all of this in a single API call:\n```python\nfrom sqapi.api import SQAPI\napi = SQAPI(host=\"http://localhost:5000\", )\n\nMEDIA_ID=8230624\nANNOTATION_SET_ID=12488\nLABEL_ID=13308\nIMG_WIDTH=640\nIMG_HEIGHT=480\n\npayload = {\n    \"annotation_set_id\":ANNOTATION_SET_ID,\n    \"set_media\": {\"id\": MEDIA_ID},\n    \"annotation_label\": {\"id\":LABEL_ID,\"comment\":\"something\",\"likelihood\":1.0,\"needs_review\":True},\n    \"pixels\": {\"polygon\":[[50, 50],[250, 50],[250, 250],[50, 250],[50, 50]],\"width\":IMG_WIDTH,\"height\":IMG_HEIGHT},\n    # \"x\":0.5, \"y\":0.5, \"polygon\":[[p1x, p1y],...],\n    \"is_targeted\":True\n}\nr = api.post('/api/point', json_data=payload).execute()\nprint(r.json())\n```\n\n\n\n### Machine learning integration\nThe [sqbot](https://bitbucket.org/ariell/sqbot/) repository, which is based on this module (`sqapi`) has has tools and \ntemplates for deploying ML allgorithms in Squidle+.\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.59",
    "project_urls": {
        "Homepage": "https://bitbucket.org/ariell/pysq"
    },
    "split_keywords": [
        "squidle+",
        " api",
        " sq",
        " machine learning"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "4b73830611c95eb25387de14a6d9f1b9e65f5c0d4eabf31589d6f8e879d1cbd2",
                "md5": "5f9e1992e49bed2e9607a02810dcab46",
                "sha256": "50df6f31ed74ef80e399a89c89841f8684e14b2e775a9ce129c3fcee72f00ba1"
            },
            "downloads": -1,
            "filename": "sqapi-0.59.tar.gz",
            "has_sig": false,
            "md5_digest": "5f9e1992e49bed2e9607a02810dcab46",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 18026,
            "upload_time": "2025-08-28T13:37:19",
            "upload_time_iso_8601": "2025-08-28T13:37:19.350841Z",
            "url": "https://files.pythonhosted.org/packages/4b/73/830611c95eb25387de14a6d9f1b9e65f5c0d4eabf31589d6f8e879d1cbd2/sqapi-0.59.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-28 13:37:19",
    "github": false,
    "gitlab": false,
    "bitbucket": true,
    "codeberg": false,
    "bitbucket_user": "ariell",
    "bitbucket_project": "pysq",
    "lcname": "sqapi"
}
        
Elapsed time: 1.58138s