Imports

[6]:
import os
import supervisely_lib as sly
import pprint

Initialize API access with your credentials

[7]:
address = os.environ['SERVER_ADDRESS']
token = os.environ['API_TOKEN']

print("Server address: ", address)
print("Your API token: ", token)

# Initialize the API access object.
api = sly.Api(address, token)
Server address:  192.168.1.69:5555
Your API token:  HfQ2owV8QjwojwnTiaPzIyEZtncIBjISnQqgBzKmDTjTL6WmV80kbd9J5DHu8PnCPVBqWBUXcOQlqjUBiCrQuUBxh562iaqAzqa4z80lJYjvxTFky5RbHDXregjOf2y8

List all registered users

[9]:
users = api.user.get_list()
print('Total number of users: ', len(users))
for user in users:
    print("Id: {:<5} Login: {:<25s} logins_count: {:<5}".format(user.id, user.login, user.logins))
print()
Total number of users:  22
Id: 1     Login: admin                     logins_count: 88
Id: 2     Login: supervisely               logins_count: 0
Id: 3     Login: andrew                    logins_count: 18
Id: 4     Login: max                       logins_count: 7
Id: 5     Login: antonc                    logins_count: 24
Id: 6     Login: umar                      logins_count: 9
Id: 7     Login: dima                      logins_count: 2
Id: 8     Login: denis                     logins_count: 1
Id: 9     Login: xxx                       logins_count: 0
Id: 10    Login: test2                     logins_count: 1
Id: 11    Login: test3                     logins_count: 2
Id: 12    Login: umar1                     logins_count: 2
Id: 13    Login: anna                      logins_count: 1
Id: 14    Login: demo_user                 logins_count: 0
Id: 20    Login: demo_user1                logins_count: 0
Id: 22    Login: demo_user2                logins_count: 0
Id: 24    Login: demo_user3                logins_count: 0
Id: 25    Login: demo_user4                logins_count: 0
Id: 29    Login: labeler_01                logins_count: 0
Id: 30    Login: labeler_02                logins_count: 0
Id: 31    Login: labeler_03                logins_count: 0
Id: 32    Login: alex                      logins_count: 0

Get UserInfo by ID

[10]:
user14_info = api.user.get_info_by_id(14)
print(user14_info)
UserInfo(id=14, login='demo_user', name='', email=None, logins=0, disabled=False, last_login=None, created_at='2019-07-18T15:57:27.271Z', updated_at='2019-07-18T15:57:27.271Z')

Get UserInfo by login

[11]:
user_info = api.user.get_info_by_login('max')
print(user_info)
UserInfo(id=4, login='max', name='max_k', email=None, logins=7, disabled=False, last_login='2019-08-02T09:18:09.155Z', created_at='2019-04-11T10:59:50.472Z', updated_at='2019-08-04T17:06:39.414Z')

Update user info

[12]:
new_password = '123321'
new_name = 'max_k'
user_info = api.user.update(user_info.id, password=new_password, name=new_name)
print(user_info)
UserInfo(id=4, login='max', name='max_k', email=None, logins=7, disabled=False, last_login='2019-08-02T09:18:09.155Z', created_at='2019-04-11T10:59:50.472Z', updated_at='2019-08-05T08:42:20.463Z')

Get User Membership (list all user teams with corresponding roles)

[13]:
def print_user_teams(login):
    user = api.user.get_info_by_login(login)
    user_teams = api.user.get_teams(user.id)
    print("\nTeams of user {!r}:".format(login))
    for team in user_teams:
        print("[team_id={}] {:<25s} [role_id={}] {}".format(team.id, team.name, team.role_id, team.role))
    print()

print_user_teams('andrew')

Teams of user 'andrew':
[team_id=7] team_x                    [role_id=1] admin
[team_id=3] jupyter_tutorials         [role_id=1] admin

Create new user

[14]:
new_user = api.user.get_info_by_login('demo_user4')
if new_user is None:
    new_user = api.user.create(login='demo_user4', password='123abc', is_restricted=False)
