Compare commits

...
3 Commits
Author SHA1 Message Date
Brian Bjarke Jensen 38fc595725 fixed code import bug
Code Quality Pipeline / Test (push) Failing after 3m41s
CI Pipeline / Test (pull_request) Failing after 3m57s
CI Pipeline / Build and Publish (pull_request) Has been skipped
2024-05-07 20:23:40 +02:00
Brian Bjarke Jensen e04ce33891 removed unused files 2024-05-07 20:23:22 +02:00
Brian Bjarke Jensen bc653a0be4 added new folder and ran tests 2024-05-07 20:19:18 +02:00
29 changed files with 144 additions and 484 deletions
+16 -17
View File
@@ -1,21 +1,20 @@
version: '3.7'
services: services:
# app: app:
# image: visual_critical_discourse_analysis:dev image: visual_critical_discourse_analysis:dev
# container_name: visual_critical_discourse_analysis container_name: visual_critical_discourse_analysis
# build: build:
# context: . context: .
# dockerfile: Dockerfile dockerfile: ./web_ui/Dockerfile
# env_file: env_file:
# - local.env - local.env
# environment: environment:
# - ENV=DEV - ENV=DEV
# ports: ports:
# - 8050:8050 - 8050:8050
# networks: networks:
# - backend - backend
# depends_on: depends_on:
# - mongo - mongo
mongo: mongo:
image: mongo:latest image: mongo:latest
container_name: mongo container_name: mongo
+1 -2
View File
@@ -1,11 +1,10 @@
version: '3.7'
services: services:
app: app:
image: visual_critical_discourse_analysis:dev image: visual_critical_discourse_analysis:dev
container_name: visual_critical_discourse_analysis container_name: visual_critical_discourse_analysis
build: build:
context: . context: .
dockerfile: Dockerfile dockerfile: ./web_ui/Dockerfile
env_file: env_file:
- server.env - server.env
ports: ports:
View File
-1
View File
@@ -1 +0,0 @@
from .classes import VisualSyntaxModelOutput
-89
View File
@@ -1,89 +0,0 @@
from pydantic import BaseModel, ValidationError
from typing import List
import random
class OptionNotSetException(Exception):
pass
class ModelOutput(BaseModel):
@classmethod
def classname(cls) -> str:
"""Return classname."""
return cls.__name__
@classmethod
def list_fields(cls) -> List[str]:
"""List options that are stored as attributes."""
return list(cls.model_fields.keys())
@classmethod
def from_random(cls):
"""Instantiate with random numbers."""
kwargs = {field: random.random() for field in cls.list_fields()}
return cls(**kwargs)
@classmethod
def from_choice(cls, option: str):
"""Instantiate from choice."""
if option is None:
raise ValidationError()
assert isinstance(option, str), "option is not a string"
allowed_options_list = cls.list_fields()
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[option] = 1
return cls(**kwargs)
def __repr__(self) -> str:
model_dict = self.model_dump()
model_repr_str = f"{self.classname()}("
model_repr_str += ", ".join([
f"{field}={value:.3f}"
for field, value
in model_dict.items()
])
model_repr_str += ")"
return model_repr_str
def highest_score_field(self) -> str:
"""Return name of field with highest score."""
model_dict = self.model_dump()
return max(model_dict, key=lambda k: model_dict[k])
def highest_score_value(self) -> float:
"""Return value of field with highest score."""
model_dict = self.model_dump()
return max(model_dict.values())
class VisualSyntaxModelOutput(ModelOutput):
non_transactional_action: float
non_transactional_reaction: float
unidirectional_transactional_action: float
unidirectional_transactional_reaction: float
bidirectional_transactional_action: float
bidirectional_transactional_reaction: float
conversion: float
speech_process: float
classification_overt_taxonomy: float
analytical_exhaustive: float
analytical_disarranged: float
analytical_temporal: float
analytical_distributed: float
analytical_topological: float
analytical_exploded: float
analytical_inclusive: float
symbolic_suggestive: float
symbolic_attributive: float
if __name__ == '__main__':
m = VisualSyntaxModelOutput.from_random()
print(m)
print(repr(m))
print(m.highest_score_field())
print(m.highest_score_value())
-20
View File
@@ -1,20 +0,0 @@
CLASS_NAMES = [
"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"
]
-9
View File
@@ -1,9 +0,0 @@
from .classes import (
ContactModelOutput,
AngleModelOutput,
PointOfViewModelOutput,
DistanceModelOutput,
ModalityLightingModelOutput,
ModalityColorModelOutput,
ModalityDepthModelOutput
)
-137
View File
@@ -1,137 +0,0 @@
from pydantic import BaseModel, ValidationError
from typing import List
import random
class ModelOutput(BaseModel):
@classmethod
def classname(cls) -> str:
"""Return classname."""
return cls.__name__
@classmethod
def list_fields(cls) -> List[str]:
"""List options that are stored as attributes."""
return list(cls.model_fields.keys())
@classmethod
def from_random(cls):
"""Instantiate with random numbers."""
kwargs = {field: random.random() for field in cls.list_fields()}
return cls(**kwargs)
@classmethod
def from_choice(cls, option: str):
"""Instantiate from choice."""
if option is None:
raise ValidationError()
assert isinstance(option, str)
allowed_options_list = cls.list_fields()
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[option] = 1
return cls(**kwargs)
def __repr__(self) -> str:
model_dict = self.model_dump()
model_repr_str = f"{self.classname()}("
model_repr_str += ", ".join([
f"{field}={value:.3f}"
for field, value
in model_dict.items()
])
model_repr_str += ")"
return model_repr_str
def highest_score_field(self) -> str:
"""Return name of field with highest score."""
model_dict = self.model_dump()
return max(model_dict, key=lambda k: model_dict[k])
def highest_score_value(self) -> float:
"""Return value of field with highest score."""
model_dict = self.model_dump()
return max(model_dict.values())
class ContactModelOutput(ModelOutput):
offer: float
demand: float
class AngleModelOutput(ModelOutput):
high: float
eye_level: float
low: float
class PointOfViewModelOutput(ModelOutput):
frontal: float
oblique: float
class DistanceModelOutput(ModelOutput):
long: float
medium: float
close: float
class ModalityLightingModelOutput(ModelOutput):
high: float
medium: float
low: float
class ModalityColorModelOutput(ModelOutput):
high: float
medium: float
low: float
class ModalityDepthModelOutput(ModelOutput):
high: float
medium: float
low: float
# class InterpersonalModelOutput(BaseModel):
# contact: ContactModelOutput
# angle: AngleModelOutput
# point_of_view: PointOfViewModelOutput
# distance: DistanceModelOutput
# modality_lighting: ModalityLightingModelOutput
# modality_color: ModalityColorModelOutput
# modality_depth: ModalityDepthModelOutput
if __name__ == '__main__':
m = ContactModelOutput.from_random()
print(repr(m))
print(m.highest_score_field())
print(m.highest_score_value())
m = AngleModelOutput.from_random()
print(repr(m))
print(m.highest_score_field())
print(m.highest_score_value())
m = PointOfViewModelOutput.from_random()
print(repr(m))
print(m.highest_score_field())
print(m.highest_score_value())
m = DistanceModelOutput.from_random()
print(repr(m))
print(m.highest_score_field())
print(m.highest_score_value())
m = ModalityLightingModelOutput.from_random()
print(repr(m))
print(m.highest_score_field())
print(m.highest_score_value())
m = ModalityColorModelOutput.from_random()
print(repr(m))
print(m.highest_score_field())
print(m.highest_score_value())
m = ModalityDepthModelOutput.from_random()
print(repr(m))
print(m.highest_score_field())
print(m.highest_score_value())
-36
View File
@@ -1,36 +0,0 @@
model_labels = {
"contact": [
"offer",
"demand"
],
"angle": [
"high",
"eye-level",
"low"
],
"point-of-view": [
"frontal",
"oblique"
],
"distance": [
"long",
"medium",
"close"
],
"modality lighting": [
"high",
"medium",
"low"
],
"modality color": [
"high",
"medium",
"low"
],
"modality depth": [
"high",
"medium",
"low"
]
}
-5
View File
@@ -1,5 +0,0 @@
from .classes import (
InformationValueModelOutput,
FramingModelOutput,
SalienceModelOutput
)
-92
View File
@@ -1,92 +0,0 @@
from pydantic import BaseModel, ValidationError
from typing import List
import random
class ModelOutput(BaseModel):
@classmethod
def classname(cls) -> str:
"""Return classname."""
return cls.__name__
@classmethod
def list_fields(cls) -> List[str]:
"""List options that are stored as attributes."""
return list(cls.model_fields.keys())
@classmethod
def from_random(cls):
"""Instantiate with random numbers."""
kwargs = {field: random.random() for field in cls.list_fields()}
return cls(**kwargs)
@classmethod
def from_choice(cls, option: str):
"""Instantiate from choice."""
if option is None:
raise ValidationError()
assert isinstance(option, str)
allowed_options_list = cls.list_fields()
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[option] = 1
return cls(**kwargs)
def __repr__(self) -> str:
model_dict = self.model_dump()
model_repr_str = f"{self.classname()}("
model_repr_str += ", ".join([
f"{field}={value:.3f}"
for field, value
in model_dict.items()
])
model_repr_str += ")"
return model_repr_str
def highest_score_field(self) -> str:
"""Return name of field with highest score."""
model_dict = self.model_dump()
return max(model_dict, key=lambda k: model_dict[k])
def highest_score_value(self) -> float:
"""Return value of field with highest score."""
model_dict = self.model_dump()
return max(model_dict.values())
class InformationValueModelOutput(ModelOutput):
given_new: float
ideal_real: float
central_marginal: float
class FramingModelOutput(ModelOutput):
frame_lines: float
empty_space: float
colour_contrast: float
form_contrast: float
class SalienceModelOutput(ModelOutput):
size: float
colour: float
tone: float
form: float
positioning: float
if __name__ == '__main__':
m = InformationValueModelOutput.from_random()
print(repr(m))
print(m.highest_score_field())
print(m.highest_score_value())
m = FramingModelOutput.from_random()
print(repr(m))
print(m.highest_score_field())
print(m.highest_score_value())
m = SalienceModelOutput.from_random()
print(repr(m))
print(m.highest_score_field())
print(m.highest_score_value())
-21
View File
@@ -1,21 +0,0 @@
model_labels = {
"information value": [
"given-new",
"ideal-real",
"central-marginal"
],
"framing": [
"frame lines",
"empty space",
"colour contrast",
"form contrast"
],
"salience": [
"size",
"colour",
"tone",
"form",
"positioning"
]
}
-4
View File
@@ -1,4 +0,0 @@
from __future__ import annotations
from src.web.app import app
from src.web.app import server
-1
View File
@@ -1 +0,0 @@
from .layout import app_layout
-21
View File
@@ -1,21 +0,0 @@
import dash_mantine_components as dmc
from dash import html
from pathlib import Path
from base64 import b64encode
# read init img
init_img_path = Path(__file__).parent / "init_img.png"
with open(init_img_path.absolute(), "rb") as fh:
init_img_enc = b64encode(fh.read()).decode("utf-8")
# generate init img string
init_img_src = f"data:image/png;base64, {init_img_enc}"
image_element = dmc.Center(
html.Img(
style={
"width": "100%",
},
id="image-container",
src=init_img_src
)
)
+57
View File
@@ -0,0 +1,57 @@
# build stage
FROM python:3.12-slim-bookworm as BUILDER
# set environment variables
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PIP_NO_CACHE_DIR=off \
PIP_DISABLE_PIP_VERSION_CHECK=ON \
PIP_DEFAULT_TIMEOUT=100 \
DEBIAN_FRONTEND=noninteractive \
POETRY_HOME=/etc/poetry \
POETRY_VERSION=1.7.1 \
POETRY_VIRTUALENVS_IN_PROJECT=1 \
POETRY_VIRTUALENVS_CREATE=1 \
POETRY_NO_INTERACTION=1 \
POETRY_CACHE_DIR=/tmp/poetry_cache \
APP_HOME=/home/app
# update system
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
build-essential \
curl \
&& apt-get clean
# install poetry
RUN curl -sSL https://install.python-poetry.org | python3 -
ENV PATH="${POETRY_HOME}/bin:$PATH"
# install runtime dependencies
WORKDIR ${APP_HOME}
COPY poetry.lock pyproject.toml ./
RUN --mount=type=cache,target=${POETRY_CACHE_DIR} poetry install --without model
# final stage
FROM python:3.12-slim-bookworm
# copy virtualenv made by poetry
ENV APP_HOME=/home/app \
VIRTUAL_ENV=/home/app/.venv
COPY --from=builder ${VIRTUAL_ENV} ${VIRTUAL_ENV}
ENV PATH="${VIRTUAL_ENV}/bin:${PATH}"
# create home directory and app user
RUN mkdir -p /home/app && \
addgroup --system app && \
adduser --system --group app
# add code while changing ownership
WORKDIR $APP_HOME
COPY --chown=app:app ./core ./core
COPY --chown=app:app ./web_ui/src ./src
# change to the app user
USER app
ENTRYPOINT [ "gunicorn", "src.main:server", "-b", "0.0.0.0:8050" ]
+3
View File
@@ -0,0 +1,3 @@
from __future__ import annotations
from .app import app
+4
View File
@@ -245,3 +245,7 @@ def cycle_visual_communication_data(
response[3] = annotation_values response[3] = annotation_values
logging.info('finished getting visual communication: %s', vis_com_name) logging.info('finished getting visual communication: %s', vis_com_name)
return tuple(response) return tuple(response)
if __name__ == '__main__':
app.run(debug=True)
+3
View File
@@ -0,0 +1,3 @@
from __future__ import annotations
from .layout import app_layout
@@ -1,3 +1,5 @@
from __future__ import annotations
import dash_mantine_components as dmc import dash_mantine_components as dmc
from .image import image_element from .image import image_element
@@ -11,8 +13,8 @@ body_element = dmc.Container(
grow=True, grow=True,
children=[ children=[
dmc.Col([image_element], span=5), dmc.Col([image_element], span=5),
dmc.Col([inputs_element], span=7) dmc.Col([inputs_element], span=7),
], ],
) ),
], ],
) )
+24
View File
@@ -0,0 +1,24 @@
from __future__ import annotations
from base64 import b64encode
from pathlib import Path
import dash_mantine_components as dmc
from dash import html
# read init img
init_img_path = Path(__file__).parent / 'init_img.png'
with open(init_img_path.absolute(), 'rb') as fh:
init_img_enc = b64encode(fh.read()).decode('utf-8')
# generate init img string
init_img_src = f"data:image/png;base64, {init_img_enc}"
image_element = dmc.Center(
html.Img(
style={
'width': '100%',
},
id='image-container',
src=init_img_src,
),
)

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

