endoreg-db 0.2.3__py3-none-any.whl → 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. endoreg_db/management/commands/delete_all.py +18 -0
  2. endoreg_db/management/commands/fix_auth_permission.py +20 -0
  3. endoreg_db/management/commands/load_user_groups.py +8 -47
  4. endoreg_db/migrations/0001_initial.py +1 -1
  5. endoreg_db/migrations/0002_rawvideofile.py +26 -0
  6. endoreg_db/migrations/0003_rawvideofile_frames_required.py +18 -0
  7. endoreg_db/migrations/0004_rename_hash_rawvideofile_video_hash.py +18 -0
  8. endoreg_db/migrations/0005_ffmpegmeta_remove_videoimportmeta_center_and_more.py +56 -0
  9. endoreg_db/migrations/0006_rawvideofile_center_alter_videometa_processor.py +25 -0
  10. endoreg_db/migrations/0007_rawvideofile_processor.py +19 -0
  11. endoreg_db/migrations/0008_rename_frames_required_rawvideofile_state_frames_required.py +18 -0
  12. endoreg_db/migrations/0009_sensitivemeta_rawvideofile_sensitive_meta.py +31 -0
  13. endoreg_db/migrations/0010_rename_endoscope_serial_number_sensitivemeta_endoscope_sn.py +18 -0
  14. endoreg_db/migrations/0011_rawvideofile_state_sensitive_data_retrieved.py +18 -0
  15. endoreg_db/migrations/0012_rawvideofile_prediction_dir_and_more.py +109 -0
  16. endoreg_db/models/data_file/__init__.py +4 -1
  17. endoreg_db/models/data_file/base_classes/__init__.py +0 -1
  18. endoreg_db/models/data_file/base_classes/abstract_video.py +1 -0
  19. endoreg_db/models/data_file/import_classes/__init__.py +31 -0
  20. endoreg_db/models/data_file/import_classes/processing_functions.py +269 -0
  21. endoreg_db/models/data_file/import_classes/raw_video.py +341 -0
  22. endoreg_db/models/data_file/metadata/__init__.py +133 -0
  23. endoreg_db/models/data_file/metadata/sensitive_meta.py +13 -0
  24. endoreg_db/models/data_file/video/__init__.py +1 -1
  25. endoreg_db/models/data_file/video/import_meta.py +21 -21
  26. endoreg_db/models/permissions/__init__.py +44 -0
  27. endoreg_db/utils/cropping.py +29 -0
  28. endoreg_db/utils/file_operations.py +30 -0
  29. endoreg_db/utils/legacy_ocr.py +201 -0
  30. endoreg_db/utils/ocr.py +19 -23
  31. endoreg_db/utils/uuid.py +4 -0
  32. endoreg_db/utils/video_metadata.py +2 -2
  33. {endoreg_db-0.2.3.dist-info → endoreg_db-0.3.0.dist-info}/METADATA +7 -1
  34. {endoreg_db-0.2.3.dist-info → endoreg_db-0.3.0.dist-info}/RECORD +36 -13
  35. {endoreg_db-0.2.3.dist-info → endoreg_db-0.3.0.dist-info}/LICENSE +0 -0
  36. {endoreg_db-0.2.3.dist-info → endoreg_db-0.3.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,18 @@
1
+ from django.core.management.base import BaseCommand
2
+ from django.apps import apps
3
+ from django.db import transaction
4
+
5
+ class Command(BaseCommand):
6
+ help = 'Deletes all objects from all models in the "endoreg_db" app.'
7
+
8
+ def handle(self, *args, **options):
9
+ app_models = apps.get_models()
10
+ app_models = [model for model in app_models if "endoreg_db" in model._meta.app_label] # Filter models by the "endoreg_db" app
11
+ for model in app_models:
12
+ with transaction.atomic(): # Use a separate transaction for each model
13
+ try:
14
+ model.objects.all().delete()
15
+ self.stdout.write(self.style.SUCCESS(f'Successfully deleted all objects in {model._meta.db_table}'))
16
+ except Exception as e:
17
+ # This catches exceptions and continues with the next model
18
+ self.stdout.write(self.style.ERROR(f'Error deleting objects in {model._meta.db_table}: {e}'))
@@ -0,0 +1,20 @@
1
+ from django.core.management.base import BaseCommand
2
+ from django.contrib.auth.models import Permission
3
+ from django.contrib.contenttypes.models import ContentType
4
+ from django.apps import apps
5
+
6
+ class Command(BaseCommand):
7
+ help = 'Sets up default permissions for each model in the app.'
8
+
9
+ def handle(self, *args, **options):
10
+ for model in apps.get_models():
11
+ content_type = ContentType.objects.get_for_model(model)
12
+ permissions = ['view', 'add', 'change', 'delete']
13
+ for perm in permissions:
14
+ codename = f'{perm}_{model._meta.model_name}'
15
+ name = f'Can {perm} {model._meta.verbose_name}'
16
+ Permission.objects.get_or_create(
17
+ codename=codename,
18
+ defaults={'name': name, 'content_type': content_type},
19
+ )
20
+ self.stdout.write(self.style.SUCCESS(f'Set up permissions for {model._meta.verbose_name}'))
@@ -1,10 +1,11 @@
1
-
2
1
  from django.core.management.base import BaseCommand
3
2
  from django.contrib.auth.models import Group, Permission
3
+ from django.contrib.contenttypes.models import ContentType
4
+ from django.apps import apps
4
5
 
5
6
 
6
7
  class Command(BaseCommand):
7
- help = """Create additional user groups"""
8
+ help = "Create additional user groups and permissions for all models in 'endoreg_db' app."
8
9
 
9
10
  def add_arguments(self, parser):
10
11
  parser.add_argument(
@@ -16,52 +17,12 @@ class Command(BaseCommand):
16
17
  def handle(self, *args, **options):
17
18
  verbose = options['verbose']
18
19
 
19
- permissions = [
20
- "g_play_production",
21
- "agl",
22
- "endo_reg_production",
23
- "ukw_production"
24
- ]
25
-
26
- for permission_name in permissions:
27
- permission, created = Permission.objects.get_or_create(codename=permission_name)
28
- if verbose:
29
- if created:
30
- self.stdout.write(self.style.SUCCESS("Created Permission {}".format(group_name)))
31
-
20
+ # Create groups
32
21
  groups = ["demo", "verified", "agl", "endo_reg_user", "g_play_user", "ukw_user"]
33
22
  for group_name in groups:
34
23
  _group, created = Group.objects.get_or_create(name=group_name)
35
- if verbose:
36
- if created:
37
- self.stdout.write(self.style.SUCCESS("Created group {}".format(group_name)))
38
-
39
- # Add permissions to groups
40
- # demo has no permissions
41
- # verified has no permissions
42
- # agl has all permissions
43
- # endo_reg_user has endo_reg_user_production permission
44
- # g_play_user has g_play_production permission
45
- agl_group = Group.objects.get(name="agl")
46
- agl_group.permissions.set(Permission.objects.all())
47
- agl_group.save()
48
-
49
- endo_reg_user_group = Group.objects.get(name="endo_reg_user")
50
- _permission = Permission.objects.get(codename="endo_reg_production")
51
- endo_reg_user_group.permissions.add(_permission)
52
- endo_reg_user_group.save()
53
-
54
- g_play_user_group = Group.objects.get(name="g_play_user")
55
- _permission = Permission.objects.get(codename="g_play_production")
56
- g_play_user_group.permissions.add(_permission)
57
- g_play_user_group.save()
58
-
59
- ukw_user_group = Group.objects.get(name="ukw_user")
60
- _permission = Permission.objects.get(codename="ukw_production")
61
- ukw_user_group.permissions.add(_permission)
62
- ukw_user_group.save()
63
-
64
-
24
+ if verbose and created:
25
+ self.stdout.write(self.style.SUCCESS(f"Created group {group_name}"))
65
26
 
66
-
67
-
27
+ if verbose:
28
+ self.stdout.write(self.style.SUCCESS("All groups processed successfully."))
@@ -1,4 +1,4 @@
1
- # Generated by Django 4.2 on 2024-02-13 12:43
1
+ # Generated by Django 4.2.10 on 2024-02-13 22:19
2
2
 
3
3
  from django.conf import settings
4
4
  from django.db import migrations, models
@@ -0,0 +1,26 @@
1
+ # Generated by Django 4.2.11 on 2024-03-09 17:44
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('endoreg_db', '0001_initial'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.CreateModel(
14
+ name='RawVideoFile',
15
+ fields=[
16
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
17
+ ('uuid', models.UUIDField()),
18
+ ('file', models.FileField(upload_to='raw_data/')),
19
+ ('original_file_name', models.CharField(max_length=255)),
20
+ ('hash', models.CharField(max_length=255, unique=True)),
21
+ ('uploaded_at', models.DateTimeField(auto_now_add=True)),
22
+ ('state_frames_extracted', models.BooleanField(default=False)),
23
+ ('frame_dir', models.CharField(max_length=255)),
24
+ ],
25
+ ),
26
+ ]
@@ -0,0 +1,18 @@
1
+ # Generated by Django 4.2.11 on 2024-03-09 20:44
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('endoreg_db', '0002_rawvideofile'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AddField(
14
+ model_name='rawvideofile',
15
+ name='frames_required',
16
+ field=models.BooleanField(default=True),
17
+ ),
18
+ ]
@@ -0,0 +1,18 @@
1
+ # Generated by Django 4.2.11 on 2024-03-10 12:08
2
+
3
+ from django.db import migrations
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('endoreg_db', '0003_rawvideofile_frames_required'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.RenameField(
14
+ model_name='rawvideofile',
15
+ old_name='hash',
16
+ new_name='video_hash',
17
+ ),
18
+ ]
@@ -0,0 +1,56 @@
1
+ # Generated by Django 4.2.11 on 2024-03-10 13:07
2
+
3
+ from django.db import migrations, models
4
+ import django.db.models.deletion
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ('endoreg_db', '0004_rename_hash_rawvideofile_video_hash'),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.CreateModel(
15
+ name='FFMpegMeta',
16
+ fields=[
17
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
18
+ ('duration', models.FloatField(blank=True, null=True)),
19
+ ('width', models.IntegerField(blank=True, null=True)),
20
+ ('height', models.IntegerField(blank=True, null=True)),
21
+ ('frame_rate', models.FloatField(blank=True, null=True)),
22
+ ('video_codec', models.CharField(blank=True, max_length=50, null=True)),
23
+ ('audio_codec', models.CharField(blank=True, max_length=50, null=True)),
24
+ ('audio_channels', models.IntegerField(blank=True, null=True)),
25
+ ('audio_sample_rate', models.IntegerField(blank=True, null=True)),
26
+ ],
27
+ ),
28
+ migrations.RemoveField(
29
+ model_name='videoimportmeta',
30
+ name='center',
31
+ ),
32
+ migrations.RemoveField(
33
+ model_name='videoimportmeta',
34
+ name='endoscope',
35
+ ),
36
+ migrations.RemoveField(
37
+ model_name='videoimportmeta',
38
+ name='processor',
39
+ ),
40
+ migrations.CreateModel(
41
+ name='VideoMeta',
42
+ fields=[
43
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
44
+ ('center', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='endoreg_db.center')),
45
+ ('endoscope', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='endoreg_db.endoscope')),
46
+ ('ffmpeg_meta', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='endoreg_db.ffmpegmeta')),
47
+ ('import_meta', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='endoreg_db.videoimportmeta')),
48
+ ('processor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='endoreg_db.endoscopyprocessor')),
49
+ ],
50
+ ),
51
+ migrations.AddField(
52
+ model_name='rawvideofile',
53
+ name='video_meta',
54
+ field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='endoreg_db.videometa'),
55
+ ),
56
+ ]
@@ -0,0 +1,25 @@
1
+ # Generated by Django 4.2.11 on 2024-03-10 14:46
2
+
3
+ from django.db import migrations, models
4
+ import django.db.models.deletion
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ('endoreg_db', '0005_ffmpegmeta_remove_videoimportmeta_center_and_more'),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AddField(
15
+ model_name='rawvideofile',
16
+ name='center',
17
+ field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='endoreg_db.center'),
18
+ preserve_default=False,
19
+ ),
20
+ migrations.AlterField(
21
+ model_name='videometa',
22
+ name='processor',
23
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='endoreg_db.endoscopyprocessor'),
24
+ ),
25
+ ]
@@ -0,0 +1,19 @@
1
+ # Generated by Django 4.2.11 on 2024-03-10 15:05
2
+
3
+ from django.db import migrations, models
4
+ import django.db.models.deletion
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ('endoreg_db', '0006_rawvideofile_center_alter_videometa_processor'),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AddField(
15
+ model_name='rawvideofile',
16
+ name='processor',
17
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='endoreg_db.endoscopyprocessor'),
18
+ ),
19
+ ]
@@ -0,0 +1,18 @@
1
+ # Generated by Django 4.2.11 on 2024-03-10 15:45
2
+
3
+ from django.db import migrations
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('endoreg_db', '0007_rawvideofile_processor'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.RenameField(
14
+ model_name='rawvideofile',
15
+ old_name='frames_required',
16
+ new_name='state_frames_required',
17
+ ),
18
+ ]
@@ -0,0 +1,31 @@
1
+ # Generated by Django 4.2.11 on 2024-03-10 17:44
2
+
3
+ from django.db import migrations, models
4
+ import django.db.models.deletion
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ('endoreg_db', '0008_rename_frames_required_rawvideofile_state_frames_required'),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.CreateModel(
15
+ name='SensitiveMeta',
16
+ fields=[
17
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
18
+ ('examination_date', models.DateField(blank=True, null=True)),
19
+ ('patient_first_name', models.CharField(blank=True, max_length=255, null=True)),
20
+ ('patient_last_name', models.CharField(blank=True, max_length=255, null=True)),
21
+ ('patient_dob', models.DateField(blank=True, null=True)),
22
+ ('endoscope_type', models.CharField(blank=True, max_length=255, null=True)),
23
+ ('endoscope_serial_number', models.CharField(blank=True, max_length=255, null=True)),
24
+ ],
25
+ ),
26
+ migrations.AddField(
27
+ model_name='rawvideofile',
28
+ name='sensitive_meta',
29
+ field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='endoreg_db.sensitivemeta'),
30
+ ),
31
+ ]
@@ -0,0 +1,18 @@
1
+ # Generated by Django 4.2.11 on 2024-03-10 17:50
2
+
3
+ from django.db import migrations
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('endoreg_db', '0009_sensitivemeta_rawvideofile_sensitive_meta'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.RenameField(
14
+ model_name='sensitivemeta',
15
+ old_name='endoscope_serial_number',
16
+ new_name='endoscope_sn',
17
+ ),
18
+ ]
@@ -0,0 +1,18 @@
1
+ # Generated by Django 4.2.11 on 2024-03-10 18:01
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('endoreg_db', '0010_rename_endoscope_serial_number_sensitivemeta_endoscope_sn'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AddField(
14
+ model_name='rawvideofile',
15
+ name='state_sensitive_data_retrieved',
16
+ field=models.BooleanField(default=False),
17
+ ),
18
+ ]
@@ -0,0 +1,109 @@
1
+ # Generated by Django 4.2.11 on 2024-03-18 23:01
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('endoreg_db', '0011_rawvideofile_state_sensitive_data_retrieved'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AddField(
14
+ model_name='rawvideofile',
15
+ name='prediction_dir',
16
+ field=models.CharField(default='.', max_length=255),
17
+ preserve_default=False,
18
+ ),
19
+ migrations.AddField(
20
+ model_name='rawvideofile',
21
+ name='state_anonym_video_performed',
22
+ field=models.BooleanField(default=False),
23
+ ),
24
+ migrations.AddField(
25
+ model_name='rawvideofile',
26
+ name='state_anonym_video_required',
27
+ field=models.BooleanField(default=True),
28
+ ),
29
+ migrations.AddField(
30
+ model_name='rawvideofile',
31
+ name='state_dataset_complete',
32
+ field=models.BooleanField(default=False),
33
+ ),
34
+ migrations.AddField(
35
+ model_name='rawvideofile',
36
+ name='state_finalized',
37
+ field=models.BooleanField(default=False),
38
+ ),
39
+ migrations.AddField(
40
+ model_name='rawvideofile',
41
+ name='state_follow_up_intervention_available',
42
+ field=models.BooleanField(default=False),
43
+ ),
44
+ migrations.AddField(
45
+ model_name='rawvideofile',
46
+ name='state_follow_up_intervention_required',
47
+ field=models.BooleanField(blank=True, null=True),
48
+ ),
49
+ migrations.AddField(
50
+ model_name='rawvideofile',
51
+ name='state_histology_available',
52
+ field=models.BooleanField(default=False),
53
+ ),
54
+ migrations.AddField(
55
+ model_name='rawvideofile',
56
+ name='state_histology_required',
57
+ field=models.BooleanField(blank=True, null=True),
58
+ ),
59
+ migrations.AddField(
60
+ model_name='rawvideofile',
61
+ name='state_initial_prediction_completed',
62
+ field=models.BooleanField(default=False),
63
+ ),
64
+ migrations.AddField(
65
+ model_name='rawvideofile',
66
+ name='state_initial_prediction_import_completed',
67
+ field=models.BooleanField(default=False),
68
+ ),
69
+ migrations.AddField(
70
+ model_name='rawvideofile',
71
+ name='state_initial_prediction_import_required',
72
+ field=models.BooleanField(default=True),
73
+ ),
74
+ migrations.AddField(
75
+ model_name='rawvideofile',
76
+ name='state_initial_prediction_required',
77
+ field=models.BooleanField(default=True),
78
+ ),
79
+ migrations.AddField(
80
+ model_name='rawvideofile',
81
+ name='state_ocr_completed',
82
+ field=models.BooleanField(default=False),
83
+ ),
84
+ migrations.AddField(
85
+ model_name='rawvideofile',
86
+ name='state_ocr_required',
87
+ field=models.BooleanField(default=True),
88
+ ),
89
+ migrations.AddField(
90
+ model_name='rawvideofile',
91
+ name='state_ocr_result_validated',
92
+ field=models.BooleanField(default=False),
93
+ ),
94
+ migrations.AddField(
95
+ model_name='rawvideofile',
96
+ name='state_original_reports_deleted',
97
+ field=models.BooleanField(default=False),
98
+ ),
99
+ migrations.AddField(
100
+ model_name='rawvideofile',
101
+ name='state_original_video_deleted',
102
+ field=models.BooleanField(default=False),
103
+ ),
104
+ migrations.AddField(
105
+ model_name='rawvideofile',
106
+ name='state_outside_validated',
107
+ field=models.BooleanField(default=False),
108
+ ),
109
+ ]
@@ -1,4 +1,7 @@
1
1
  from .frame import Frame, LegacyFrame