print(new_user)
UserInfo(id=25, login='demo_user4', name='', email=None, logins=0, disabled=False, last_login=None, created_at='2019-07-19T09:44:45.750Z', updated_at='2019-08-03T16:17:15.228Z')

Disable/Enable user

[15]:
api.user.disable(new_user.id)
api.user.enable(new_user.id)

Invite user to team

[16]:
user = api.user.get_info_by_login('demo_user4')
team = api.team.get_info_by_name('max')
if api.user.get_team_role(user.id, team.id) is None:
    api.user.add_to_team(user.id, team.id, api.role.DefaultRole.ANNOTATOR) #TODO: {"error":"NONUNIQUE","details":"User already in this team"
print_user_teams(user.login)

Teams of user 'demo_user4':
[team_id=22] demo_user4                [role_id=1] admin
[team_id=4] max                       [role_id=3] annotator

List all team users with corresponding roles

[17]:
team = api.team.get_info_by_name('max')
members = api.user.get_team_members(team.id)
print("\nAll members in team {!r}".format(team.name))
pprint.pprint(members)

All members in team 'max'
[UserInfo(id=4, login='max', name='max_k', email=None, logins=7, disabled=False, last_login='2019-08-02T09:18:09.155Z', created_at='2019-04-11T10:59:50.472Z', updated_at='2019-08-05T08:42:20.463Z'),
 UserInfo(id=25, login='demo_user4', name='', email=None, logins=0, disabled=False, last_login=None, created_at='2019-07-19T09:44:45.750Z', updated_at='2019-08-05T08:42:21.934Z'),
 UserInfo(id=29, login='labeler_01', name='', email=None, logins=0, disabled=False, last_login=None, created_at='2019-07-20T15:12:51.898Z', updated_at='2019-07-20T16:55:19.917Z'),
 UserInfo(id=30, login='labeler_02', name='', email=None, logins=0, disabled=False, last_login=None, created_at='2019-07-20T15:12:52.448Z', updated_at='2019-07-20T15:12:52.448Z'),
 UserInfo(id=31, login='labeler_03', name='', email=None, logins=0, disabled=False, last_login=None, created_at='2019-07-20T15:12:52.779Z', updated_at='2019-07-20T15:12:52.779Z')]

Change user role in team

[18]:
user = api.user.get_info_by_login('demo_user4')
team = api.team.get_info_by_name('max')
api.user.change_team_role(user.id, team.id, api.role.DefaultRole.VIEWER)
print_user_teams('demo_user4')

Teams of user 'demo_user4':
[team_id=22] demo_user4                [role_id=1] admin
[team_id=4] max                       [role_id=4] viewer

Remove user from team

[19]:
team = api.team.get_info_by_name('max')
user = api.user.get_info_by_login('demo_user4')
api.user.remove_from_team(user.id, team.id)
print_user_teams('demo_user4')

Teams of user 'demo_user4':
[team_id=22] demo_user4                [role_id=1] admin

Labeling jobs

[20]:
# create accounts for annotators with restrictions (learn more here: https://docs.enterprise.supervise.ly/jobs/)
# user will be able to login only after being added to at least one command
[21]:
labeler01 = api.user.get_info_by_login(login='labeler_01')
if labeler01 is None:
    labeler01 = api.user.create(login='labeler_01', password='labeler01pass', is_restricted=True)

labeler02 = api.user.get_info_by_login(login='labeler_02')
if labeler02 is None:
    labeler02 = api.user.create(login='labeler_02', password='labeler02pass', is_restricted=True)

Step 1. Before creating labeling Job, it is needed to add annotators to team

[22]:
team = api.team.get_info_by_name('max')
workspace = api.workspace.get_info_by_name(team.id, 'First Workspace')

if api.user.get_team_role(labeler01.id, team.id) is None:
    api.user.add_to_team(labeler01.id, team.id, api.role.DefaultRole.ANNOTATOR)
if api.user.get_team_role(labeler02.id, team.id) is None:
    api.user.add_to_team(labeler02.id, team.id, api.role.DefaultRole.ANNOTATOR)