@@ -1,23 +1,25 @@
from __future__ import annotations
import dash_mantine_components as dmc import dash_mantine_components as dmc
from .labels import labels_element from .labels import labels_element
next_button = dmc.Button( next_button = dmc.Button(
"next".title(), 'next'.title(),
id="next-button", id='next-button',
n_clicks=0, n_clicks=0,
fullWidth=True, fullWidth=True,
color="lime", color='lime',
radius="sm", radius='sm',
size="md", size='md',
style={ style={
"height": "50px" 'height': '50px',
} },
) )
inputs_element = dmc.SimpleGrid( inputs_element = dmc.SimpleGrid(
children=[ children=[
labels_element, labels_element,
next_button next_button,
] ],
) )
@@ -1,22 +1,24 @@
from __future__ import annotations
import dash_mantine_components as dmc import dash_mantine_components as dmc
from .stores import stores_element
from .alerts import alerts_element from .alerts import alerts_element
from .header import header_element
from .body import body_element from .body import body_element
from .header import header_element
from .stores import stores_element
app_layout = dmc.MantineProvider( app_layout = dmc.MantineProvider(
theme={ theme={
"fontFamily": '"Inter", sans-serif', 'fontFamily': '"Inter", sans-serif',
"components": { 'components': {
"NavLink": { 'NavLink': {
"styles": { 'styles': {
"label": { 'label': {
"color": "#c2c7d0" 'color': '#c2c7d0',
} },
} },
} },
}, },
}, },
children=[ children=[
@@ -27,8 +29,8 @@ app_layout = dmc.MantineProvider(
header_element, header_element,
body_element, body_element,
], ],
fluid=True fluid=True,
), ),
] ],
) )
+6 -5
View File
@@ -6,10 +6,10 @@ from pathlib import Path
from dotenv import load_dotenv from dotenv import load_dotenv
from src.web import app from .app import app
# prepare optional local setup # prepare optional local setup
env_path = Path(__file__).parent.parent / 'local.env' env_path = Path(__file__).parent.parent.parent / 'local.env'
load_dotenv(env_path) load_dotenv(env_path)
# ensure env vars set # ensure env vars set
@@ -31,18 +31,19 @@ for env_var in necesasary_var_list:
) )
# setup logging stream handler # setup logging stream handler
fmt = ( FMT = (
'%(asctime)s | ' '%(asctime)s | '
'%(levelname)s | ' '%(levelname)s | '
'%(filename)s | ' '%(filename)s | '
'%(funcName)s | ' '%(funcName)s | '
'%(message)s' '%(message)s'
) )
datefmt = '%Y-%m-%d %H:%M:%S' 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')
server = app.server server = app.server
server.config.update(SECRET_KEY=os.urandom(24))
if __name__ == '__main__': if __name__ == '__main__':
# prepare local env vars # prepare local env vars