Skip to content

Commit

Permalink
Merge pull request #29 from michelin/yarrow-add-metrics-optional-fiel…
Browse files Browse the repository at this point in the history
…d-to-yarrow

Add metrics optional field to yarrow
  • Loading branch information
Arthemide authored Aug 19, 2024
2 parents b4055ab + f415b45 commit b3ecd5a
Show file tree
Hide file tree
Showing 14 changed files with 117 additions and 21 deletions.
5 changes: 2 additions & 3 deletions .github/workflows/test-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
python-version: ["3.8", "3.9", "3.10", "3.11"]
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-verion }}
Expand All @@ -31,8 +31,7 @@ jobs:
if: ${{ always() }}
- name: lint
run: |
black --check .
isort -c .
make check
build:
needs: test
Expand Down
18 changes: 18 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,21 @@ help:
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

VENV_NAME = .venv
PIP = $(VENV_DIR)/bin/pip

setup:
python -m venv $(VENV_NAME)
$(PIP) install --upgrade pip
$(PIP) install .[dev]

check:
black . --check
isort . --check --gitignore
autoflake --check .

lint:
black .
isort . --gitignore
autoflake -i --remove-all-unused-imports .
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ The full description can be found [here](schema/description.md) with the rules o
```sh
pip install yarrowformat
```
## Install it locally

```sh
make setup
source .venv/bin/activate
```

## How to use

Expand All @@ -41,7 +47,7 @@ yar_set.add_annotation(annot)

# now save it somewhere else
with open("path/to/other/file.yarrow.json", "w") as fp:
json.dump(yar_set.pydantic().dict(), fp, default=str)
json.dump(yar_set.pydantic().model_dump(exclude_none=True), fp, default=str)

```

Expand Down
7 changes: 6 additions & 1 deletion examples/generate_overlays/generate_overlays_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,9 @@ class FakeMeta(BaseModel):
with open(
"examples/generate_overlays/example_overlays_classes.yarrow.json", "w"
) as fp:
json.dump(yarrowset.pydantic().dict(), fp, default=str, indent=4)
json.dump(
yarrowset.pydantic().model_dump(exclude_none=True),
fp,
default=str,
indent=4,
)
9 changes: 5 additions & 4 deletions examples/generate_overlays/generate_overlays_multilayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
from datetime import datetime
from uuid import uuid4

from pydantic import BaseModel

import yarrow

if __name__ == "__main__":
Expand Down Expand Up @@ -40,12 +38,15 @@

yarrowset = yarrow.YarrowDataset(info=info)

# You shoud use the add_* method insert elements into the dataset
# You should use the add_* method insert elements into the dataset
yarrowset.add_multilayer_image(multilayer=multilayer)

with open(
"examples/generate_overlays/example_overlays_multilayer.yarrow.json", "w"
) as fp:
json.dump(
yarrowset.pydantic().dict(exclude_none=True), fp, default=str, indent=4
yarrowset.pydantic().model_dump(eexclude_none=True),
fp,
default=str,
indent=4,
)
2 changes: 1 addition & 1 deletion examples/generate_simple/generate_simple.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import json
from datetime import datetime

import yarrow
Expand All @@ -18,4 +17,5 @@

yarrowset.pydantic().save_to_file(
"examples/generate_simple/example_simple.yarrow.json",
exclude_none=True,
)
2 changes: 1 addition & 1 deletion examples/object_classes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ All previously mentioned classes (Image, Annotation and YarrowDataset) implement
```python
import json

yar_set_dict = yar_set.pydantic().dict(exclude_none=True)
yar_set_dict = yar_set.pydantic().model_dump(exclude_none=True)

with open("path/to/file.yarrow.json", "w") as fp:
json.dump(yar_set_dict, fp, default=str)
Expand Down
2 changes: 1 addition & 1 deletion examples/object_classes/demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@
yar_set.add_annotation(annot)

