Compare commits

...
10 Commits
21 changed files with 710 additions and 68 deletions
+1 -1
View File
@@ -121,7 +121,7 @@ celerybeat.pid
*.sage.py *.sage.py
# Environments # Environments
.env *.env
.venv .venv
env/ env/
venv/ venv/
+33 -1
View File
@@ -1,3 +1,4 @@
version: '3.7'
services: services:
app: app:
image: visual_critical_discourse_analysis:dev image: visual_critical_discourse_analysis:dev
@@ -5,11 +6,42 @@ services:
build: build:
context: . context: .
dockerfile: Dockerfile dockerfile: Dockerfile
env_file:
- mongodb.env
environment:
- MONGO_HOST=mongo
ports: ports:
- 8050:8050 - 8050:8050
networks: networks:
- backend - backend
depends_on:
- mongo
mongo:
image: mongo:latest
container_name: mongo
env_file:
- mongodb.env
ports:
- "27017:27017"
networks:
- backend
mongo-express:
image: mongo-express
ports:
- 8081:8081
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: root
ME_CONFIG_MONGODB_ADMINPASSWORD: vSH7I7RxsDvb
ME_CONFIG_MONGODB_PORT: 27017
ME_CONFIG_BASICAUTH_USERNAME: admin
ME_CONFIG_BASICAUTH_PASSWORD: q
links:
- mongo
networks:
- backend
depends_on:
- mongo
networks: networks:
backend: backend:
external: false driver: bridge
Generated
+124 -1
View File
@@ -268,6 +268,26 @@ requests = ">=2.28.1,<3.0.0"
[package.extras] [package.extras]
async = ["httpx (>=0.23.0,<0.24.0)"] async = ["httpx (>=0.23.0,<0.24.0)"]
[[package]]
name = "dnspython"
version = "2.6.1"
description = "DNS toolkit"
optional = false
python-versions = ">=3.8"
files = [
{file = "dnspython-2.6.1-py3-none-any.whl", hash = "sha256:5ef3b9680161f6fa89daf8ad451b5f1a33b18ae8a1c6778cdf4b43f08c0a6e50"},
{file = "dnspython-2.6.1.tar.gz", hash = "sha256:e8f0f9c23a7b7cb99ded64e6c3a6f3e701d78f50c55e002b839dea7225cff7cc"},
]
[package.extras]
dev = ["black (>=23.1.0)", "coverage (>=7.0)", "flake8 (>=7)", "mypy (>=1.8)", "pylint (>=3)", "pytest (>=7.4)", "pytest-cov (>=4.1.0)", "sphinx (>=7.2.0)", "twine (>=4.0.0)", "wheel (>=0.42.0)"]
dnssec = ["cryptography (>=41)"]
doh = ["h2 (>=4.1.0)", "httpcore (>=1.0.0)", "httpx (>=0.26.0)"]
doq = ["aioquic (>=0.9.25)"]
idna = ["idna (>=3.6)"]
trio = ["trio (>=0.23)"]
wmi = ["wmi (>=1.5.1)"]
[[package]] [[package]]
name = "flask" name = "flask"
version = "3.0.2" version = "3.0.2"
@@ -669,6 +689,109 @@ 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 = "pymongo"
version = "4.6.1"
description = "Python driver for MongoDB <http://www.mongodb.org>"
optional = false
python-versions = ">=3.7"
files = [
{file = "pymongo-4.6.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4344c30025210b9fa80ec257b0e0aab5aa1d5cca91daa70d82ab97b482cc038e"},
{file = "pymongo-4.6.1-cp310-cp310-manylinux1_i686.whl", hash = "sha256:1c5654bb8bb2bdb10e7a0bc3c193dd8b49a960b9eebc4381ff5a2043f4c3c441"},
{file = "pymongo-4.6.1-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:eaf2f65190c506def2581219572b9c70b8250615dc918b3b7c218361a51ec42e"},
{file = "pymongo-4.6.1-cp310-cp310-manylinux2014_i686.whl", hash = "sha256:262356ea5fcb13d35fb2ab6009d3927bafb9504ef02339338634fffd8a9f1ae4"},
{file = "pymongo-4.6.1-cp310-cp310-manylinux2014_ppc64le.whl", hash = "sha256:2dd2f6960ee3c9360bed7fb3c678be0ca2d00f877068556785ec2eb6b73d2414"},
{file = "pymongo-4.6.1-cp310-cp310-manylinux2014_s390x.whl", hash = "sha256:ff925f1cca42e933376d09ddc254598f8c5fcd36efc5cac0118bb36c36217c41"},
{file = "pymongo-4.6.1-cp310-cp310-manylinux2014_x86_64.whl", hash = "sha256:3cadf7f4c8e94d8a77874b54a63c80af01f4d48c4b669c8b6867f86a07ba994f"},
{file = "pymongo-4.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55dac73316e7e8c2616ba2e6f62b750918e9e0ae0b2053699d66ca27a7790105"},
{file = "pymongo-4.6.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:154b361dcb358ad377d5d40df41ee35f1cc14c8691b50511547c12404f89b5cb"},
{file = "pymongo-4.6.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2940aa20e9cc328e8ddeacea8b9a6f5ddafe0b087fedad928912e787c65b4909"},
{file = "pymongo-4.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:010bc9aa90fd06e5cc52c8fac2c2fd4ef1b5f990d9638548dde178005770a5e8"},
{file = "pymongo-4.6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e470fa4bace5f50076c32f4b3cc182b31303b4fefb9b87f990144515d572820b"},
{file = "pymongo-4.6.1-cp310-cp310-win32.whl", hash = "sha256:da08ea09eefa6b960c2dd9a68ec47949235485c623621eb1d6c02b46765322ac"},
{file = "pymongo-4.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:13d613c866f9f07d51180f9a7da54ef491d130f169e999c27e7633abe8619ec9"},
{file = "pymongo-4.6.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6a0ae7a48a6ef82ceb98a366948874834b86c84e288dbd55600c1abfc3ac1d88"},
{file = "pymongo-4.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bd94c503271e79917b27c6e77f7c5474da6930b3fb9e70a12e68c2dff386b9a"},
{file = "pymongo-4.6.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2d4ccac3053b84a09251da8f5350bb684cbbf8c8c01eda6b5418417d0a8ab198"},
{file = "pymongo-4.6.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:349093675a2d3759e4fb42b596afffa2b2518c890492563d7905fac503b20daa"},
{file = "pymongo-4.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88beb444fb438385e53dc9110852910ec2a22f0eab7dd489e827038fdc19ed8d"},
{file = "pymongo-4.6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8e62d06e90f60ea2a3d463ae51401475568b995bafaffd81767d208d84d7bb1"},
{file = "pymongo-4.6.1-cp311-cp311-win32.whl", hash = "sha256:5556e306713e2522e460287615d26c0af0fe5ed9d4f431dad35c6624c5d277e9"},
{file = "pymongo-4.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:b10d8cda9fc2fcdcfa4a000aa10413a2bf8b575852cd07cb8a595ed09689ca98"},
{file = "pymongo-4.6.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b435b13bb8e36be11b75f7384a34eefe487fe87a6267172964628e2b14ecf0a7"},
{file = "pymongo-4.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e438417ce1dc5b758742e12661d800482200b042d03512a8f31f6aaa9137ad40"},
{file = "pymongo-4.6.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8b47ebd89e69fbf33d1c2df79759d7162fc80c7652dacfec136dae1c9b3afac7"},
{file = "pymongo-4.6.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bbed8cccebe1169d45cedf00461b2842652d476d2897fd1c42cf41b635d88746"},
{file = "pymongo-4.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c30a9e06041fbd7a7590693ec5e407aa8737ad91912a1e70176aff92e5c99d20"},
{file = "pymongo-4.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b8729dbf25eb32ad0dc0b9bd5e6a0d0b7e5c2dc8ec06ad171088e1896b522a74"},
{file = "pymongo-4.6.1-cp312-cp312-win32.whl", hash = "sha256:3177f783ae7e08aaf7b2802e0df4e4b13903520e8380915e6337cdc7a6ff01d8"},
{file = "pymongo-4.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:00c199e1c593e2c8b033136d7a08f0c376452bac8a896c923fcd6f419e07bdd2"},
{file = "pymongo-4.6.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6dcc95f4bb9ed793714b43f4f23a7b0c57e4ef47414162297d6f650213512c19"},
{file = "pymongo-4.6.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:13552ca505366df74e3e2f0a4f27c363928f3dff0eef9f281eb81af7f29bc3c5"},
{file = "pymongo-4.6.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:77e0df59b1a4994ad30c6d746992ae887f9756a43fc25dec2db515d94cf0222d"},
{file = "pymongo-4.6.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:3a7f02a58a0c2912734105e05dedbee4f7507e6f1bd132ebad520be0b11d46fd"},
{file = "pymongo-4.6.1-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:026a24a36394dc8930cbcb1d19d5eb35205ef3c838a7e619e04bd170713972e7"},
{file = "pymongo-4.6.1-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:3b287e814a01deddb59b88549c1e0c87cefacd798d4afc0c8bd6042d1c3d48aa"},
{file = "pymongo-4.6.1-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:9a710c184ba845afb05a6f876edac8f27783ba70e52d5eaf939f121fc13b2f59"},
{file = "pymongo-4.6.1-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:30b2c9caf3e55c2e323565d1f3b7e7881ab87db16997dc0cbca7c52885ed2347"},
{file = "pymongo-4.6.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff62ba8ff70f01ab4fe0ae36b2cb0b5d1f42e73dfc81ddf0758cd9f77331ad25"},
{file = "pymongo-4.6.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:547dc5d7f834b1deefda51aedb11a7af9c51c45e689e44e14aa85d44147c7657"},
{file = "pymongo-4.6.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1de3c6faf948f3edd4e738abdb4b76572b4f4fdfc1fed4dad02427e70c5a6219"},
{file = "pymongo-4.6.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2831e05ce0a4df10c4ac5399ef50b9a621f90894c2a4d2945dc5658765514ed"},
{file = "pymongo-4.6.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:144a31391a39a390efce0c5ebcaf4bf112114af4384c90163f402cec5ede476b"},
{file = "pymongo-4.6.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:33bb16a07d3cc4e0aea37b242097cd5f7a156312012455c2fa8ca396953b11c4"},
{file = "pymongo-4.6.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b7b1a83ce514700276a46af3d9e481ec381f05b64939effc9065afe18456a6b9"},
{file = "pymongo-4.6.1-cp37-cp37m-win32.whl", hash = "sha256:3071ec998cc3d7b4944377e5f1217c2c44b811fae16f9a495c7a1ce9b42fb038"},
{file = "pymongo-4.6.1-cp37-cp37m-win_amd64.whl", hash = "sha256:2346450a075625c4d6166b40a013b605a38b6b6168ce2232b192a37fb200d588"},
{file = "pymongo-4.6.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:061598cbc6abe2f382ab64c9caa83faa2f4c51256f732cdd890bcc6e63bfb67e"},
{file = "pymongo-4.6.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:d483793a384c550c2d12cb794ede294d303b42beff75f3b3081f57196660edaf"},
{file = "pymongo-4.6.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:f9756f1d25454ba6a3c2f1ef8b7ddec23e5cdeae3dc3c3377243ae37a383db00"},
{file = "pymongo-4.6.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:1ed23b0e2dac6f84f44c8494fbceefe6eb5c35db5c1099f56ab78fc0d94ab3af"},
{file = "pymongo-4.6.1-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:3d18a9b9b858ee140c15c5bfcb3e66e47e2a70a03272c2e72adda2482f76a6ad"},
{file = "pymongo-4.6.1-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:c258dbacfff1224f13576147df16ce3c02024a0d792fd0323ac01bed5d3c545d"},
{file = "pymongo-4.6.1-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:f7acc03a4f1154ba2643edeb13658d08598fe6e490c3dd96a241b94f09801626"},
{file = "pymongo-4.6.1-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:76013fef1c9cd1cd00d55efde516c154aa169f2bf059b197c263a255ba8a9ddf"},
{file = "pymongo-4.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f0e6a6c807fa887a0c51cc24fe7ea51bb9e496fe88f00d7930063372c3664c3"},
{file = "pymongo-4.6.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd1fa413f8b9ba30140de198e4f408ffbba6396864c7554e0867aa7363eb58b2"},
{file = "pymongo-4.6.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d219b4508f71d762368caec1fc180960569766049bbc4d38174f05e8ef2fe5b"},
{file = "pymongo-4.6.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27b81ecf18031998ad7db53b960d1347f8f29e8b7cb5ea7b4394726468e4295e"},
{file = "pymongo-4.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:56816e43c92c2fa8c11dc2a686f0ca248bea7902f4a067fa6cbc77853b0f041e"},
{file = "pymongo-4.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ef801027629c5b511cf2ba13b9be29bfee36ae834b2d95d9877818479cdc99ea"},
{file = "pymongo-4.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d4c2be9760b112b1caf649b4977b81b69893d75aa86caf4f0f398447be871f3c"},
{file = "pymongo-4.6.1-cp38-cp38-win32.whl", hash = "sha256:39d77d8bbb392fa443831e6d4ae534237b1f4eee6aa186f0cdb4e334ba89536e"},
{file = "pymongo-4.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:4497d49d785482cc1a44a0ddf8830b036a468c088e72a05217f5b60a9e025012"},
{file = "pymongo-4.6.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:69247f7a2835fc0984bbf0892e6022e9a36aec70e187fcfe6cae6a373eb8c4de"},
{file = "pymongo-4.6.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:7bb0e9049e81def6829d09558ad12d16d0454c26cabe6efc3658e544460688d9"},
{file = "pymongo-4.6.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:6a1810c2cbde714decf40f811d1edc0dae45506eb37298fd9d4247b8801509fe"},
{file = "pymongo-4.6.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:e2aced6fb2f5261b47d267cb40060b73b6527e64afe54f6497844c9affed5fd0"},
{file = "pymongo-4.6.1-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:d0355cff58a4ed6d5e5f6b9c3693f52de0784aa0c17119394e2a8e376ce489d4"},
{file = "pymongo-4.6.1-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:3c74f4725485f0a7a3862cfd374cc1b740cebe4c133e0c1425984bcdcce0f4bb"},
{file = "pymongo-4.6.1-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:9c79d597fb3a7c93d7c26924db7497eba06d58f88f58e586aa69b2ad89fee0f8"},
{file = "pymongo-4.6.1-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:8ec75f35f62571a43e31e7bd11749d974c1b5cd5ea4a8388725d579263c0fdf6"},
{file = "pymongo-4.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5e641f931c5cd95b376fd3c59db52770e17bec2bf86ef16cc83b3906c054845"},
{file = "pymongo-4.6.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9aafd036f6f2e5ad109aec92f8dbfcbe76cff16bad683eb6dd18013739c0b3ae"},
{file = "pymongo-4.6.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f2b856518bfcfa316c8dae3d7b412aecacf2e8ba30b149f5eb3b63128d703b9"},
{file = "pymongo-4.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ec31adc2e988fd7db3ab509954791bbc5a452a03c85e45b804b4bfc31fa221d"},
{file = "pymongo-4.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9167e735379ec43d8eafa3fd675bfbb12e2c0464f98960586e9447d2cf2c7a83"},
{file = "pymongo-4.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1461199b07903fc1424709efafe379205bf5f738144b1a50a08b0396357b5abf"},
{file = "pymongo-4.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:3094c7d2f820eecabadae76bfec02669567bbdd1730eabce10a5764778564f7b"},
{file = "pymongo-4.6.1-cp39-cp39-win32.whl", hash = "sha256:c91ea3915425bd4111cb1b74511cdc56d1d16a683a48bf2a5a96b6a6c0f297f7"},
{file = "pymongo-4.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:ef102a67ede70e1721fe27f75073b5314911dbb9bc27cde0a1c402a11531e7bd"},
{file = "pymongo-4.6.1.tar.gz", hash = "sha256:31dab1f3e1d0cdd57e8df01b645f52d43cc1b653ed3afd535d2891f4fc4f9712"},
]
[package.dependencies]
dnspython = ">=1.16.0,<3.0.0"
[package.extras]
aws = ["pymongo-auth-aws (<2.0.0)"]
encryption = ["certifi", "pymongo[aws]", "pymongocrypt (>=1.6.0,<2.0.0)"]
gssapi = ["pykerberos", "winkerberos (>=0.5.0)"]
ocsp = ["certifi", "cryptography (>=2.5)", "pyopenssl (>=17.2.0)", "requests (<3.0.0)", "service-identity (>=18.1.0)"]
snappy = ["python-snappy"]
test = ["pytest (>=7)"]
zstd = ["zstandard"]
[[package]] [[package]]
name = "python-dotenv" name = "python-dotenv"
version = "1.0.1" version = "1.0.1"
@@ -839,4 +962,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 = "e4892a5e8db437b5c79b40f259ba6b512d1c0b18677b4f13163fee518276a28d" content-hash = "e4aacea5a98281d935411e0d96152d1d24680f6c1e5288e9a1be913a0536b78e"
+1
View File
@@ -18,6 +18,7 @@ dash-bootstrap-components = "^1.5.0"
dash-mantine-components = "^0.12.1" dash-mantine-components = "^0.12.1"
pydantic = "^2.6.1" pydantic = "^2.6.1"
pillow = "^10.2.0" pillow = "^10.2.0"
pymongo = "^4.6.1"
[build-system] [build-system]
+5
View File
@@ -0,0 +1,5 @@
from .classes import (
ModelOutputs,
VisualCommunication
)
from .database import connect
+69
View File
@@ -0,0 +1,69 @@
from __future__ import annotations
from pydantic import BaseModel, field_validator
from PIL import Image
from io import BytesIO
from pathlib import Path
from src.model_experiential import ExperientialModelOutput
from src.model_interpersonal import (
ContactModelOutput,
AngleModelOutput,
PointOfViewModelOutput,
DistanceModelOutput,
ModalityLightingModelOutput,
ModalityColorModelOutput,
ModalityDepthModelOutput
)
from src.model_textual import (
InformationValueModelOutput,
FramingModelOutput,
SalienceModelOutput
)
class ModelOutputs(BaseModel):
experiential: ExperientialModelOutput
contact: ContactModelOutput
angle: AngleModelOutput
point_of_view: PointOfViewModelOutput
distance: DistanceModelOutput
modality_lighting: ModalityLightingModelOutput
modality_color: ModalityColorModelOutput
modality_depth: ModalityDepthModelOutput
information_value: InformationValueModelOutput
framing: FramingModelOutput
salience: SalienceModelOutput
class VisualCommunication(BaseModel):
name: str
image: bytes
annotation: ModelOutputs | None = None
prediction: ModelOutputs | None = None
@classmethod
def classname(cls) -> str:
"""Return classname."""
return cls.__name__
@classmethod
def from_file(cls, path: Path) -> VisualCommunication:
"""Instantiate from file."""
name = path.stem
image = Image.open(path)
return VisualCommunication(name=name, image=image)
@field_validator("image", mode="before")
@classmethod
def convert_to_bytes(cls, raw: Image.Image | BytesIO | bytes) -> bytes:
if isinstance(raw, Image.Image):
raw = raw.tobytes()
if isinstance(raw, BytesIO):
raw = raw.read()
return raw
def __repr__(self) -> str:
return f"{self.classname()}(name='{self.name}')"
@property
def image(self) -> Image.Image:
return Image.open(BytesIO(self.image))
+22
View File
@@ -0,0 +1,22 @@
from pymongo import MongoClient
from dotenv import load_dotenv
import os
def connect():
"""Connect to MongoDB."""
# load env vars
load_dotenv()
necessary_env_vars = [
"MONGO_HOST",
"MONGO_DB",
"MONGO_COLLECTION"
]
for env_var in necessary_env_vars:
assert env_var in os.environ, f"{env_var} not found"
# connect to database
client = MongoClient(os.getenv("MONGO_HOST"))
db = client[os.getenv("MONGO_DB")]
collection = db[os.getenv("MONGO_COLLECTION")]
return collection, db, client
+24 -1
View File
@@ -1 +1,24 @@
from .output import model_labels from .classes import ExperientialModelOutput
# 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"
# ]
+68
View File
@@ -0,0 +1,68 @@
from pydantic import BaseModel
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)
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 ExperientialModelOutput(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 = ExperientialModelOutput.from_random()
print(m)
print(repr(m))
print(m.highest_score_field())
print(m.highest_score_value())
+1 -2
View File
@@ -1,5 +1,4 @@
CLASS_NAMES = [
model_labels = [
"non transactional action", "non transactional action",
"non transactional reaction", "non transactional reaction",
"unidirectional transactional action", "unidirectional transactional action",
+9 -1
View File
@@ -1 +1,9 @@
from .output import model_labels from .classes import (
ContactModelOutput,
AngleModelOutput,
PointOfViewModelOutput,
DistanceModelOutput,
ModalityLightingModelOutput,
ModalityColorModelOutput,
ModalityDepthModelOutput
)
+120
View File
@@ -0,0 +1,120 @@
from pydantic import BaseModel
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)
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())
+2 -2
View File
@@ -1,8 +1,8 @@
model_labels = { model_labels = {
"contact": [ "contact": [
"contact offer", "offer",
"contact demand" "demand"
], ],
"angle": [ "angle": [
"high", "high",
+5 -1
View File
@@ -1 +1,5 @@
from .output import model_labels from .classes import (
InformationValueModelOutput,
FramingModelOutput,
SalienceModelOutput
)
+75
View File
@@ -0,0 +1,75 @@
from pydantic import BaseModel
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)
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())
+4 -9
View File
@@ -4,9 +4,6 @@ import dash_mantine_components as dmc
from .header import generate_header from .header import generate_header
from .body import generate_body from .body import generate_body
from model_experiential import model_labels as experiential_labels
from model_interpersonal import model_labels as interpersonal_labels
from model_textual import model_labels as textual_labels
app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP]) app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
@@ -20,14 +17,12 @@ app.layout = dmc.MantineProvider(
}, },
}, },
children=[ children=[
dmc.Container([ dmc.Container(
[
generate_header(), generate_header(),
generate_body( generate_body(),
experiential_labels, ], fluid=True
interpersonal_labels,
textual_labels
), ),
]),
], ],
) )
+117 -45
View File
@@ -1,71 +1,143 @@
import dash_mantine_components as dmc import dash_mantine_components as dmc
from dash import dcc, html from dash import dcc, html
from typing import List
def generate_body( from src.model_experiential import ExperientialModelOutput
experiential_labels, from src.model_interpersonal import (
interpersonal_labels, ContactModelOutput,
textual_labels AngleModelOutput,
): PointOfViewModelOutput,
DistanceModelOutput,
ModalityLightingModelOutput,
ModalityColorModelOutput,
ModalityDepthModelOutput
)
from src.model_textual import (
InformationValueModelOutput,
FramingModelOutput,
SalienceModelOutput
)
def generate_option_labels(model) -> List[str]:
"""Generate presentable list of attributes from an OutputModel."""
labels = [
label.replace('_', ' ').title()
for label in model.list_fields()
]
return labels
def generate_experiential_options_map():
"""Generate map of titles and options for experiential labels."""
options_map = {}
# add experiential labels
options_map["experiential".title()] = generate_option_labels(ExperientialModelOutput)
return options_map
def generate_interpersonal_options_map():
"""Generate map of titles and options for interpersonal labels."""
options_map = {}
# add interpersonal labels
options_map["contact".title()] = generate_option_labels(ContactModelOutput)
options_map["angle".title()] = generate_option_labels(AngleModelOutput)
options_map["point of view".title()] = generate_option_labels(PointOfViewModelOutput)
options_map["distance".title()] = generate_option_labels(DistanceModelOutput)
options_map["modality lighting".title()] = generate_option_labels(ModalityLightingModelOutput)
options_map["modality color".title()] = generate_option_labels(ModalityColorModelOutput)
options_map["modality depth".title()] = generate_option_labels(ModalityDepthModelOutput)
return options_map
def generate_textual_options_map():
"""Generate map of titles and options for textual labels."""
options_map = {}
# add textual labels
options_map["information value".title()] = generate_option_labels(InformationValueModelOutput)
options_map["framing".title()] = generate_option_labels(FramingModelOutput)
options_map["salience".title()] = generate_option_labels(SalienceModelOutput)
return options_map
def generate_body():
image_container = dmc.Image( image_container = dmc.Image(
width=400, width=600,
height=400, height=600,
withPlaceholder=True, withPlaceholder=True,
placeholder=[dmc.Loader(color="gray", size="md")], placeholder=[dmc.Loader(color="gray", size="md")],
) )
# prepare experiential container
experiential_labels_container = dmc.Container( experiential_map = generate_experiential_options_map()
experiential_container = dmc.Col(
children=[ children=[
html.H4("experiential labels".title()), dmc.Container([
dcc.RadioItems(options=list(experiential_labels)), html.H4(list(experiential_map.keys())[0]),
] html.B("visual syntax".title()),
dcc.RadioItems(options=list(experiential_map.values())[0]),
])
], span=4
) )
# prepare interpersonal container
interpersonal_labels_container = dmc.Container( interpersonal_map = generate_interpersonal_options_map()
children=[] interpersonal_container = dmc.Col(
)
for category, options in interpersonal_labels.items():
interpersonal_labels_container.children.append(html.H4(category.title()))
interpersonal_labels_container.children.append(dcc.RadioItems(options))
textual_labels_container = dmc.Container(
children=[]
)
for category, options in textual_labels.items():
textual_labels_container.children.append(html.H4(category.title()))
textual_labels_container.children.append(dcc.RadioItems(options))
label_container = dmc.Container(
children=[ children=[
experiential_labels_container, html.H4("interpersonal".title()),
dmc.Divider(), ], span=4
interpersonal_labels_container,
dmc.Divider(),
textual_labels_container,
dmc.Divider(),
html.Button(
"confirm",
id="submit-button"
) )
] for title, options in interpersonal_map.items():
interpersonal_container.children.append(
dmc.Container([
html.B(title),
dcc.RadioItems(options)
])
) )
# prepare textual container
textual_map = generate_textual_options_map()
textual_container = dmc.Col(
children=[
html.H4("textual".title()),
], span=4
)
for title, options in textual_map.items():
textual_container.children.append(
dmc.Container([
html.B(title),
dcc.RadioItems(options)
])
)
# prepare labels container
label_container = dmc.Grid(
children=[
experiential_container,
interpersonal_container,
textual_container,
],
)
# build the full body container
body_container = dmc.Container( body_container = dmc.Container(
dmc.Grid( dmc.Grid(
children=[ children=[
dmc.Col( dmc.Col(
dmc.Center(
image_container, image_container,
span=5,
), ),
dmc.Col( span=5,
dmc.Divider(orientation="vertical"),
span=1,
), ),
dmc.Col( dmc.Col(
# radio buttons part # radio buttons part
children = [
label_container, label_container,
span=5, dmc.Button(
"confirm",
id="submit-button",
fullWidth=True,
color="lime",
radius="sm",
size="md",
style={
"height": "50px"
}
), ),
], span=7,
),
# dmc.Col(span=1),
], grow=True ], grow=True
) ), fluid=True
) )
return body_container return body_container
Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

+26
View File
@@ -0,0 +1,26 @@
from pathlib import Path
from dotenv import load_dotenv
from pymongo import MongoClient
import os
from src.database import VisualCommunication, connect
if __name__ == "__main__":
# get list of image paths
test_dir = Path(__file__).parent
img_dir = test_dir / "imgs"
img_path_list = [path for path in img_dir.glob("*.jpeg") if path.is_file()]
print(img_path_list)
# instantiate data object
vis_com_list = [VisualCommunication.from_file(path) for path in img_path_list]
for vis_com in vis_com_list:
print(repr(vis_com))
# upload images to database
env_path = test_dir.parent / "mongodb.env"
assert env_path.exists()
load_dotenv(env_path)
collection, db, client = connect()
print(client.server_info())
for vis_com in vis_com_list:
result = collection.insert_one(vis_com.model_dump_json())
print(f"inserted document: {result}")