Skip to content

Commit f3c94d4

Browse files
committed
2 parents 2d82336 + 62ce6db commit f3c94d4

File tree

7 files changed

+70
-13
lines changed

7 files changed

+70
-13
lines changed

README.md

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,11 @@ pip install 'git+https://github.com/philferriere/cocoapi.git#egg=pycocotools&sub
2929
```
3030

3131

32-
The package officially supports Python 3.6+ and was tested under Linux platform.
33-
For Windows based Anaconda distribution
34-
you might also need to install *shapely* package separately:
32+
The package officially supports Python 3.6+ and was tested under Linux and
33+
Windows ([Anaconda](https://www.anaconda.com/products/individual#windows)) platforms.
3534

36-
```console
37-
conda install shapely
38-
```
39-
40-
For further steps please have a look at the [tutorial](https://superannotate.readthedocs.io/en/latest/tutorial.sdk.html).
35+
For more detailed installation steps and package usage please have a look at the
36+
[tutorial](https://superannotate.readthedocs.io/en/stable/tutorial.sdk.html).
4137

4238
## Supported Features
4339

docs/source/index.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ for COCO annotation format converters support also need to install:
5454
pip install "git+https://github.com/cocodataset/panopticapi.git"
5555
pip install "git+https://github.com/philferriere/cocoapi.git#egg=pycocotools&subdirectory=PythonAPI"
5656
57-
The package officially supports Python 3.6+ and was tested under Linux platform.
57+
The package officially supports Python 3.6+ and was tested under Linux and
58+
Windows (`Anaconda <https://www.anaconda.com/products/individual#windows>`_) platforms.
5859

5960
For more detailed installation steps and package usage please have a look at
6061
the :ref:`tutorial <ref_tutorial>`.

docs/source/tutorial.sdk.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,17 @@ for COCO annotation format converters support also need to install:
2424
pip install "git+https://github.com/cocodataset/panopticapi.git"
2525
pip install "git+https://github.com/philferriere/cocoapi.git#egg=pycocotools&subdirectory=PythonAPI"
2626
27-
The package officially supports Python 3.6+ and was tested under Linux platform.
27+
The package officially supports Python 3.6+ and was tested under Linux and
28+
Windows (`Anaconda <https://www.anaconda.com/products/individual#windows>`_) platforms.
2829

2930
For Windows based Anaconda distribution
30-
you might also need to install :py:obj:`shapely` package separately:
31+
you might also need to install beforehand :py:obj:`shapely` package:
3132

3233
.. code-block:: bash
3334
3435
conda install shapely
3536
36-
and also need to install C++ build tools from `Microsoft Visual Studio Tools
37+
and C++ build tools from `Microsoft Visual Studio Tools
3738
<https://visualstudio.microsoft.com/visual-cpp-build-tools/>`_.
3839

3940
----------

superannotate/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from .analytics.class_analytics import (
99
attribute_distribution, class_distribution
1010
)
11+
from .analytics.user_analytics import image_analytics
1112
from .analytics.common import aggregate_annotations_as_df, df_to_annotations
1213
from .annotation_helpers import (
1314
add_annotation_bbox_to_json, add_annotation_comment_to_json,
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import pandas as pd
2+
from tqdm import tqdm
3+
import plotly.express as px
4+
5+
def image_analytics(annotations_df, visualize = False):
6+
"""
7+
Aggregates image analytics: num instances/annotation time in seconds per image
8+
:param annotations_df: pandas DataFrame of project annotations
9+
:type annotations_df: pandas.DataFrame
10+
:param visulaize: enables image analytics scatter plot
11+
:type visualize: bool
12+
13+
:return: DataFrame on image analytics with columns ["image", "instances", "time"]
14+
:rtype: pandas DataFrame
15+
16+
"""
17+
def fix_spent_time(grp: pd.Series) -> pd.Series:
18+
grp = grp.copy()
19+
grp_lost_msk = (grp > 600) | (grp.isna())
20+
grp.loc[grp_lost_msk] = grp[~grp_lost_msk].median()
21+
return grp
22+
23+
analytics = {"user_id": [], "user_role": [], "image": [], "time": [], "ninstances": [] }
24+
annot_cols = ["imageName", "instanceId", "createdAt", "creatorEmail", "creatorRole"]
25+
annotations_df = annotations_df[annotations_df["creationType"] == "Manual"][annot_cols].drop_duplicates()
26+
27+
for annot, grp in annotations_df.groupby(["creatorEmail", "creatorRole"]):
28+
grp_sorted = grp.sort_values("createdAt")
29+
time_spent = grp_sorted.createdAt.diff().shift(-1).dt.total_seconds()
30+
grp["time_spent"] = fix_spent_time(time_spent)
31+
img_time = grp.groupby("imageName", as_index=False)["time_spent"].agg("sum")
32+
img_n_instance = grp.groupby("imageName")["instanceId"].agg("count")
33+
34+
analytics["image"] += img_time.imageName.tolist()
35+
analytics["time"] += img_time.time_spent.tolist()
36+
analytics["ninstances"] += img_n_instance.tolist()
37+
analytics["user_id"] += [annot[0]] * len(img_time)
38+
analytics["user_role"] += [annot[1]] * len(img_time)
39+
40+
analytics_df = pd.DataFrame(analytics)
41+
if visualize:
42+
#scatter plot of number of instances vs annotation time
43+
fig = px.scatter(
44+
analytics_df,
45+
x="ninstances",
46+
y="time",
47+
color="user_id",
48+
facet_col="user_role",
49+
custom_data = ["image"],
50+
color_discrete_sequence=px.colors.qualitative.Dark24,
51+
labels = {'user_id': "User Email", "ninstances": "Number of Instances", "time": "Annotation time"}
52+
)
53+
fig.for_each_annotation(lambda a: a.update(text=a.text.split("=")[-1]))
54+
fig.update_traces(hovertemplate="%{customdata[0]}")
55+
fig.show()
56+
return analytics_df

superannotate/api.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ def init(self, config_location=None):
7474
if "main_endpoint" in self._api_config:
7575
self._main_endpoint = self._api_config["main_endpoint"]
7676
self._verify = True
77+
if "ssl_verify" in self._api_config:
78+
self._verify = self._api_config["ssl_verify"]
7779
self._session = None
7880
self._authenticated = True
7981
response = self.send_request(

superannotate/input_converters/conversion.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ def _passes_converter_sanity(args, direction):
143143
if not test_passed:
144144
raise SABaseException(
145145
0,
146-
"Please enter valid converter values. You can check available candidates in the documentation(https://superannotate.readthedocs.io/en/latest/index.html)."
146+
"Please enter valid converter values. You can check available candidates in the documentation (https://superannotate.readthedocs.io/en/stable/index.html)."
147147
)
148148

149149

0 commit comments

Comments
 (0)