ATrISys is built on Cytomine and provides a set of HTTP APIs that allow users to automate the platform through programming, including:
Below is a basic introduction to API operations.
For detailed usage, please refer to the Cytomine official documentation.
Before using the API, you need the following four pieces of information:
curl for Testingcurl -X GET \
"{HOST}/api/currentuser.json" \
-H "X-Auth-Token: {PUBLIC_KEY}" \
-H "X-Auth-Secret: {PRIVATE_KEY}"
Replace with:
{HOST}:https://www.asynapse.xyz/{PUBLIC_KEY}:your public key{PRIVATE_KEY}:your private key If successful, the API returns a JSON containing:
curl -X GET \
"{HOST}/api/project.json" \
-H "X-Auth-Token: {PUBLIC_KEY}" \
-H "X-Auth-Secret: {PRIVATE_KEY}"
The response will be a JSON array, where each object represents a project:
{"id": 123, "name": "Breast Cancer Project", ...}
You can obtain the Project ID from here.
The official Cytomine Python client is used:
pip install cytomine
from cytomine import Cytomine
HOST = "https://www.asynapse.xyz"
PUBLIC_KEY = "YOUR_PUBLIC_KEY"
PRIVATE_KEY = "YOUR_PRIVATE_KEY"
with Cytomine(HOST, PUBLIC_KEY, PRIVATE_KEY) as cyto:
print("Connected")
from cytomine.models import Project
project = Project().fetch(PROJECT_ID)
print(project.name, project.ontology)
The returned information includes:
from cytomine.models import Ontology, TermCollection
ontology = Ontology().fetch(project.ontology)
terms = TermCollection().fetch_with_filter("ontology", ontology.id)
for t in terms:
print(t.id, t.name)
Each term represents an annotation category, such as:
from cytomine.models import ImageInstanceCollection
images = ImageInstanceCollection().fetch_with_filter("project", PROJECT_ID)
print("Number of images:", len(images))
for img in images:
print(img.id, img.filename, img.width, img.height)
from cytomine.models import AnnotationCollection
image_id = 12345
W, H = img.width, img.height
MSK_DIR = "" # output dir
GEO_DIR = "" # output dir
SAVE_WHOLE_MASK = True
SAVE_PER_IMAGE_GEOJSON = True
anns = AnnotationCollection(image=image_id, showWKT=True, showTerm=True)
anns.fetch()
mask_img = None
if SAVE_WHOLE_MASK:
mask_img = Image.new("L", (W, H), 0)
drawer = ImageDraw.Draw(mask_img, "L")
if SAVE_PER_IMAGE_GEOJSON:
geo = {
"type": "FeatureCollection",
"features": []
}
for a in anns:
print(a.id, a.location, a.term)
wkt_str = a.location
try:
poly = wkt.loads(wkt_str)
except Exception:
continue
term_names = []
if getattr(a, "term", None):
term_id = a.term[0]
tname = next((t.name for t in terms if t.id == term_id), "Unlabeled")
term_names.append(tname)
else:
tname = "Unlabeled"
class_id = class_name_to_id.get(tname, 255)
if SAVE_PER_IMAGE_GEOJSON:
feature = {
"type": "Feature",
"properties": {
"image_id": image_id,
"annotation_id": a.id,
"class_id": class_id,
"class_name": tname,
},
"geometry": mapping(poly)
}
geo["features"].append(feature)
if SAVE_WHOLE_MASK:
def draw_polygon(geom):
if geom.geom_type == "Polygon":
exterior = [(x, y) for x, y in np.array(geom.exterior.coords)]
interiors = [
[(x, y) for x, y in np.array(ring.coords)]
for ring in geom.interiors
]
drawer.polygon(exterior, fill=int(class_id))
for hole in interiors:
drawer.polygon(hole, fill=0)
elif geom.geom_type == "MultiPolygon":
for g in geom.geoms:
draw_polygon(g)
draw_polygon(poly)
# === 輸出區 ===
if SAVE_PER_IMAGE_GEOJSON:
with open(os.path.join(GEO_DIR, f"{image_id}.geojson"), "w", encoding="utf-8") as jf:
json.dump(geo, jf, ensure_ascii=False)
if SAVE_WHOLE_MASK:
mask_img.save(os.path.join(MSK_DIR, f"{image_id}_mask.png"))
win_url = f"{HOST}/api/imageinstance/{image_id}/window-{W}-{H}-0-0.jpg?zoom=0"
r = cyto._session.get(win_url)
open("image.jpg","wb").write(r.content)
When using the ATrISys/Cytomine API, all permissions follow the user’s original permissions on the platform. The API cannot access any data the user is not authorized to view via the web interface. API keys and private keys are available only under individual user accounts—please keep them confidential and never share them.