2
2
  from .report_file import ReportFile
3
3
  from .video import Video, LegacyVideo, VideoImportMeta
4
- from .video_segment import LegacyLabelVideoSegment, LabelVideoSegment
4
+ from .video_segment import LegacyLabelVideoSegment, LabelVideoSegment
5
+ from .metadata import FFMpegMeta, SensitiveMeta
6
+
7
+ from .import_classes import RawVideoFile
@@ -1,3 +1,2 @@
1
1
  from .abstract_frame import AbstractFrame
2
2
  from .abstract_video import AbstractVideo
3
-
@@ -3,6 +3,7 @@ from PIL import Image
3
3
  from django.core.files.base import ContentFile
4
4
  from django.db import models, transaction
5
5
  from tqdm import tqdm
6
+ # import cv2
6
7
  import io
7
8
  from datetime import date
8
9
 
@@ -0,0 +1,31 @@
1
+ import os
2
+ from pathlib import Path
3
+
4
+ from .raw_video import RawVideoFile
5
+
6
+ # FileImporter class
7
+ # This class is used to import data from a file into the database.
8
+ # Expects a directory containing files to import.
9
+ # creates correct import file object depending on file type
10
+
11
+ # FileImporter class
12
+ # This class is used to import data from a file into the database by creating objects for the files.
13
+ # main method is import_files which expects a path to a directory containing files to import.
14
+ # creates correct import file object depending on file type by checking the file extension
15
+
16
+ class FileImporter:
17
+ def __init__(self, directory):
18
+ self.directory = directory
19
+
20
+ def import_files(self):
21
+ directory_path = Path(self.directory)
22
+ for file in directory_path.iterdir():
23
+ if file.is_file():
24
+ if file.suffix.lower() in ['.mov', '.mp4']:
25
+ RawVideoFile.create_from_file(file)
26
+ else:
27
+ raise ValueError(f"File type {file.suffix} not supported")
28
+ else:
29
+ raise ValueError(f"{file} is not a file")
30
+
31
+