Step 2. Define project and datasets to label

[23]:
project = api.project.get_info_by_name(workspace.id, 'tutorial_project')
project_meta_json = api.project.get_meta(project.id)
project_meta = sly.ProjectMeta.from_json(project_meta_json)
print(project_meta)

datasets = api.dataset.get_list(project.id)
pprint.pprint(datasets)
ProjectMeta:
Object Classes
+--------+-----------+----------------+
|  Name  |   Shape   |     Color      |
+--------+-----------+----------------+
|  bike  | Rectangle | [246, 255, 0]  |
|  car   |  Polygon  | [190, 85, 206] |
|  dog   |  Polygon  |  [253, 0, 0]   |
| person |   Bitmap  |  [0, 255, 18]  |
+--------+-----------+----------------+
Tags
+---------------+--------------+-----------------------+
|      Name     |  Value type  |    Possible values    |
+---------------+--------------+-----------------------+
|   car_color   |  any_string  |          None         |
|  cars_number  |  any_number  |          None         |
|      like     |     none     |          None         |
| person_gender | oneof_string |   ['male', 'female']  |
|    situated   | oneof_string | ['inside', 'outside'] |
|  vehicle_age  | oneof_string | ['modern', 'vintage'] |
+---------------+--------------+-----------------------+

[DatasetInfo(id=1585, name='dataset_01', description='', size='1277440', project_id=511, images_count=3, created_at='2019-07-18T15:39:57.377Z', updated_at='2019-07-18T15:39:57.377Z'),
 DatasetInfo(id=1586, name='dataset_02', description='', size='704971', project_id=511, images_count=2, created_at='2019-07-18T15:39:57.377Z', updated_at='2019-07-18T15:39:57.377Z')]

Labeler1 will label cars on the first dataset

[24]:
created_jobs = api.labeling_job.create(name='labeler1_cars_task',
                                       dataset_id=datasets[0].id,
                                       user_ids=[labeler01.id],
                                       readme='annotation manual for cars in markdown format here (optional)',
                                       description='short description is here (optional)',
                                       classes_to_label=["car"])
pprint.pprint(created_jobs)
[LabelingJobInfo(id=37, name='labeler1_cars_task (#18)', readme='annotation manual for cars in markdown format here (optional)', description='short description is here (optional)', team_id=4, workspace_id=7, workspace_name='First Workspace', project_id=511, project_name='tutorial_project', dataset_id=1585, dataset_name='dataset_01', created_by_id=4, created_by_login='max', assigned_to_id=29, assigned_to_login='labeler_01', created_at='2019-08-05T08:42:30.588Z', started_at=None, finished_at=None, status='pending', disabled=False, images_count=3, finished_images_count=0, rejected_images_count=0, accepted_images_count=0, classes_to_label=[], tags_to_label=[], images_range=(None, None), objects_limit_per_image=None, tags_limit_per_image=None, filter_images_by_tags=[], include_images_with_tags=[], exclude_images_with_tags=[])]

Stop Labeling Job, job will be unavailable for labeler

[25]:
api.labeling_job.stop(created_jobs[0].id)

Labeler2 will label cars on the first dataset

[26]:
created_jobs = api.labeling_job.create(name='labeler2_task_with_complex_settings',
                                       dataset_id=datasets[0].id,
                                       user_ids=[labeler02.id],
                                       readme='annotation manual for cars in markdown format here (optional)',
                                       description='short description is here (optional)',
                                       classes_to_label=["car", 'bike'],
                                       objects_limit_per_image=2,
                                       tags_to_label=["car_color", "vehicle_age"],
                                       tags_limit_per_image=5,
                                       exclude_images_with_tags=["situated"]
                                       )