yar_set_dict = yar_set.pydantic().save_to_file(
"examples/object_classes/demo.yarrow.json"
"examples/object_classes/demo.yarrow.json", exclude_none=True
)
13 changes: 13 additions & 0 deletions schema/yarrow_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@
"items": {
"$ref": "#/definitions/MultilayerImage_pydantic"
}
},
"metrics": {
"title": "Metrics",
"type": "dict",
"items": {
"$ref": "#/definitions/Metrics"
}

}
},
"required": [
Expand Down Expand Up @@ -502,6 +510,11 @@
"type": "string"
}
}
},
"Metrics": {
"title": "Metrics",
"description": "Defining custom metrics links to image",
"type": "dict"
}
}
}
8 changes: 7 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ author_email = mathieu.pichon_ext@michelin.com
package_dir =
= src
packages = find:
python_requires = >= 3.7
python_requires = >= 3.8
install_requires =
setuptools
wheel
Expand All @@ -25,6 +25,7 @@ include_package_data = True
dev =
black == 22.8.0
isort
autoflake
pytest
pytest-cov
sphinx
Expand All @@ -44,3 +45,8 @@ versionfile_source = src/yarrow/_version.py
versionfile_build = yarrow/_version.py
tag_prefix = v
parentdir_prefix = yarrow-

[autoflake]
ignore-init-module-imports=true
exclude=.venv
recursive=true
4 changes: 3 additions & 1 deletion src/yarrow/yarrow.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import json
import uuid
from datetime import datetime
from typing import Any, List, Optional, Union
from typing import Any, Dict, List, Optional, Union
from warnings import warn

