Compare commits
4
Commits
201ca0a8ee
...
b37fea850a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b37fea850a | ||
|
|
fc19c31af9 | ||
|
|
fa2230d5cf | ||
|
|
993c9a122b |
@@ -18,8 +18,8 @@ jobs:
|
|||||||
- name: Install Packages
|
- name: Install Packages
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install flake8 mypy poetry
|
pip install poetry
|
||||||
poetry install
|
poetry install --with test
|
||||||
- name: PEP8 Check
|
- name: PEP8 Check
|
||||||
run: flake8 ./src --benchmark
|
run: flake8 ./src --benchmark
|
||||||
- name: Type Check
|
- name: Type Check
|
||||||
|
|||||||
Generated
+50
-1
@@ -287,6 +287,22 @@ idna = ["idna (>=3.6)"]
|
|||||||
trio = ["trio (>=0.23)"]
|
trio = ["trio (>=0.23)"]
|
||||||
wmi = ["wmi (>=1.5.1)"]
|
wmi = ["wmi (>=1.5.1)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "flake8"
|
||||||
|
version = "7.0.0"
|
||||||
|
description = "the modular source code checker: pep8 pyflakes and co"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8.1"
|
||||||
|
files = [
|
||||||
|
{file = "flake8-7.0.0-py2.py3-none-any.whl", hash = "sha256:a6dfbb75e03252917f2473ea9653f7cd799c3064e54d4c8140044c5c065f53c3"},
|
||||||
|
{file = "flake8-7.0.0.tar.gz", hash = "sha256:33f96621059e65eec474169085dc92bf26e7b2d47366b70be2f67ab80dc25132"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
mccabe = ">=0.7.0,<0.8.0"
|
||||||
|
pycodestyle = ">=2.11.0,<2.12.0"
|
||||||
|
pyflakes = ">=3.2.0,<3.3.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flask"
|
name = "flask"
|
||||||
version = "3.0.2"
|
version = "3.0.2"
|
||||||
@@ -456,6 +472,17 @@ files = [
|
|||||||
{file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"},
|
{file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mccabe"
|
||||||
|
version = "0.7.0"
|
||||||
|
description = "McCabe checker, plugin for flake8"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
files = [
|
||||||
|
{file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"},
|
||||||
|
{file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nest-asyncio"
|
name = "nest-asyncio"
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
@@ -578,6 +605,17 @@ files = [
|
|||||||
packaging = "*"
|
packaging = "*"
|
||||||
tenacity = ">=6.2.0"
|
tenacity = ">=6.2.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pycodestyle"
|
||||||
|
version = "2.11.1"
|
||||||
|
description = "Python style guide checker"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "pycodestyle-2.11.1-py2.py3-none-any.whl", hash = "sha256:44fe31000b2d866f2e41841b18528a505fbd7fef9017b04eff4e2648a0fadc67"},
|
||||||
|
{file = "pycodestyle-2.11.1.tar.gz", hash = "sha256:41ba0e7afc9752dfb53ced5489e89f8186be00e599e712660695b7a75ff2663f"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pydantic"
|
name = "pydantic"
|
||||||
version = "2.6.1"
|
version = "2.6.1"
|
||||||
@@ -688,6 +726,17 @@ files = [
|
|||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
|
typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyflakes"
|
||||||
|
version = "3.2.0"
|
||||||
|
description = "passive checker of Python programs"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "pyflakes-3.2.0-py2.py3-none-any.whl", hash = "sha256:84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a"},
|
||||||
|
{file = "pyflakes-3.2.0.tar.gz", hash = "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pymongo"
|
name = "pymongo"
|
||||||
version = "4.6.1"
|
version = "4.6.1"
|
||||||
@@ -944,4 +993,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.12"
|
python-versions = "^3.12"
|
||||||
content-hash = "d4df77270fa7781e482a10c4671c5c22d23f4d461bbe007f98b929142078a653"
|
content-hash = "598aca4396fc86bb93d5070acdff5e0579210f65cd8e4747d7b1bc609da55cbb"
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ pymongo = "^4.6.1"
|
|||||||
dash-auth = "^2.2.0"
|
dash-auth = "^2.2.0"
|
||||||
|
|
||||||
|
|
||||||
|
[tool.poetry.group.test.dependencies]
|
||||||
|
flake8 = "^7.0.0"
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry-core"]
|
requires = ["poetry-core"]
|
||||||
build-backend = "poetry.core.masonry.api"
|
build-backend = "poetry.core.masonry.api"
|
||||||
|
|||||||
+33
-17
@@ -25,6 +25,11 @@ from src.model_textual import (
|
|||||||
SalienceModelOutput
|
SalienceModelOutput
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class NoDocumentFoundException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ModelOutputs(BaseModel):
|
class ModelOutputs(BaseModel):
|
||||||
visual_syntax: VisualSyntaxModelOutput
|
visual_syntax: VisualSyntaxModelOutput
|
||||||
contact: ContactModelOutput
|
contact: ContactModelOutput
|
||||||
@@ -52,7 +57,7 @@ class ModelOutputs(BaseModel):
|
|||||||
in cls.model_fields.items()
|
in cls.model_fields.items()
|
||||||
}
|
}
|
||||||
return cls(**kwargs)
|
return cls(**kwargs)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_annotations(
|
def from_annotations(
|
||||||
cls,
|
cls,
|
||||||
@@ -70,17 +75,28 @@ class ModelOutputs(BaseModel):
|
|||||||
) -> ModelOutputs:
|
) -> ModelOutputs:
|
||||||
"""Instantiate from annotation."""
|
"""Instantiate from annotation."""
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"visual_syntax": VisualSyntaxModelOutput.from_choice(visual_syntax),
|
"visual_syntax": VisualSyntaxModelOutput
|
||||||
"contact": ContactModelOutput.from_choice(contact),
|
.from_choice(visual_syntax),
|
||||||
"angle": AngleModelOutput.from_choice(angle),
|
"contact": ContactModelOutput
|
||||||
"point_of_view": PointOfViewModelOutput.from_choice(point_of_view),
|
.from_choice(contact),
|
||||||
"distance": DistanceModelOutput.from_choice(distance),
|
"angle": AngleModelOutput
|
||||||
"modality_lighting": ModalityLightingModelOutput.from_choice(modality_lighting),
|
.from_choice(angle),
|
||||||
"modality_color": ModalityColorModelOutput.from_choice(modality_color),
|
"point_of_view": PointOfViewModelOutput
|
||||||
"modality_depth": ModalityDepthModelOutput.from_choice(modality_depth),
|
.from_choice(point_of_view),
|
||||||
"information_value": InformationValueModelOutput.from_choice(information_value),
|
"distance": DistanceModelOutput
|
||||||
"framing": FramingModelOutput.from_choice(framing),
|
.from_choice(distance),
|
||||||
"salience": SalienceModelOutput.from_choice(salience)
|
"modality_lighting": ModalityLightingModelOutput
|
||||||
|
.from_choice(modality_lighting),
|
||||||
|
"modality_color": ModalityColorModelOutput
|
||||||
|
.from_choice(modality_color),
|
||||||
|
"modality_depth": ModalityDepthModelOutput
|
||||||
|
.from_choice(modality_depth),
|
||||||
|
"information_value": InformationValueModelOutput
|
||||||
|
.from_choice(information_value),
|
||||||
|
"framing": FramingModelOutput
|
||||||
|
.from_choice(framing),
|
||||||
|
"salience": SalienceModelOutput
|
||||||
|
.from_choice(salience)
|
||||||
}
|
}
|
||||||
return cls(**kwargs)
|
return cls(**kwargs)
|
||||||
|
|
||||||
@@ -115,7 +131,10 @@ class VisualCommunication(BaseModel):
|
|||||||
|
|
||||||
@field_validator("image", mode="before")
|
@field_validator("image", mode="before")
|
||||||
@classmethod
|
@classmethod
|
||||||
def convert_to_image(cls, image: Image.Image | BytesIO | bytes) -> Image.Image:
|
def convert_to_image(
|
||||||
|
cls,
|
||||||
|
image: Image.Image | BytesIO | bytes
|
||||||
|
) -> Image.Image:
|
||||||
if isinstance(image, bytes):
|
if isinstance(image, bytes):
|
||||||
image = BytesIO(image)
|
image = BytesIO(image)
|
||||||
if isinstance(image, BytesIO):
|
if isinstance(image, BytesIO):
|
||||||
@@ -124,7 +143,7 @@ class VisualCommunication(BaseModel):
|
|||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return f"{self.classname()}(name='{self.name}')"
|
return f"{self.classname()}(name='{self.name}')"
|
||||||
|
|
||||||
def webencoded_image(self) -> str:
|
def webencoded_image(self) -> str:
|
||||||
"""Convert image to be displayed on webpage."""
|
"""Convert image to be displayed on webpage."""
|
||||||
# convert images to bytes string
|
# convert images to bytes string
|
||||||
@@ -138,6 +157,3 @@ class VisualCommunication(BaseModel):
|
|||||||
if not force and self.prediction is not None:
|
if not force and self.prediction is not None:
|
||||||
logging.warning("set force=True to overwrite existing values.")
|
logging.warning("set force=True to overwrite existing values.")
|
||||||
self.prediction = ModelOutputs.from_random()
|
self.prediction = ModelOutputs.from_random()
|
||||||
|
|
||||||
class NoDocumentFoundException(Exception):
|
|
||||||
pass
|
|
||||||
|
|||||||
+20
-8
@@ -20,15 +20,17 @@ def total_annotated(
|
|||||||
) -> int:
|
) -> int:
|
||||||
"""Get total number of annotated documents in database."""
|
"""Get total number of annotated documents in database."""
|
||||||
query = {
|
query = {
|
||||||
"annotation": { "$ne": None }
|
"annotation": {
|
||||||
|
"$ne": None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return collection.count_documents(filter=query)
|
return collection.count_documents(filter=query)
|
||||||
|
|
||||||
|
|
||||||
def get_visual_communication(
|
def get_visual_communication(
|
||||||
collection: Collection,
|
collection: Collection,
|
||||||
with_annotation: bool = False
|
with_annotation: bool = False
|
||||||
) -> VisualCommunication:
|
) -> VisualCommunication:
|
||||||
"""Get a random visual communication from the database."""
|
"""Get a random visual communication from the database."""
|
||||||
query = {}
|
query = {}
|
||||||
if with_annotation:
|
if with_annotation:
|
||||||
@@ -36,8 +38,14 @@ def get_visual_communication(
|
|||||||
else:
|
else:
|
||||||
query["annotation"] = None
|
query["annotation"] = None
|
||||||
data = collection.aggregate([
|
data = collection.aggregate([
|
||||||
{ "$match": query }, # find using filters
|
{
|
||||||
{ "$sample": { "size": 1 } } # get one random
|
"$match": query # find using filters
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$sample": {
|
||||||
|
"size": 1 # get one random
|
||||||
|
}
|
||||||
|
}
|
||||||
])
|
])
|
||||||
data = list(data) # read data from cursor object
|
data = list(data) # read data from cursor object
|
||||||
if len(data) == 0:
|
if len(data) == 0:
|
||||||
@@ -58,7 +66,9 @@ def upsert_predictions(
|
|||||||
"name": vis_com_name
|
"name": vis_com_name
|
||||||
}
|
}
|
||||||
update = {
|
update = {
|
||||||
"$set": { "prediction": predictions.model_dump() }
|
"$set": {
|
||||||
|
"prediction": predictions.model_dump()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
res = collection.update_one(
|
res = collection.update_one(
|
||||||
filter=query,
|
filter=query,
|
||||||
@@ -79,7 +89,9 @@ def upsert_annotations(
|
|||||||
"name": vis_com_name
|
"name": vis_com_name
|
||||||
}
|
}
|
||||||
update = {
|
update = {
|
||||||
"$set": { "annotation": annotations.model_dump() }
|
"$set": {
|
||||||
|
"annotation": annotations.model_dump()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
res = collection.update_one(
|
res = collection.update_one(
|
||||||
filter=query,
|
filter=query,
|
||||||
|
|||||||
+3
-4
@@ -1,9 +1,10 @@
|
|||||||
import logging
|
import logging
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import logging
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from src.web import app
|
||||||
|
|
||||||
# prepare optional local setup
|
# prepare optional local setup
|
||||||
env_path = Path(__file__).parent.parent / "local.env"
|
env_path = Path(__file__).parent.parent / "local.env"
|
||||||
load_dotenv(env_path)
|
load_dotenv(env_path)
|
||||||
@@ -38,8 +39,6 @@ datefmt = '%Y-%m-%d %H:%M:%S'
|
|||||||
logging.basicConfig(format=fmt, datefmt=datefmt, level=logging.INFO)
|
logging.basicConfig(format=fmt, datefmt=datefmt, level=logging.INFO)
|
||||||
|
|
||||||
logging.info("initialized app")
|
logging.info("initialized app")
|
||||||
|
|
||||||
from src.web import app
|
|
||||||
server = app.server
|
server = app.server
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
@@ -47,4 +46,4 @@ if __name__ == "__main__":
|
|||||||
os.environ["MONGO_HOST"] = "localhost"
|
os.environ["MONGO_HOST"] = "localhost"
|
||||||
# run app
|
# run app
|
||||||
app.run(debug=True)
|
app.run(debug=True)
|
||||||
logging.info("started app")
|
logging.info("started app")
|
||||||
|
|||||||
@@ -1,24 +1 @@
|
|||||||
from .classes import VisualSyntaxModelOutput
|
from .classes import VisualSyntaxModelOutput
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# CLASS_NAME_LIST = Literal[
|
|
||||||
# "non transactional action",
|
|
||||||
# "non transactional reaction",
|
|
||||||
# "unidirectional transactional action",
|
|
||||||
# "unidirectional transactional reaction",
|
|
||||||
# "bidirectional transactional action",
|
|
||||||
# "bidirectional transactional reaction",
|
|
||||||
# "conversion",
|
|
||||||
# "speech process",
|
|
||||||
# "classification overt taxonomy",
|
|
||||||
# "analytical exhaustive",
|
|
||||||
# "analytical disarranged",
|
|
||||||
# "analytical temporal",
|
|
||||||
# "analytical distributed",
|
|
||||||
# "anaytical topological",
|
|
||||||
# "analytical exploded",
|
|
||||||
# "analytical inclusive",
|
|
||||||
# "symbolic suggestive",
|
|
||||||
# "symbolic attributive"
|
|
||||||
# ]
|
|
||||||
@@ -6,6 +6,7 @@ import random
|
|||||||
class OptionNotSetException(Exception):
|
class OptionNotSetException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ModelOutput(BaseModel):
|
class ModelOutput(BaseModel):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -17,13 +18,13 @@ class ModelOutput(BaseModel):
|
|||||||
def list_fields(cls) -> List[str]:
|
def list_fields(cls) -> List[str]:
|
||||||
"""List options that are stored as attributes."""
|
"""List options that are stored as attributes."""
|
||||||
return list(cls.model_fields.keys())
|
return list(cls.model_fields.keys())
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_random(cls):
|
def from_random(cls):
|
||||||
"""Instantiate with random numbers."""
|
"""Instantiate with random numbers."""
|
||||||
kwargs = {field: random.random() for field in cls.list_fields()}
|
kwargs = {field: random.random() for field in cls.list_fields()}
|
||||||
return cls(**kwargs)
|
return cls(**kwargs)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_choice(cls, option: str):
|
def from_choice(cls, option: str):
|
||||||
"""Instantiate from choice."""
|
"""Instantiate from choice."""
|
||||||
@@ -31,7 +32,8 @@ class ModelOutput(BaseModel):
|
|||||||
raise ValidationError()
|
raise ValidationError()
|
||||||
assert isinstance(option, str), "option is not a string"
|
assert isinstance(option, str), "option is not a string"
|
||||||
allowed_options_list = cls.list_fields()
|
allowed_options_list = cls.list_fields()
|
||||||
assert option in allowed_options_list, f"{option} is not among allowed fields {allowed_options_list}"
|
assert option in allowed_options_list, \
|
||||||
|
f"{option} is not among allowed fields {allowed_options_list}"
|
||||||
kwargs = {field: 0 for field in cls.list_fields()}
|
kwargs = {field: 0 for field in cls.list_fields()}
|
||||||
kwargs[option] = 1
|
kwargs[option] = 1
|
||||||
return cls(**kwargs)
|
return cls(**kwargs)
|
||||||
@@ -39,15 +41,19 @@ class ModelOutput(BaseModel):
|
|||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
model_dict = self.model_dump()
|
model_dict = self.model_dump()
|
||||||
model_repr_str = f"{self.classname()}("
|
model_repr_str = f"{self.classname()}("
|
||||||
model_repr_str += ", ".join([f"{field}={value:.3f}" for field, value in model_dict.items()])
|
model_repr_str += ", ".join([
|
||||||
|
f"{field}={value:.3f}"
|
||||||
|
for field, value
|
||||||
|
in model_dict.items()
|
||||||
|
])
|
||||||
model_repr_str += ")"
|
model_repr_str += ")"
|
||||||
return model_repr_str
|
return model_repr_str
|
||||||
|
|
||||||
def highest_score_field(self) -> str:
|
def highest_score_field(self) -> str:
|
||||||
"""Return name of field with highest score."""
|
"""Return name of field with highest score."""
|
||||||
model_dict = self.model_dump()
|
model_dict = self.model_dump()
|
||||||
return max(model_dict, key=lambda k: model_dict[k])
|
return max(model_dict, key=lambda k: model_dict[k])
|
||||||
|
|
||||||
def highest_score_value(self) -> float:
|
def highest_score_value(self) -> float:
|
||||||
"""Return value of field with highest score."""
|
"""Return value of field with highest score."""
|
||||||
model_dict = self.model_dump()
|
model_dict = self.model_dump()
|
||||||
|
|||||||
@@ -6,4 +6,4 @@ from .classes import (
|
|||||||
ModalityLightingModelOutput,
|
ModalityLightingModelOutput,
|
||||||
ModalityColorModelOutput,
|
ModalityColorModelOutput,
|
||||||
ModalityDepthModelOutput
|
ModalityDepthModelOutput
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -14,13 +14,13 @@ class ModelOutput(BaseModel):
|
|||||||
def list_fields(cls) -> List[str]:
|
def list_fields(cls) -> List[str]:
|
||||||
"""List options that are stored as attributes."""
|
"""List options that are stored as attributes."""
|
||||||
return list(cls.model_fields.keys())
|
return list(cls.model_fields.keys())
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_random(cls):
|
def from_random(cls):
|
||||||
"""Instantiate with random numbers."""
|
"""Instantiate with random numbers."""
|
||||||
kwargs = {field: random.random() for field in cls.list_fields()}
|
kwargs = {field: random.random() for field in cls.list_fields()}
|
||||||
return cls(**kwargs)
|
return cls(**kwargs)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_choice(cls, option: str):
|
def from_choice(cls, option: str):
|
||||||
"""Instantiate from choice."""
|
"""Instantiate from choice."""
|
||||||
@@ -28,7 +28,8 @@ class ModelOutput(BaseModel):
|
|||||||
raise ValidationError()
|
raise ValidationError()
|
||||||
assert isinstance(option, str)
|
assert isinstance(option, str)
|
||||||
allowed_options_list = cls.list_fields()
|
allowed_options_list = cls.list_fields()
|
||||||
assert option in allowed_options_list, f"{option} is not among allowed fields {allowed_options_list}"
|
assert option in allowed_options_list, \
|
||||||
|
f"{option} is not among allowed fields {allowed_options_list}"
|
||||||
kwargs = {field: 0 for field in cls.list_fields()}
|
kwargs = {field: 0 for field in cls.list_fields()}
|
||||||
kwargs[option] = 1
|
kwargs[option] = 1
|
||||||
return cls(**kwargs)
|
return cls(**kwargs)
|
||||||
@@ -36,15 +37,19 @@ class ModelOutput(BaseModel):
|
|||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
model_dict = self.model_dump()
|
model_dict = self.model_dump()
|
||||||
model_repr_str = f"{self.classname()}("
|
model_repr_str = f"{self.classname()}("
|
||||||
model_repr_str += ", ".join([f"{field}={value:.3f}" for field, value in model_dict.items()])
|
model_repr_str += ", ".join([
|
||||||
|
f"{field}={value:.3f}"
|
||||||
|
for field, value
|
||||||
|
in model_dict.items()
|
||||||
|
])
|
||||||
model_repr_str += ")"
|
model_repr_str += ")"
|
||||||
return model_repr_str
|
return model_repr_str
|
||||||
|
|
||||||
def highest_score_field(self) -> str:
|
def highest_score_field(self) -> str:
|
||||||
"""Return name of field with highest score."""
|
"""Return name of field with highest score."""
|
||||||
model_dict = self.model_dump()
|
model_dict = self.model_dump()
|
||||||
return max(model_dict, key=lambda k: model_dict[k])
|
return max(model_dict, key=lambda k: model_dict[k])
|
||||||
|
|
||||||
def highest_score_value(self) -> float:
|
def highest_score_value(self) -> float:
|
||||||
"""Return value of field with highest score."""
|
"""Return value of field with highest score."""
|
||||||
model_dict = self.model_dump()
|
model_dict = self.model_dump()
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ from .classes import (
|
|||||||
InformationValueModelOutput,
|
InformationValueModelOutput,
|
||||||
FramingModelOutput,
|
FramingModelOutput,
|
||||||
SalienceModelOutput
|
SalienceModelOutput
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -14,13 +14,13 @@ class ModelOutput(BaseModel):
|
|||||||
def list_fields(cls) -> List[str]:
|
def list_fields(cls) -> List[str]:
|
||||||
"""List options that are stored as attributes."""
|
"""List options that are stored as attributes."""
|
||||||
return list(cls.model_fields.keys())
|
return list(cls.model_fields.keys())
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_random(cls):
|
def from_random(cls):
|
||||||
"""Instantiate with random numbers."""
|
"""Instantiate with random numbers."""
|
||||||
kwargs = {field: random.random() for field in cls.list_fields()}
|
kwargs = {field: random.random() for field in cls.list_fields()}
|
||||||
return cls(**kwargs)
|
return cls(**kwargs)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_choice(cls, option: str):
|
def from_choice(cls, option: str):
|
||||||
"""Instantiate from choice."""
|
"""Instantiate from choice."""
|
||||||
@@ -28,7 +28,8 @@ class ModelOutput(BaseModel):
|
|||||||
raise ValidationError()
|
raise ValidationError()
|
||||||
assert isinstance(option, str)
|
assert isinstance(option, str)
|
||||||
allowed_options_list = cls.list_fields()
|
allowed_options_list = cls.list_fields()
|
||||||
assert option in allowed_options_list, f"{option} is not among allowed fields {allowed_options_list}"
|
assert option in allowed_options_list, \
|
||||||
|
f"{option} is not among allowed fields {allowed_options_list}"
|
||||||
kwargs = {field: 0 for field in cls.list_fields()}
|
kwargs = {field: 0 for field in cls.list_fields()}
|
||||||
kwargs[option] = 1
|
kwargs[option] = 1
|
||||||
return cls(**kwargs)
|
return cls(**kwargs)
|
||||||
@@ -36,15 +37,19 @@ class ModelOutput(BaseModel):
|
|||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
model_dict = self.model_dump()
|
model_dict = self.model_dump()
|
||||||
model_repr_str = f"{self.classname()}("
|
model_repr_str = f"{self.classname()}("
|
||||||
model_repr_str += ", ".join([f"{field}={value:.3f}" for field, value in model_dict.items()])
|
model_repr_str += ", ".join([
|
||||||
|
f"{field}={value:.3f}"
|
||||||
|
for field, value
|
||||||
|
in model_dict.items()
|
||||||
|
])
|
||||||
model_repr_str += ")"
|
model_repr_str += ")"
|
||||||
return model_repr_str
|
return model_repr_str
|
||||||
|
|
||||||
def highest_score_field(self) -> str:
|
def highest_score_field(self) -> str:
|
||||||
"""Return name of field with highest score."""
|
"""Return name of field with highest score."""
|
||||||
model_dict = self.model_dump()
|
model_dict = self.model_dump()
|
||||||
return max(model_dict, key=lambda k: model_dict[k])
|
return max(model_dict, key=lambda k: model_dict[k])
|
||||||
|
|
||||||
def highest_score_value(self) -> float:
|
def highest_score_value(self) -> float:
|
||||||
"""Return value of field with highest score."""
|
"""Return value of field with highest score."""
|
||||||
model_dict = self.model_dump()
|
model_dict = self.model_dump()
|
||||||
@@ -84,4 +89,4 @@ if __name__ == '__main__':
|
|||||||
m = SalienceModelOutput.from_random()
|
m = SalienceModelOutput.from_random()
|
||||||
print(repr(m))
|
print(repr(m))
|
||||||
print(m.highest_score_field())
|
print(m.highest_score_field())
|
||||||
print(m.highest_score_value())
|
print(m.highest_score_value())
|
||||||
|
|||||||
+7
-5
@@ -30,6 +30,7 @@ BasicAuth(app, AUTH_DICT)
|
|||||||
# connect to database
|
# connect to database
|
||||||
collection, db, client = connect()
|
collection, db, client = connect()
|
||||||
|
|
||||||
|
|
||||||
# define callbacks
|
# define callbacks
|
||||||
@app.callback(
|
@app.callback(
|
||||||
Output("alert-element", "is_open"),
|
Output("alert-element", "is_open"),
|
||||||
@@ -44,6 +45,7 @@ def show_alert(
|
|||||||
logging.info(f"updated alert message: {msg}")
|
logging.info(f"updated alert message: {msg}")
|
||||||
return True, msg
|
return True, msg
|
||||||
|
|
||||||
|
|
||||||
@app.callback(
|
@app.callback(
|
||||||
Output("alert-message", "data"),
|
Output("alert-message", "data"),
|
||||||
Output("vis-com-name", "data"),
|
Output("vis-com-name", "data"),
|
||||||
@@ -73,7 +75,7 @@ def cycle_visual_communication_data(
|
|||||||
annotation_values
|
annotation_values
|
||||||
]
|
]
|
||||||
# check if next-button clicked
|
# check if next-button clicked
|
||||||
if n_clicks == 0:
|
if n_clicks == 0:
|
||||||
logging.info("stopping early: next-button has not yet been clicked")
|
logging.info("stopping early: next-button has not yet been clicked")
|
||||||
return response
|
return response
|
||||||
# check if visual communication name is set
|
# check if visual communication name is set
|
||||||
@@ -102,13 +104,13 @@ def cycle_visual_communication_data(
|
|||||||
in annotation_values
|
in annotation_values
|
||||||
]
|
]
|
||||||
annotations = {
|
annotations = {
|
||||||
key: value
|
key: value
|
||||||
for key, value
|
for key, value
|
||||||
in zip(annotation_keys, annotation_values)
|
in zip(annotation_keys, annotation_values)
|
||||||
}
|
}
|
||||||
# instantiate ModelOutputs object
|
# instantiate ModelOutputs object
|
||||||
annotations = ModelOutputs.from_annotations(**annotations)
|
annotations = ModelOutputs.from_annotations(**annotations)
|
||||||
# save data to
|
# save data to database
|
||||||
upsert_annotations(
|
upsert_annotations(
|
||||||
collection=collection,
|
collection=collection,
|
||||||
vis_com_name=vis_com_name,
|
vis_com_name=vis_com_name,
|
||||||
@@ -137,7 +139,7 @@ def cycle_visual_communication_data(
|
|||||||
# reset annotations
|
# reset annotations
|
||||||
annotation_values = [None for elem in annotation_values]
|
annotation_values = [None for elem in annotation_values]
|
||||||
except NoDocumentFoundException:
|
except NoDocumentFoundException:
|
||||||
msg = f"no unannotated data in database"
|
msg = "no unannotated data in database"
|
||||||
logging.warning(msg)
|
logging.warning(msg)
|
||||||
response[0] = msg
|
response[0] = msg
|
||||||
return tuple(response)
|
return tuple(response)
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
from .layout import app_layout
|
from .layout import app_layout
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from dash import html, dcc
|
from dash import html
|
||||||
import dash_bootstrap_components as dbc
|
import dash_bootstrap_components as dbc
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import dash_mantine_components as dmc
|
import dash_mantine_components as dmc
|
||||||
from dash import dcc, html
|
|
||||||
from typing import List
|
|
||||||
|
|
||||||
from .image import image_element
|
from .image import image_element
|
||||||
from .inputs import inputs_element
|
from .inputs import inputs_element
|
||||||
@@ -17,4 +15,4 @@ body_element = dmc.Container(
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -20,4 +20,4 @@ inputs_element = dmc.SimpleGrid(
|
|||||||
labels_element,
|
labels_element,
|
||||||
next_button
|
next_button
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ from src.model_textual import (
|
|||||||
SalienceModelOutput
|
SalienceModelOutput
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def generate_option_labels(model) -> List[str]:
|
def generate_option_labels(model) -> List[str]:
|
||||||
"""Generate presentable list of attributes from an OutputModel."""
|
"""Generate presentable list of attributes from an OutputModel."""
|
||||||
labels = [
|
labels = [
|
||||||
@@ -28,35 +29,51 @@ def generate_option_labels(model) -> List[str]:
|
|||||||
]
|
]
|
||||||
return labels
|
return labels
|
||||||
|
|
||||||
|
|
||||||
def generate_visual_syntax_options_map():
|
def generate_visual_syntax_options_map():
|
||||||
"""Generate map of titles and options for visual syntax labels."""
|
"""Generate map of titles and options for visual syntax labels."""
|
||||||
options_map = {}
|
options_map = {}
|
||||||
# add experiential labels
|
# add experiential labels
|
||||||
options_map["visual syntax"] = generate_option_labels(VisualSyntaxModelOutput)
|
options_map["visual syntax"] = generate_option_labels(
|
||||||
|
VisualSyntaxModelOutput
|
||||||
|
)
|
||||||
return options_map
|
return options_map
|
||||||
|
|
||||||
|
|
||||||
def generate_interpersonal_options_map():
|
def generate_interpersonal_options_map():
|
||||||
"""Generate map of titles and options for interpersonal labels."""
|
"""Generate map of titles and options for interpersonal labels."""
|
||||||
options_map = {}
|
options_map = {}
|
||||||
# add interpersonal labels
|
# add interpersonal labels
|
||||||
options_map["contact"] = generate_option_labels(ContactModelOutput)
|
options_map["contact"] = generate_option_labels(ContactModelOutput)
|
||||||
options_map["angle"] = generate_option_labels(AngleModelOutput)
|
options_map["angle"] = generate_option_labels(AngleModelOutput)
|
||||||
options_map["point of view"] = generate_option_labels(PointOfViewModelOutput)
|
options_map["point of view"] = generate_option_labels(
|
||||||
|
PointOfViewModelOutput
|
||||||
|
)
|
||||||
options_map["distance"] = generate_option_labels(DistanceModelOutput)
|
options_map["distance"] = generate_option_labels(DistanceModelOutput)
|
||||||
options_map["modality lighting"] = generate_option_labels(ModalityLightingModelOutput)
|
options_map["modality lighting"] = generate_option_labels(
|
||||||
options_map["modality color"] = generate_option_labels(ModalityColorModelOutput)
|
ModalityLightingModelOutput
|
||||||
options_map["modality depth"] = generate_option_labels(ModalityDepthModelOutput)
|
)
|
||||||
|
options_map["modality color"] = generate_option_labels(
|
||||||
|
ModalityColorModelOutput
|
||||||
|
)
|
||||||
|
options_map["modality depth"] = generate_option_labels(
|
||||||
|
ModalityDepthModelOutput
|
||||||
|
)
|
||||||
return options_map
|
return options_map
|
||||||
|
|
||||||
|
|
||||||
def generate_textual_options_map():
|
def generate_textual_options_map():
|
||||||
"""Generate map of titles and options for textual labels."""
|
"""Generate map of titles and options for textual labels."""
|
||||||
options_map = {}
|
options_map = {}
|
||||||
# add textual labels
|
# add textual labels
|
||||||
options_map["information value"] = generate_option_labels(InformationValueModelOutput)
|
options_map["information value"] = generate_option_labels(
|
||||||
|
InformationValueModelOutput
|
||||||
|
)
|
||||||
options_map["framing"] = generate_option_labels(FramingModelOutput)
|
options_map["framing"] = generate_option_labels(FramingModelOutput)
|
||||||
options_map["salience"] = generate_option_labels(SalienceModelOutput)
|
options_map["salience"] = generate_option_labels(SalienceModelOutput)
|
||||||
return options_map
|
return options_map
|
||||||
|
|
||||||
|
|
||||||
# prepare experiential container
|
# prepare experiential container
|
||||||
experiential_map = generate_visual_syntax_options_map()
|
experiential_map = generate_visual_syntax_options_map()
|
||||||
experiential_container = dmc.Col(
|
experiential_container = dmc.Col(
|
||||||
@@ -118,4 +135,4 @@ labels_element = dmc.Grid(
|
|||||||
interpersonal_container,
|
interpersonal_container,
|
||||||
textual_container,
|
textual_container,
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
from dash import dcc
|
|
||||||
import dash_mantine_components as dmc
|
import dash_mantine_components as dmc
|
||||||
|
|
||||||
from .stores import stores_element
|
from .stores import stores_element
|
||||||
|
|||||||
@@ -5,12 +5,14 @@ import os
|
|||||||
storage_type = "session"
|
storage_type = "session"
|
||||||
if "ENV" in os.environ and os.getenv("ENV") == "DEV":
|
if "ENV" in os.environ and os.getenv("ENV") == "DEV":
|
||||||
storage_type = "memory"
|
storage_type = "memory"
|
||||||
logging.info(f"ENV=DEV -> dcc.Stores changed to storage_type={storage_type}")
|
logging.info(
|
||||||
|
"ENV=DEV -> dcc.Stores changed to storage_type=%s",
|
||||||
|
storage_type
|
||||||
|
)
|
||||||
|
|
||||||
stores_element = html.Div(
|
stores_element = html.Div(
|
||||||
children=[
|
children=[
|
||||||
dcc.Store(id="alert-message", storage_type=storage_type, data=""),
|
dcc.Store(id="alert-message", storage_type=storage_type, data=""),
|
||||||
dcc.Store(id="vis-com-name", storage_type=storage_type, data=""),
|
dcc.Store(id="vis-com-name", storage_type=storage_type, data=""),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -10,8 +10,12 @@ if __name__ == "__main__":
|
|||||||
img_path_list = [path for path in img_dir.glob("*.jpeg") if path.is_file()]
|
img_path_list = [path for path in img_dir.glob("*.jpeg") if path.is_file()]
|
||||||
print(img_path_list)
|
print(img_path_list)
|
||||||
# instantiate data object
|
# instantiate data object
|
||||||
vis_com_list = [VisualCommunication.from_file(path) for path in img_path_list]
|
vis_com_list = [
|
||||||
|
VisualCommunication.from_file(path)
|
||||||
|
for path
|
||||||
|
in img_path_list
|
||||||
|
]
|
||||||
# generate random predictions
|
# generate random predictions
|
||||||
[vis_com.generate_random_prediction() for vis_com in vis_com_list]
|
[vis_com.generate_random_prediction() for vis_com in vis_com_list]
|
||||||
for vis_com in vis_com_list:
|
for vis_com in vis_com_list:
|
||||||
print(vis_com)
|
print(vis_com)
|
||||||
|
|||||||
@@ -12,7 +12,11 @@ if __name__ == "__main__":
|
|||||||
img_path_list = [path for path in img_dir.glob("*.jpeg") if path.is_file()]
|
img_path_list = [path for path in img_dir.glob("*.jpeg") if path.is_file()]
|
||||||
print(img_path_list)
|
print(img_path_list)
|
||||||
# instantiate data object
|
# instantiate data object
|
||||||
vis_com_list = [VisualCommunication.from_file(path) for path in img_path_list]
|
vis_com_list = [
|
||||||
|
VisualCommunication.from_file(path)
|
||||||
|
for path
|
||||||
|
in img_path_list
|
||||||
|
]
|
||||||
for vis_com in vis_com_list:
|
for vis_com in vis_com_list:
|
||||||
print(repr(vis_com))
|
print(repr(vis_com))
|
||||||
# prepare env vars
|
# prepare env vars
|
||||||
|
|||||||
@@ -3,11 +3,12 @@ from src.database import ModelOutputs
|
|||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# instantiate data object
|
# instantiate data object
|
||||||
annotation = {
|
vis_com_list = [
|
||||||
|
ModelOutputs.from_random()
|
||||||
}
|
for i
|
||||||
vis_com_list = [ModelOutputs.from_annotation(path) for path in img_path_list]
|
in range(3)
|
||||||
|
]
|
||||||
# generate random predictions
|
# generate random predictions
|
||||||
[vis_com.generate_random_prediction() for vis_com in vis_com_list]
|
[vis_com.generate_random_prediction() for vis_com in vis_com_list]
|
||||||
for vis_com in vis_com_list:
|
for vis_com in vis_com_list:
|
||||||
print(vis_com)
|
print(vis_com)
|
||||||
|
|||||||
@@ -25,7 +25,11 @@ if __name__ == "__main__":
|
|||||||
img_dir = test_dir / "imgs"
|
img_dir = test_dir / "imgs"
|
||||||
img_path_list = [path for path in img_dir.glob("*.jpeg") if path.is_file()]
|
img_path_list = [path for path in img_dir.glob("*.jpeg") if path.is_file()]
|
||||||
# instantiate data object
|
# instantiate data object
|
||||||
vis_com_list = [VisualCommunication.from_file(path) for path in img_path_list]
|
vis_com_list = [
|
||||||
|
VisualCommunication.from_file(path)
|
||||||
|
for path
|
||||||
|
in img_path_list
|
||||||
|
]
|
||||||
# generate random predictions
|
# generate random predictions
|
||||||
[vis_com.generate_random_prediction() for vis_com in vis_com_list]
|
[vis_com.generate_random_prediction() for vis_com in vis_com_list]
|
||||||
# prepare env vars
|
# prepare env vars
|
||||||
|
|||||||
@@ -17,4 +17,4 @@ if __name__ == "__main__":
|
|||||||
collection, db, client = connect()
|
collection, db, client = connect()
|
||||||
# get visual communication
|
# get visual communication
|
||||||
num_docs = total_annotated(collection)
|
num_docs = total_annotated(collection)
|
||||||
print(f"number of annotated documents in database: {num_docs}")
|
print(f"number of annotated documents in database: {num_docs}")
|
||||||
|
|||||||
@@ -17,4 +17,4 @@ if __name__ == "__main__":
|
|||||||
collection, db, client = connect()
|
collection, db, client = connect()
|
||||||
# get visual communication
|
# get visual communication
|
||||||
num_docs = total_documents(collection)
|
num_docs = total_documents(collection)
|
||||||
print(f"total number of documents in database: {num_docs}")
|
print(f"total number of documents in database: {num_docs}")
|
||||||
|
|||||||
Reference in New Issue
Block a user