pprint.pprint(created_jobs)
[LabelingJobInfo(id=38, name='labeler2_task_with_complex_settings (#9)', readme='annotation manual for cars in markdown format here (optional)', description='short description is here (optional)', team_id=4, workspace_id=7, workspace_name='First Workspace', project_id=511, project_name='tutorial_project', dataset_id=1585, dataset_name='dataset_01', created_by_id=4, created_by_login='max', assigned_to_id=30, assigned_to_login='labeler_02', created_at='2019-08-05T08:42:36.092Z', started_at=None, finished_at=None, status='pending', disabled=False, images_count=3, finished_images_count=0, rejected_images_count=0, accepted_images_count=0, classes_to_label=[], tags_to_label=[], images_range=(None, None), objects_limit_per_image=2, tags_limit_per_image=5, filter_images_by_tags=[{'id': 4174, 'positive': False, 'name': 'situated'}], include_images_with_tags=[], exclude_images_with_tags=['situated'])]

Get all labeling jobs in a team

[27]:
jobs = api.labeling_job.get_list(team.id)
pprint.pprint(jobs)
[LabelingJobInfo(id=37, name='labeler1_cars_task (#18)', readme='annotation manual for cars in markdown format here (optional)', description='short description is here (optional)', team_id=4, workspace_id=7, workspace_name='First Workspace', project_id=511, project_name='tutorial_project', dataset_id=1585, dataset_name='dataset_01', created_by_id=4, created_by_login='max', assigned_to_id=29, assigned_to_login='labeler_01', created_at='2019-08-05T08:42:30.588Z', started_at=None, finished_at=None, status='stopped', disabled=False, images_count=3, finished_images_count=0, rejected_images_count=0, accepted_images_count=0, classes_to_label=[], tags_to_label=[], images_range=(None, None), objects_limit_per_image=None, tags_limit_per_image=None, filter_images_by_tags=[], include_images_with_tags=[], exclude_images_with_tags=[]),
 LabelingJobInfo(id=38, name='labeler2_task_with_complex_settings (#9)', readme='annotation manual for cars in markdown format here (optional)', description='short description is here (optional)', team_id=4, workspace_id=7, workspace_name='First Workspace', project_id=511, project_name='tutorial_project', dataset_id=1585, dataset_name='dataset_01', created_by_id=4, created_by_login='max', assigned_to_id=30, assigned_to_login='labeler_02', created_at='2019-08-05T08:42:36.092Z', started_at=None, finished_at=None, status='pending', disabled=False, images_count=3, finished_images_count=0, rejected_images_count=0, accepted_images_count=0, classes_to_label=[], tags_to_label=[], images_range=(None, None), objects_limit_per_image=2, tags_limit_per_image=5, filter_images_by_tags=[{'id': 4174, 'positive': False, 'title': 'situated'}], include_images_with_tags=[], exclude_images_with_tags=['situated'])]

Labeling Jobs Filtering (filters [created_by_id, assigned_to_id, project_id, dataset_id] can be used in various combinations)

Get all labeling that were created by user ‘max’

[28]:
user = api.user.get_info_by_login('max')
jobs = api.labeling_job.get_list(team.id, created_by_id=user.id)
pprint.pprint(jobs)
[LabelingJobInfo(id=37, name='labeler1_cars_task (#18)', readme='annotation manual for cars in markdown format here (optional)', description='short description is here (optional)', team_id=4, workspace_id=7, workspace_name='First Workspace', project_id=511, project_name='tutorial_project', dataset_id=1585, dataset_name='dataset_01', created_by_id=4, created_by_login='max', assigned_to_id=29, assigned_to_login='labeler_01', created_at='2019-08-05T08:42:30.588Z', started_at=None, finished_at=None, status='stopped', disabled=False, images_count=3, finished_images_count=0, rejected_images_count=0, accepted_images_count=0, classes_to_label=[], tags_to_label=[], images_range=(None, None), objects_limit_per_image=None, tags_limit_per_image=None, filter_images_by_tags=[], include_images_with_tags=[], exclude_images_with_tags=[]),
 LabelingJobInfo(id=38, name='labeler2_task_with_complex_settings (#9)', readme='annotation manual for cars in markdown format here (optional)', description='short description is here (optional)', team_id=4, workspace_id=7, workspace_name='First Workspace', project_id=511, project_name='tutorial_project', dataset_id=1585, dataset_name='dataset_01', created_by_id=4, created_by_login='max', assigned_to_id=30, assigned_to_login='labeler_02', created_at='2019-08-05T08:42:36.092Z', started_at=None, finished_at=None, status='pending', disabled=False, images_count=3, finished_images_count=0, rejected_images_count=0, accepted_images_count=0, classes_to_label=[], tags_to_label=[], images_range=(None, None), objects_limit_per_image=2, tags_limit_per_image=5, filter_images_by_tags=[{'id': 4174, 'positive': False, 'title': 'situated'}], include_images_with_tags=[], exclude_images_with_tags=['situated'])]