import numpy as np
Expand Down Expand Up @@ -70,6 +70,7 @@ def __eq__(self, other) -> bool:
if isinstance(other, Image_pydantic):
return all(
(
self.azure_url == other.azure_url,
self.file_name == other.file_name,
self.width == other.width,
self.height == other.height,
Expand Down Expand Up @@ -298,6 +299,7 @@ class YarrowDataset_pydantic(BaseModel):
contributors : Optional[List[Contributor]] = Field(default_factory=list)
categories : Optional[List[Category]] = Field(default_factory=list)
multilayer_images: Optional[List[MultilayerImage_pydantic]] = Field(default_factory=list)
metrics : Optional[Dict[str, float]] = None
# fmt: on

def __eq__(self, other: Any) -> bool:
Expand Down
12 changes: 9 additions & 3 deletions src/yarrow/yarrow_cls.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def __init__(
self.date_captured = date_captured
self.azure_url = azure_url
self.confidential = confidential
self.meta = meta or {}
self.meta = meta
self.comment = comment
self.asset_id = asset_id
self.split = split
Expand Down Expand Up @@ -199,7 +199,7 @@ def __init__(
self.num_keypoints = num_keypoints
self.weight = weight
self.date_captured = date_captured
self.meta = meta or {}
self.meta = meta

self._pydantic_self = None

Expand Down Expand Up @@ -322,7 +322,7 @@ def __init__(
self.id = id or uuid_init()
self.images = images or []
self.name = name or ""
self.meta = meta or {}
self.meta = meta
self.split = split

self._pydantic = None
Expand Down Expand Up @@ -385,6 +385,7 @@ def __init__(
confidential: List[Clearance] = None,
categories: List[Category] = None,
multilayer_images: List[MultilayerImage] = None,
metrics: Dict[str, float] = None,
) -> None:
"""Entry point for a YarrowDataset, can be created empty of images or annotations.\
Use the appropriate functions `add_annotations()` and `add_images()` to insert \
Expand All @@ -407,6 +408,7 @@ def __init__(
confidential (List[Clearance], optional): Defaults to None.
categories (List[Category], optional): Defaults to None.
multilayer_images (List[MultilayerImage], optional): Defaults to None.
metrics (Dict[str, float], optional): Defaults to None.
"""
self.info = info
self.images = images or []
Expand All @@ -415,6 +417,7 @@ def __init__(
self.confidential = confidential or []
self.categories = categories or []
self.multilayer_images = multilayer_images or []
self.metrics = metrics or {}

def __eq__(self, other: "YarrowDataset"):
if isinstance(other, YarrowDataset):
Expand All @@ -426,6 +429,7 @@ def __eq__(self, other: "YarrowDataset"):
set(self.confidential) == set(other.confidential),
set(self.categories) == set(other.categories),
set(self.multilayer_images) == set(other.multilayer_images),
set(self.metrics) == set(other.metrics),
)
)
return NotImplemented
Expand Down Expand Up @@ -603,6 +607,7 @@ def pydantic(
]
if len(self.multilayer_images) > 0
else None,
metrics=self.metrics if self.metrics else None,
)

def set_split(self, split: str) -> None:
Expand Down Expand Up @@ -780,6 +785,7 @@ def from_yarrow(cls, yarrow: YarrowDataset_pydantic) -> "YarrowDataset":
confidential=conf_list,
categories=cat_list,
multilayer_images=multilayer_list,
metrics=yarrow.metrics,
)

@classmethod
Expand Down
44 changes: 42 additions & 2 deletions tests/test_append.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from copy import deepcopy

import pytest
from pydantic import ValidationError

from yarrow import *

Expand Down Expand Up @@ -46,7 +47,7 @@ def test_append_empty(yar_dataset: YarrowDataset):
def test_save_and_load_file(yar_dataset: YarrowDataset, tmp_path):
# We save the yarrow
yar_path = os.path.join(tmp_path, "test.yarrow.json")
yar_dataset.pydantic().save_to_file(yar_path)
yar_dataset.pydantic().save_to_file(yar_path, exclude_none=True)

new_dataset = YarrowDataset.parse_file(yar_path)
compare_yarrow_datasets_pydantic(yar_dataset, new_dataset)
Expand All @@ -55,8 +56,47 @@ def test_save_and_load_file(yar_dataset: YarrowDataset, tmp_path):
def test_save_and_load_raw(yar_dataset: YarrowDataset, tmp_path):
# We save the yarrow
yar_path = os.path.join(tmp_path, "test.yarrow.json")
yar_dataset.pydantic().save_to_file(yar_path)
yar_dataset.pydantic().save_to_file(yar_path, exclude_none=True)

with open(yar_path, "rb") as jsf:
new_dataset = YarrowDataset.parse_raw(jsf)
compare_yarrow_datasets_pydantic(yar_dataset, new_dataset)


def test_pass_wrong_dict_to_metrics_should_raise():
# Given
excepted_error_msg = (
"Input should be a valid number, unable to parse string as a number"
)
excepted_number_errors = 1

# When
with pytest.raises(ValidationError) as excinfo:
YarrowDataset_pydantic(
images=[],
info=Info(source="common_flow", date_created="2021-01-01"),
metrics={"key": "wrong_value"},
)
actual_error_msg = excinfo.value.errors()[0].get("msg")
actual_number_errors = len(excinfo.value.errors())

# Then
assert len(excinfo.value.errors()) == excepted_number_errors == actual_number_errors
assert excepted_error_msg == actual_error_msg


def test_pass_good_dict_to_metrics_should_create_YarrowDataset():
# Given
excepted_object = YarrowDataset_pydantic
excepted_metrics = {"iou": 0.99}

# When
actual_yar_dataset = YarrowDataset_pydantic(
images=[],
info=Info(source="common_flow", date_created="2021-01-01"),
metrics=excepted_metrics,
)

# Then
assert type(actual_yar_dataset) == excepted_object
assert actual_yar_dataset.metrics == excepted_metrics
4 changes: 2 additions & 2 deletions tests/test_cls.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ def test_yar_cls_add_annotation(
def test_poly_mask_validator(yar_dataset: YarrowDataset):
annot = yar_dataset.annotations[0]

annot_param = annot.pydantic().dict()
annot_param = annot.pydantic().model_dump(exclude_none=True)
polygon = [[0.1, 0.1], [0.2, 0.2], [0.3, 0.3]]

annot_param["polygon"] = polygon
Expand Down Expand Up @@ -183,7 +183,7 @@ def test_image_id(yar_dataset: YarrowDataset):


def test_serialize(yar_dataset: YarrowDataset):
str_res = yar_dataset.pydantic().json(exclude_none=True)
str_res = yar_dataset.pydantic().model_dump_json(exclude_none=True)

dict_res = json.loads(str_res)

Expand Down

0 comments on commit b3ecd5a

Please sign in to comment.