Get all labeling that were created by user ‘max’ and were assigned to labeler02

[29]:
jobs = api.labeling_job.get_list(team.id, created_by_id=user.id, assigned_to_id=labeler02.id)
pprint.pprint(jobs)
[LabelingJobInfo(id=38, name='labeler2_task_with_complex_settings (#9)', readme='annotation manual for cars in markdown format here (optional)', description='short description is here (optional)', team_id=4, workspace_id=7, workspace_name='First Workspace', project_id=511, project_name='tutorial_project', dataset_id=1585, dataset_name='dataset_01', created_by_id=4, created_by_login='max', assigned_to_id=30, assigned_to_login='labeler_02', created_at='2019-08-05T08:42:36.092Z', started_at=None, finished_at=None, status='pending', disabled=False, images_count=3, finished_images_count=0, rejected_images_count=0, accepted_images_count=0, classes_to_label=[], tags_to_label=[], images_range=(None, None), objects_limit_per_image=2, tags_limit_per_image=5, filter_images_by_tags=[{'id': 4174, 'positive': False, 'title': 'situated'}], include_images_with_tags=[], exclude_images_with_tags=['situated'])]

Archive Labeling Job

[30]:
api.labeling_job.archive(jobs[0].id)

Get all active labeling jobs in a team

[31]:
jobs = api.labeling_job.get_list(team.id)
pprint.pprint(jobs)
[LabelingJobInfo(id=37, name='labeler1_cars_task (#18)', readme='annotation manual for cars in markdown format here (optional)', description='short description is here (optional)', team_id=4, workspace_id=7, workspace_name='First Workspace', project_id=511, project_name='tutorial_project', dataset_id=1585, dataset_name='dataset_01', created_by_id=4, created_by_login='max', assigned_to_id=29, assigned_to_login='labeler_01', created_at='2019-08-05T08:42:30.588Z', started_at=None, finished_at=None, status='stopped', disabled=False, images_count=3, finished_images_count=0, rejected_images_count=0, accepted_images_count=0, classes_to_label=[], tags_to_label=[], images_range=(None, None), objects_limit_per_image=None, tags_limit_per_image=None, filter_images_by_tags=[], include_images_with_tags=[], exclude_images_with_tags=[])]

Labeling Jobs Statuses

api.labeling_job.Status.PENDING - labeling job is created, labeler still has not started

api.labeling_job.Status.IN_PROGRESS - labeler started, but not finished

api.labeling_job.Status.ON_REVIEW - labeler finished his job, reviewer is in progress

api.labeling_job.Status.COMPLETED - reviewer completed job

api.labeling_job.Status.STOPPED - job was stopped at some stage

[33]:
job_id = 37
api.labeling_job.get_status(job_id)
[33]:
<Status.STOPPED: 'stopped'>
[37]:
job_id = 39
api.labeling_job.get_status(job_id)
[37]:
<Status.PENDING: 'pending'>
[38]:
api.labeling_job.wait(job_id, target_status=api.labeling_job.Status.ON_REVIEW) # it means that labeler is finished
print('Labeler finished his work')
api.labeling_job.wait(job_id, target_status=api.labeling_job.Status.COMPLETED) # it meant that reviewer is finished
print('Reviewer finished job review')
Labeler finished his work
Reviewer finished job review
[ ]: