endoreg-db 0.6.2__py3-none-any.whl → 0.6.4__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.
Potentially problematic release.
This version of endoreg-db might be problematic. Click here for more details.
- endoreg_db/data/__init__.py +14 -0
- endoreg_db/data/disease_classification/chronic_kidney_disease.yaml +2 -2
- endoreg_db/data/disease_classification_choice/chronic_kidney_disease.yaml +6 -6
- endoreg_db/data/distribution/numeric/data.yaml +1 -1
- endoreg_db/data/examination/examinations/data.yaml +22 -21
- endoreg_db/data/examination/type/data.yaml +12 -0
- endoreg_db/data/examination_indication/endoscopy.yaml +417 -1
- endoreg_db/data/examination_indication_classification/endoscopy.yaml +157 -5
- endoreg_db/data/finding/data.yaml +18 -11
- endoreg_db/data/finding_intervention/endoscopy.yaml +26 -121
- endoreg_db/data/finding_intervention/endoscopy_colonoscopy.yaml +163 -0
- endoreg_db/data/finding_intervention/endoscopy_egd.yaml +128 -0
- endoreg_db/data/finding_intervention/endoscopy_ercp.yaml +32 -0
- endoreg_db/data/finding_intervention/endoscopy_eus_lower.yaml +9 -0
- endoreg_db/data/finding_intervention/endoscopy_eus_upper.yaml +36 -0
- endoreg_db/data/information_source/endoscopy_guidelines.yaml +7 -0
- endoreg_db/data/medication_indication/anticoagulation.yaml +4 -4
- endoreg_db/data/pdf_type/data.yaml +9 -16
- endoreg_db/data/requirement/colonoscopy_indications.yaml +56 -0
- endoreg_db/data/requirement/disease_cardiovascular.yaml +79 -0
- endoreg_db/data/requirement/disease_classification_choice_cardiovascular.yaml +38 -0
- endoreg_db/data/requirement/disease_hepatology.yaml +12 -0
- endoreg_db/data/requirement/disease_misc.yaml +12 -0
- endoreg_db/data/requirement/disease_renal.yaml +80 -0
- endoreg_db/data/requirement/event_cardiology.yaml +251 -0
- endoreg_db/data/requirement/lab_value.yaml +120 -0
- endoreg_db/data/requirement_operator/lab_operators.yaml +128 -0
- endoreg_db/data/requirement_operator/model_operators.yaml +90 -0
- endoreg_db/data/requirement_set/endoscopy_bleeding_risk.yaml +12 -0
- endoreg_db/data/requirement_set_type/data.yaml +20 -0
- endoreg_db/data/requirement_type/requirement_types.yaml +83 -0
- endoreg_db/data/risk/bleeding.yaml +26 -0
- endoreg_db/data/risk/thrombosis.yaml +37 -0
- endoreg_db/data/risk_type/data.yaml +27 -0
- endoreg_db/data/unit/time.yaml +36 -1
- endoreg_db/management/commands/load_base_db_data.py +14 -1
- endoreg_db/management/commands/load_center_data.py +46 -21
- endoreg_db/management/commands/load_examination_indication_data.py +49 -27
- endoreg_db/management/commands/load_requirement_data.py +156 -0
- endoreg_db/management/commands/load_risk_data.py +56 -0
- endoreg_db/mermaid/Overall_flow_patient_finding_intervention.md +10 -0
- endoreg_db/mermaid/anonymized_image_annotation.md +20 -0
- endoreg_db/mermaid/binary_classification_annotation.md +50 -0
- endoreg_db/mermaid/classification.md +8 -0
- endoreg_db/mermaid/examination.md +8 -0
- endoreg_db/mermaid/findings.md +7 -0
- endoreg_db/mermaid/image_classification.md +28 -0
- endoreg_db/mermaid/interventions.md +8 -0
- endoreg_db/mermaid/morphology.md +8 -0
- endoreg_db/mermaid/patient_creation.md +14 -0
- endoreg_db/mermaid/video_segmentation_annotation.md +17 -0
- endoreg_db/migrations/0009_requirementoperator_requirementsettype_and_more.py +154 -0
- endoreg_db/models/__init__.py +20 -0
- endoreg_db/models/ai_model/ai_model.py +0 -13
- endoreg_db/models/ai_model/model_meta.py +2 -12
- endoreg_db/models/data_file/base_classes/abstract_frame.py +0 -2
- endoreg_db/models/data_file/base_classes/abstract_pdf.py +0 -9
- endoreg_db/models/data_file/base_classes/abstract_video.py +7 -8
- endoreg_db/models/data_file/base_classes/utils.py +0 -22
- endoreg_db/models/data_file/frame.py +1 -1
- endoreg_db/models/data_file/import_classes/raw_pdf.py +5 -11
- endoreg_db/models/data_file/import_classes/raw_video.py +6 -4
- endoreg_db/models/data_file/video/video.py +3 -3
- endoreg_db/models/disease.py +88 -19
- endoreg_db/models/event.py +108 -21
- endoreg_db/models/examination/examination_indication.py +108 -29
- endoreg_db/models/examination/examination_type.py +20 -6
- endoreg_db/models/information_source.py +37 -1
- endoreg_db/models/laboratory/lab_value.py +83 -32
- endoreg_db/models/requirement/__init__.py +11 -0
- endoreg_db/models/requirement/requirement.py +325 -0
- endoreg_db/models/requirement/requirement_evaluation/__init__.py +134 -0
- endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +102 -0
- endoreg_db/models/requirement/requirement_operator.py +58 -0
- endoreg_db/models/requirement/requirement_set.py +127 -0
- endoreg_db/models/risk/__init__.py +7 -0
- endoreg_db/models/risk/risk.py +72 -0
- endoreg_db/models/risk/risk_type.py +55 -0
- endoreg_db/serializers/raw_pdf_anony_text_validation.py +137 -0
- endoreg_db/serializers/raw_pdf_meta_validation.py +223 -0
- endoreg_db/serializers/raw_video_meta_validation.py +163 -1
- endoreg_db/serializers/video_segmentation.py +208 -126
- endoreg_db/urls.py +127 -14
- endoreg_db/utils/__init__.py +43 -0
- endoreg_db/utils/dataloader.py +38 -19
- endoreg_db/utils/hashs.py +1 -0
- endoreg_db/utils/paths.py +86 -0
- endoreg_db/views/raw_pdf_anony_text_validation_views.py +95 -0
- endoreg_db/views/raw_pdf_meta_validation_views.py +111 -0
- endoreg_db/views/raw_video_meta_validation_views.py +128 -18
- endoreg_db/views/video_segmentation_views.py +28 -11
- endoreg_db/views/views.py +107 -0
- {endoreg_db-0.6.2.dist-info → endoreg_db-0.6.4.dist-info}/METADATA +1 -1
- {endoreg_db-0.6.2.dist-info → endoreg_db-0.6.4.dist-info}/RECORD +96 -46
- endoreg_db/management/commands/load_name_data.py +0 -37
- {endoreg_db-0.6.2.dist-info → endoreg_db-0.6.4.dist-info}/WHEEL +0 -0
- {endoreg_db-0.6.2.dist-info → endoreg_db-0.6.4.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
```mermaid
|
|
2
|
+
graph TD;
|
|
3
|
+
|
|
4
|
+
%% File Handling Process
|
|
5
|
+
A[**Uploaded File**] -->|Original File Uploaded| B[**Anonymized File**]
|
|
6
|
+
B -->|File Anonymized & Stored| C[**Anonymous Image Annotation**]
|
|
7
|
+
|
|
8
|
+
%% Image Annotation & Processing
|
|
9
|
+
C -->|Label Assigned| D[**Anonymized Image Label**]
|
|
10
|
+
C -->|Detected Personal Info Removed| E[**Dropped Name**]
|
|
11
|
+
|
|
12
|
+
%% Relationships & Processing
|
|
13
|
+
E -->|Stored for Record-Keeping| C;
|
|
14
|
+
D -->|Predefined Labels Used| C;
|
|
15
|
+
|
|
16
|
+
%% Example Data (Corrected & Meaningful)
|
|
17
|
+
X1(["**Example: Uploaded colonoscopy.jpg**"]) -.-> A;
|
|
18
|
+
X2(["**Example: anonymized_colonoscopy.jpg**"]) -.-> B;
|
|
19
|
+
X3(["**Example: Label - 'Polyp Detected'**"]) -.-> D;
|
|
20
|
+
X4(["**Example: Name 'John Doe' removed**"]) -.-> E;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
```mermaid
|
|
2
|
+
graph TD;
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
%% Step 1: Image Classification (Start)
|
|
7
|
+
|
|
8
|
+
A[**Image Classification**] -->|Uses| B[**Label**];
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
%% Step 2: Video Segmentation
|
|
13
|
+
|
|
14
|
+
A -->|Segments Stored In| C[**Video Segmentation**];
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
%% Step 3: Automatic Segmentation Detection
|
|
19
|
+
|
|
20
|
+
D["**find_segments_in_prediction_array()**"] -->|Detects & Segments| C;
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
%% Step 4: Fetching Unclassified Frames for Annotation
|
|
25
|
+
|
|
26
|
+
E["get_legacy_binary_classification_annotation_tasks_by_label()"] -->|Finds Frames Needing Annotation| F;
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
%% Step 5: Binary Classification Task Management
|
|
31
|
+
|
|
32
|
+
F[**Binary Classification Task**] -->|Assigned To| G[**Frame**];
|
|
33
|
+
|
|
34
|
+
F -->|Assigned To| H[**Legacy Frame**];
|
|
35
|
+
|
|
36
|
+
F -->|Uses| B;
|
|
37
|
+
|
|
38
|
+
%% Step 6: Task Completion & Cleanup (End)
|
|
39
|
+
|
|
40
|
+
I["clear_finished_legacy_tasks()"] -->|Removes Completed Tasks| F;
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
%% Example Data
|
|
45
|
+
|
|
46
|
+
X1(["Example: Frame classified as 'Polyp Present'"]) -.-> A;
|
|
47
|
+
|
|
48
|
+
X2(["Example: Video segment marked from 100s to 200s"]) -.-> C;
|
|
49
|
+
|
|
50
|
+
X3(["Example: 10 unclassified frames found"]) -.-> F;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
```mermaid
|
|
2
|
+
graph TD;
|
|
3
|
+
|
|
4
|
+
A["Start: Select Finding Location Classification"] --> B["Store in endoreg_db_findinglocationclassification"]
|
|
5
|
+
B --> C["Retrieve Available Choices"]
|
|
6
|
+
C --> D["Save Selected Location in endoreg_db_patientfinding_locations"]
|
|
7
|
+
D --> E["Link Location to Patient Finding via Foreign Key"]
|
|
8
|
+
E --> F["Finding Location Process Completed"]
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
```mermaid
|
|
2
|
+
graph TD;
|
|
3
|
+
|
|
4
|
+
A["Start: Record Examination"] --> B["Store in endoreg_db_examination"]
|
|
5
|
+
B --> C["Retrieve Patient ID"]
|
|
6
|
+
C --> D["Save in endoreg_db_patientexamination with Patient ID"]
|
|
7
|
+
D --> E["Link Patient to Examination via Foreign Key"]
|
|
8
|
+
E --> F["Examination Process Completed"]
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
```mermaid
|
|
2
|
+
graph TD;
|
|
3
|
+
|
|
4
|
+
A["Start: Identify Medical Finding"] --> B["Store in endoreg_db_finding"]
|
|
5
|
+
B --> C["Retrieve Patient Examination ID"]
|
|
6
|
+
C --> D["Save in endoreg_db_patientfinding with Examination ID (Link Finding to Examination via Foreign Key)"]
|
|
7
|
+
D --> E["Finding Process Completed"]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
```mermaid
|
|
2
|
+
graph TD;
|
|
3
|
+
|
|
4
|
+
%% Image Classification Process
|
|
5
|
+
A[**Image Classification Annotation**] -->|Attached to| B[**Frame**];
|
|
6
|
+
A -->|Attached to| C[**Legacy Frame**];
|
|
7
|
+
A -->|Attached to| D[**Legacy Image**];
|
|
8
|
+
A -->|Uses Predefined| E[**Label**];
|
|
9
|
+
|
|
10
|
+
%% Video Segmentation Process
|
|
11
|
+
F[**Abstract Label Video Segment**] -->|Base Class for| G[**Legacy Label Video Segment**];
|
|
12
|
+
F -->|Base Class for| H[**Label Video Segment**];
|
|
13
|
+
|
|
14
|
+
%% Video References
|
|
15
|
+
G -->|Segmentation of| I[**Legacy Video**];
|
|
16
|
+
H -->|Segmentation of| J[**Modern Video**];
|
|
17
|
+
|
|
18
|
+
%% Metadata & Prediction Handling
|
|
19
|
+
G -->|Uses Prediction Data| K[**Legacy Video Prediction Meta**];
|
|
20
|
+
H -->|Uses Prediction Data| L[**Video Prediction Meta**];
|
|
21
|
+
|
|
22
|
+
%% Automatic Segmentation Process
|
|
23
|
+
M["**find_segments_in_prediction_array()**"] -->|Detects & Segments Frames| F;
|
|
24
|
+
|
|
25
|
+
%% Example Data
|
|
26
|
+
X1(["**Example: Frame classified as 'Polyp Present'**"]) -.-> A;
|
|
27
|
+
X2(["**Example: Segment starts at frame 100, ends at frame 200**"]) -.-> F;
|
|
28
|
+
X3(["**Example: Legacy Video used for segmentation**"]) -.-> G;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
```mermaid
|
|
2
|
+
graph TD;
|
|
3
|
+
|
|
4
|
+
A["Start: Select Intervention"] --> B["Store in endoreg_db_findingintervention"]
|
|
5
|
+
B --> C["Retrieve Patient Finding ID"]
|
|
6
|
+
C --> D["Save in endoreg_db_patientfindingintervention"]
|
|
7
|
+
D --> E["Link Intervention to Patient Finding via Foreign Key"]
|
|
8
|
+
E --> F["Intervention Process Completed"]
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
```mermaid
|
|
2
|
+
graph TD;
|
|
3
|
+
|
|
4
|
+
A["Start: Select Morphology Classification"] --> B["Store in endoreg_db_findingmorphologyclassification"]
|
|
5
|
+
B --> C["Retrieve Associated Classification Type"]
|
|
6
|
+
C --> D["Save in endoreg_db_patientfinding_morphology"]
|
|
7
|
+
D --> E["Link Morphology to Patient Finding via Foreign Key"]
|
|
8
|
+
E --> F["Morphology Process Completed"]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
```mermaid
|
|
2
|
+
graph TD;
|
|
3
|
+
|
|
4
|
+
A["Start: Create New Patient (John)"] --> B{"Does the Center Exist?"}
|
|
5
|
+
|
|
6
|
+
B -- Yes --> C["Retrieve Existing Center ID"]
|
|
7
|
+
B -- No --> D["Create New Medical Center"]
|
|
8
|
+
|
|
9
|
+
D --> E["Retrieve Newly Created Center ID"]
|
|
10
|
+
C --> F["Save Patient in endoreg_db_patient with Center ID"]
|
|
11
|
+
E --> F
|
|
12
|
+
|
|
13
|
+
F --> G["Patient Registration Completed"]
|
|
14
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
```mermaid
|
|
2
|
+
graph TD;
|
|
3
|
+
|
|
4
|
+
%% Label Management
|
|
5
|
+
A[**Video Segmentation Label**] -->|Used in| B[**Video Segmentation Annotation**];
|
|
6
|
+
|
|
7
|
+
%% Annotation Process
|
|
8
|
+
B -->|Assigned to| C[**Raw Video File**];
|
|
9
|
+
|
|
10
|
+
%% Attributes Breakdown
|
|
11
|
+
A -->|Has Fields| A1[**Name, Description, Color, Priority**];
|
|
12
|
+
B -->|Has Fields| B1[**Start Time, Stop Time, Validity**];
|
|
13
|
+
|
|
14
|
+
%% Example Data (Placed Outside for Clarity)
|
|
15
|
+
X1(["Example: Label - 'Polyp Detected'"]) -.-> A;
|
|
16
|
+
X2(["Example: Video1.mp4, Start: 10s, Stop: 15s"]) -.-> B;
|
|
17
|
+
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Generated by Django 5.1.3 on 2025-04-06 23:05
|
|
2
|
+
|
|
3
|
+
import django.core.files.storage
|
|
4
|
+
import django.core.validators
|
|
5
|
+
import django.db.models.deletion
|
|
6
|
+
from django.db import migrations, models
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Migration(migrations.Migration):
|
|
10
|
+
|
|
11
|
+
dependencies = [
|
|
12
|
+
('endoreg_db', '0008_remove_reportfile_patient_examination_and_more'),
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
operations = [
|
|
16
|
+
migrations.CreateModel(
|
|
17
|
+
name='RequirementOperator',
|
|
18
|
+
fields=[
|
|
19
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
20
|
+
('name', models.CharField(max_length=100, unique=True)),
|
|
21
|
+
('name_de', models.CharField(blank=True, max_length=100, null=True)),
|
|
22
|
+
('name_en', models.CharField(blank=True, max_length=100, null=True)),
|
|
23
|
+
('description', models.TextField(blank=True, null=True)),
|
|
24
|
+
],
|
|
25
|
+
),
|
|
26
|
+
migrations.CreateModel(
|
|
27
|
+
name='RequirementSetType',
|
|
28
|
+
fields=[
|
|
29
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
30
|
+
('name', models.CharField(max_length=100, unique=True)),
|
|
31
|
+
('name_de', models.CharField(blank=True, max_length=100, null=True)),
|
|
32
|
+
('name_en', models.CharField(blank=True, max_length=100, null=True)),
|
|
33
|
+
('description', models.TextField(blank=True, null=True)),
|
|
34
|
+
],
|
|
35
|
+
),
|
|
36
|
+
migrations.CreateModel(
|
|
37
|
+
name='RequirementType',
|
|
38
|
+
fields=[
|
|
39
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
40
|
+
('name', models.CharField(max_length=100, unique=True)),
|
|
41
|
+
('name_de', models.CharField(blank=True, max_length=100, null=True)),
|
|
42
|
+
('name_en', models.CharField(blank=True, max_length=100, null=True)),
|
|
43
|
+
('description', models.TextField(blank=True, null=True)),
|
|
44
|
+
],
|
|
45
|
+
),
|
|
46
|
+
migrations.CreateModel(
|
|
47
|
+
name='RiskType',
|
|
48
|
+
fields=[
|
|
49
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
50
|
+
('name', models.CharField(max_length=100, unique=True)),
|
|
51
|
+
('name_de', models.CharField(blank=True, max_length=100, null=True)),
|
|
52
|
+
('name_en', models.CharField(blank=True, max_length=100, null=True)),
|
|
53
|
+
('description', models.TextField(blank=True, null=True)),
|
|
54
|
+
],
|
|
55
|
+
),
|
|
56
|
+
migrations.RemoveField(
|
|
57
|
+
model_name='examinationindication',
|
|
58
|
+
name='classification',
|
|
59
|
+
),
|
|
60
|
+
migrations.AddField(
|
|
61
|
+
model_name='examinationindication',
|
|
62
|
+
name='classifications',
|
|
63
|
+
field=models.ManyToManyField(blank=True, related_name='indications', to='endoreg_db.examinationindicationclassification'),
|
|
64
|
+
),
|
|
65
|
+
migrations.AddField(
|
|
66
|
+
model_name='examinationindication',
|
|
67
|
+
name='description',
|
|
68
|
+
field=models.TextField(blank=True, null=True),
|
|
69
|
+
),
|
|
70
|
+
migrations.AddField(
|
|
71
|
+
model_name='examinationindication',
|
|
72
|
+
name='expected_interventions',
|
|
73
|
+
field=models.ManyToManyField(blank=True, related_name='indications', to='endoreg_db.findingintervention'),
|
|
74
|
+
),
|
|
75
|
+
migrations.AddField(
|
|
76
|
+
model_name='examinationindicationclassification',
|
|
77
|
+
name='description',
|
|
78
|
+
field=models.TextField(blank=True, null=True),
|
|
79
|
+
),
|
|
80
|
+
migrations.AddField(
|
|
81
|
+
model_name='examinationindicationclassification',
|
|
82
|
+
name='examination',
|
|
83
|
+
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='indication_classifications', to='endoreg_db.examination'),
|
|
84
|
+
),
|
|
85
|
+
migrations.AlterField(
|
|
86
|
+
model_name='rawpdffile',
|
|
87
|
+
name='file',
|
|
88
|
+
field=models.FileField(storage=django.core.files.storage.FileSystemStorage(location='/home/admin/dev/endoreg-db/erc_data'), upload_to='raw_pdf/', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['pdf'])]),
|
|
89
|
+
),
|
|
90
|
+
migrations.AlterField(
|
|
91
|
+
model_name='rawvideofile',
|
|
92
|
+
name='file',
|
|
93
|
+
field=models.FileField(storage=django.core.files.storage.FileSystemStorage(location='/home/admin/dev/endoreg-db/erc_data'), upload_to='db_raw_videos', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['mp4'])]),
|
|
94
|
+
),
|
|
95
|
+
migrations.AlterField(
|
|
96
|
+
model_name='video',
|
|
97
|
+
name='file',
|
|
98
|
+
field=models.FileField(storage=django.core.files.storage.FileSystemStorage(location='/home/admin/dev/endoreg-db/erc_data'), upload_to='db_videos', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['mp4'])]),
|
|
99
|
+
),
|
|
100
|
+
migrations.CreateModel(
|
|
101
|
+
name='Requirement',
|
|
102
|
+
fields=[
|
|
103
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
104
|
+
('name', models.CharField(max_length=100, unique=True)),
|
|
105
|
+
('name_de', models.CharField(blank=True, max_length=100, null=True)),
|
|
106
|
+
('name_en', models.CharField(blank=True, max_length=100, null=True)),
|
|
107
|
+
('description', models.TextField(blank=True, null=True)),
|
|
108
|
+
('numeric_value', models.FloatField(blank=True, help_text='Numeric value for the requirement. If not set, the requirement is not used in calculations.', null=True)),
|
|
109
|
+
('numeric_value_min', models.FloatField(blank=True, help_text='Minimum numeric value for the requirement. If not set, the requirement is not used in calculations.', null=True)),
|
|
110
|
+
('numeric_value_max', models.FloatField(blank=True, help_text='Maximum numeric value for the requirement. If not set, the requirement is not used in calculations.', null=True)),
|
|
111
|
+
('string_value', models.CharField(blank=True, help_text='String value for the requirement. If not set, the requirement is not used in calculations.', max_length=100, null=True)),
|
|
112
|
+
('string_values', models.TextField(blank=True, help_text=" ','-separated list of string values for the requirement.If not set, the requirement is not used in calculations.", null=True)),
|
|
113
|
+
('disease_classification_choices', models.ManyToManyField(blank=True, related_name='required_in', to='endoreg_db.diseaseclassificationchoice')),
|
|
114
|
+
('diseases', models.ManyToManyField(blank=True, related_name='required_in', to='endoreg_db.disease')),
|
|
115
|
+
('events', models.ManyToManyField(blank=True, related_name='required_in', to='endoreg_db.event')),
|
|
116
|
+
('examination_indications', models.ManyToManyField(blank=True, related_name='required_in', to='endoreg_db.examinationindication')),
|
|
117
|
+
('examinations', models.ManyToManyField(blank=True, related_name='required_in', to='endoreg_db.examination')),
|
|
118
|
+
('finding_interventions', models.ManyToManyField(blank=True, related_name='required_in', to='endoreg_db.findingintervention')),
|
|
119
|
+
('finding_location_classification_choices', models.ManyToManyField(blank=True, related_name='required_in', to='endoreg_db.findinglocationclassificationchoice')),
|
|
120
|
+
('finding_morphology_classification_choices', models.ManyToManyField(blank=True, related_name='required_in', to='endoreg_db.findingmorphologyclassificationchoice')),
|
|
121
|
+
('findings', models.ManyToManyField(blank=True, related_name='required_in', to='endoreg_db.finding')),
|
|
122
|
+
('lab_values', models.ManyToManyField(blank=True, related_name='required_in', to='endoreg_db.labvalue')),
|
|
123
|
+
('unit', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='required_in', to='endoreg_db.unit')),
|
|
124
|
+
('operators', models.ManyToManyField(blank=True, related_name='required_in', to='endoreg_db.requirementoperator')),
|
|
125
|
+
('requirement_types', models.ManyToManyField(blank=True, related_name='linked_requirements', to='endoreg_db.requirementtype')),
|
|
126
|
+
],
|
|
127
|
+
),
|
|
128
|
+
migrations.CreateModel(
|
|
129
|
+
name='RequirementSet',
|
|
130
|
+
fields=[
|
|
131
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
132
|
+
('name', models.CharField(max_length=100, unique=True)),
|
|
133
|
+
('name_de', models.CharField(blank=True, max_length=100, null=True)),
|
|
134
|
+
('name_en', models.CharField(blank=True, max_length=100, null=True)),
|
|
135
|
+
('description', models.TextField(blank=True, null=True)),
|
|
136
|
+
('information_sources', models.ManyToManyField(blank=True, related_name='requirement_sets', to='endoreg_db.informationsource')),
|
|
137
|
+
('links_to_sets', models.ManyToManyField(blank=True, related_name='links_from_sets', to='endoreg_db.requirementset')),
|
|
138
|
+
('requirements', models.ManyToManyField(blank=True, related_name='requirement_sets', to='endoreg_db.requirement')),
|
|
139
|
+
('requirement_set_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='requirement_sets', to='endoreg_db.requirementsettype')),
|
|
140
|
+
],
|
|
141
|
+
),
|
|
142
|
+
migrations.CreateModel(
|
|
143
|
+
name='Risk',
|
|
144
|
+
fields=[
|
|
145
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
146
|
+
('name', models.CharField(max_length=100, unique=True)),
|
|
147
|
+
('name_de', models.CharField(blank=True, max_length=100, null=True)),
|
|
148
|
+
('name_en', models.CharField(blank=True, max_length=100, null=True)),
|
|
149
|
+
('description', models.TextField(blank=True, null=True)),
|
|
150
|
+
('risk_value', models.FloatField(blank=True, help_text='Risk value for the risk. If not set, the risk is not used in calculations.', null=True)),
|
|
151
|
+
('risk_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='risks', to='endoreg_db.risktype')),
|
|
152
|
+
],
|
|
153
|
+
),
|
|
154
|
+
]
|
endoreg_db/models/__init__.py
CHANGED
|
@@ -97,6 +97,19 @@ from .case_template import (
|
|
|
97
97
|
CaseTemplateRuleValueType,
|
|
98
98
|
)
|
|
99
99
|
|
|
100
|
+
from .risk import (
|
|
101
|
+
Risk,
|
|
102
|
+
RiskType,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
from .requirement import (
|
|
106
|
+
Requirement,
|
|
107
|
+
RequirementSet,
|
|
108
|
+
RequirementSetType,
|
|
109
|
+
RequirementOperator,
|
|
110
|
+
RequirementType,
|
|
111
|
+
)
|
|
112
|
+
|
|
100
113
|
# Rules
|
|
101
114
|
from .rules import (
|
|
102
115
|
Rule,
|
|
@@ -373,4 +386,11 @@ __all__ = [
|
|
|
373
386
|
"RawPdfFile",
|
|
374
387
|
"RawVideoFile",
|
|
375
388
|
"VideoSegmentationLabelSet",
|
|
389
|
+
"RequirementSet",
|
|
390
|
+
"RequirementSetType",
|
|
391
|
+
"Requirement",
|
|
392
|
+
"RequirementOperator",
|
|
393
|
+
"RequirementType",
|
|
394
|
+
"Risk",
|
|
395
|
+
"RiskType",
|
|
376
396
|
]
|
|
@@ -1,22 +1,9 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Django model for AI models.
|
|
3
3
|
"""
|
|
4
|
-
|
|
5
|
-
from pathlib import Path
|
|
6
|
-
import os
|
|
7
4
|
from django.db import models
|
|
8
5
|
from icecream import ic
|
|
9
6
|
|
|
10
|
-
PSEUDO_DIR = Path(os.environ.get("DJANGO_PSEUDO_DIR", Path("./erc_data")))
|
|
11
|
-
|
|
12
|
-
STORAGE_LOCATION = PSEUDO_DIR
|
|
13
|
-
WEIGHTS_DIR_NAME = "db_model_weights"
|
|
14
|
-
WEIGHTS_DIR = STORAGE_LOCATION / WEIGHTS_DIR_NAME
|
|
15
|
-
|
|
16
|
-
if not WEIGHTS_DIR.exists():
|
|
17
|
-
WEIGHTS_DIR.mkdir(parents=True)
|
|
18
|
-
|
|
19
|
-
|
|
20
7
|
class AiModelManager(models.Manager):
|
|
21
8
|
"""
|
|
22
9
|
Manager for AI models with custom query methods.
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
This module defines the ModelMeta and ModelMetaManager classes for managing AI model metadata.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
import os
|
|
6
5
|
from pathlib import Path
|
|
7
6
|
from typing import Optional, TYPE_CHECKING
|
|
8
7
|
import shutil
|
|
@@ -10,20 +9,11 @@ import shutil
|
|
|
10
9
|
from django.db import models
|
|
11
10
|
from django.core.validators import FileExtensionValidator
|
|
12
11
|
from icecream import ic
|
|
12
|
+
from ...utils import WEIGHTS_DIR
|
|
13
13
|
|
|
14
14
|
if TYPE_CHECKING:
|
|
15
15
|
from endoreg_db.models import LabelSet, AiModel # pylint: disable=import-outside-toplevel
|
|
16
16
|
|
|
17
|
-
PSEUDO_DIR = Path(os.environ.get("DJANGO_PSEUDO_DIR", Path("./erc_data")))
|
|
18
|
-
|
|
19
|
-
STORAGE_LOCATION = PSEUDO_DIR
|
|
20
|
-
WEIGHTS_DIR_NAME = "db_model_weights"
|
|
21
|
-
WEIGHTS_DIR = STORAGE_LOCATION / WEIGHTS_DIR_NAME
|
|
22
|
-
|
|
23
|
-
if not WEIGHTS_DIR.exists():
|
|
24
|
-
WEIGHTS_DIR.mkdir(parents=True)
|
|
25
|
-
|
|
26
|
-
|
|
27
17
|
class ModelMetaManager(models.Manager):
|
|
28
18
|
"""
|
|
29
19
|
Custom manager for ModelMeta with additional query methods.
|
|
@@ -57,7 +47,7 @@ class ModelMeta(models.Model):
|
|
|
57
47
|
activation = models.CharField(max_length=255, default="sigmoid")
|
|
58
48
|
|
|
59
49
|
weights = models.FileField(
|
|
60
|
-
upload_to=
|
|
50
|
+
upload_to=WEIGHTS_DIR.name,
|
|
61
51
|
validators=[FileExtensionValidator(allowed_extensions=["ckpt"])],
|
|
62
52
|
# storage=FileSystemStorage(location=STORAGE_LOCATION.resolve().as_posix()),
|
|
63
53
|
null=True,
|
|
@@ -5,12 +5,10 @@ from endoreg_db.models.annotation.image_classification import (
|
|
|
5
5
|
from endoreg_db.models.label.label import Label
|
|
6
6
|
|
|
7
7
|
from django.db import models
|
|
8
|
-
from .utils import FRAME_DIR_NAME
|
|
9
8
|
|
|
10
9
|
if TYPE_CHECKING:
|
|
11
10
|
from endoreg_db.models import Video, RawVideoFile
|
|
12
11
|
|
|
13
|
-
|
|
14
12
|
class AbstractFrame(models.Model):
|
|
15
13
|
frame_number = models.IntegerField()
|
|
16
14
|
# Add any other fields you need to store frame-related information
|
|
@@ -26,21 +26,12 @@ import logging
|
|
|
26
26
|
from pathlib import Path
|
|
27
27
|
from typing import TYPE_CHECKING
|
|
28
28
|
|
|
29
|
-
from ..base_classes.utils import (
|
|
30
|
-
STORAGE_LOCATION,
|
|
31
|
-
)
|
|
32
29
|
|
|
33
30
|
if TYPE_CHECKING:
|
|
34
31
|
from endoreg_db.models import SensitiveMeta
|
|
35
32
|
|
|
36
33
|
logger = logging.getLogger("pdf_import")
|
|
37
34
|
|
|
38
|
-
RAW_PDF_DIR_NAME = "raw_pdf"
|
|
39
|
-
RAW_PDF_DIR = STORAGE_LOCATION / RAW_PDF_DIR_NAME
|
|
40
|
-
|
|
41
|
-
if not RAW_PDF_DIR.exists():
|
|
42
|
-
RAW_PDF_DIR.mkdir(parents=True)
|
|
43
|
-
|
|
44
35
|
|
|
45
36
|
class AbstractPdfFile(models.Model):
|
|
46
37
|
pdf_hash = models.CharField(max_length=255, unique=True)
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
""" """
|
|
2
2
|
|
|
3
|
+
from django.db import models
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
from collections import defaultdict, Counter
|
|
5
6
|
import shutil
|
|
6
7
|
import os
|
|
7
|
-
import subprocess
|
|
8
8
|
from typing import Optional, List, TYPE_CHECKING, Union
|
|
9
|
-
from django.db import models, transaction
|
|
10
9
|
from icecream import ic
|
|
11
|
-
from tqdm import tqdm
|
|
12
10
|
from endoreg_db.utils.hashs import get_video_hash
|
|
13
11
|
from endoreg_db.utils.file_operations import get_uuid_filename
|
|
14
12
|
from endoreg_db.utils.ocr import extract_text_from_rois
|
|
@@ -21,12 +19,11 @@ from ....utils.video import (
|
|
|
21
19
|
)
|
|
22
20
|
|
|
23
21
|
from ..metadata import VideoMeta, SensitiveMeta
|
|
24
|
-
from
|
|
25
|
-
|
|
22
|
+
from ....utils import (
|
|
23
|
+
STORAGE_DIR,
|
|
26
24
|
VIDEO_DIR,
|
|
27
25
|
FRAME_DIR,
|
|
28
26
|
)
|
|
29
|
-
from .prepare_bulk_frames import prepare_bulk_frames
|
|
30
27
|
|
|
31
28
|
if TYPE_CHECKING:
|
|
32
29
|
from endoreg_db.models import (
|
|
@@ -180,10 +177,10 @@ class AbstractVideoFile(models.Model):
|
|
|
180
177
|
ic(f"No existing DB entry found, creating new with UUID {uuid}")
|
|
181
178
|
|
|
182
179
|
try:
|
|
183
|
-
relative_path = transcoded_file_path.relative_to(
|
|
180
|
+
relative_path = transcoded_file_path.relative_to(STORAGE_DIR)
|
|
184
181
|
except ValueError as e:
|
|
185
182
|
raise Exception(
|
|
186
|
-
f"{transcoded_file_path} is outside
|
|
183
|
+
f"{transcoded_file_path} is outside STORAGE_DIR {STORAGE_DIR}"
|
|
187
184
|
) from e
|
|
188
185
|
|
|
189
186
|
video = cls(
|
|
@@ -325,6 +322,8 @@ class AbstractVideoFile(models.Model):
|
|
|
325
322
|
ModelMeta,
|
|
326
323
|
AiModel,
|
|
327
324
|
) # pylint: disable=import-outside-toplevel
|
|
325
|
+
#TODO Create issue to movie this function to the endo-ai module
|
|
326
|
+
#endoreg-db is our "base" module, so it should not depend "upstream" models
|
|
328
327
|
from endo_ai.predictor.inference_dataset import InferenceDataset # pylint: disable=import-outside-toplevel
|
|
329
328
|
from endo_ai.predictor.model_loader import MultiLabelClassificationNet
|
|
330
329
|
from endo_ai.predictor.predict import Classifier
|
|
@@ -7,28 +7,6 @@ from pathlib import Path
|
|
|
7
7
|
import cv2
|
|
8
8
|
import numpy as np
|
|
9
9
|
|
|
10
|
-
DJANGO_NAME_SALT = os.environ.get("DJANGO_NAME_SALT", "default_salt")
|
|
11
|
-
|
|
12
|
-
# Directory stuff
|
|
13
|
-
PSEUDO_DIR = Path(os.environ.get("DJANGO_PSEUDO_DIR", Path("./erc_data")))
|
|
14
|
-
STORAGE_LOCATION = PSEUDO_DIR
|
|
15
|
-
FRAME_DIR_NAME = os.environ.get("DJANGO_FRAME_DIR_NAME", "db_frames")
|
|
16
|
-
RAW_FRAME_DIR_NAME = os.environ.get("DJANGO_RAW_FRAME_DIR_NAME", "db_raw_frames")
|
|
17
|
-
VIDEO_DIR_NAME = os.environ.get("DJANGO_VIDEO_DIR_NAME", "db_videos")
|
|
18
|
-
RAW_VIDEO_DIR_NAME = os.environ.get("DJANGO_RAW_VIDEO_DIR_NAME", "db_raw_videos")
|
|
19
|
-
|
|
20
|
-
FRAME_DIR = STORAGE_LOCATION / FRAME_DIR_NAME
|
|
21
|
-
VIDEO_DIR = STORAGE_LOCATION / VIDEO_DIR_NAME
|
|
22
|
-
RAW_VIDEO_DIR = STORAGE_LOCATION / RAW_VIDEO_DIR_NAME
|
|
23
|
-
|
|
24
|
-
TEST_RUN = os.environ.get("TEST_RUN", False)
|
|
25
|
-
TEST_RUN_FRAME_NUMBER = os.environ.get("TEST_RUN_FRAME_NUMBER", 1000)
|
|
26
|
-
|
|
27
|
-
VIDEO_DIR.mkdir(parents=True, exist_ok=True)
|
|
28
|
-
RAW_VIDEO_DIR.mkdir(parents=True, exist_ok=True)
|
|
29
|
-
|
|
30
|
-
# AI Stuff
|
|
31
|
-
FRAME_PROCESSING_BATCH_SIZE = os.environ.get("DJANGO_FRAME_PROCESSING_BATCH_SIZE", 10)
|
|
32
10
|
|
|
33
11
|
|
|
34
12
|
def anonymize_frame(
|
|
@@ -4,7 +4,7 @@ from endoreg_db.models.label.label import Label
|
|
|
4
4
|
from .base_classes import AbstractFrame
|
|
5
5
|
from django.db import models
|
|
6
6
|
|
|
7
|
-
from
|
|
7
|
+
from ...utils import FRAME_DIR_NAME, RAW_FRAME_DIR_NAME
|
|
8
8
|
|
|
9
9
|
if TYPE_CHECKING:
|
|
10
10
|
from endoreg_db.models import RawVideoFile, Video
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
|
|
8
8
|
from django.db import models
|
|
9
9
|
from django.core.files.storage import FileSystemStorage
|
|
10
|
-
from django.conf import settings
|
|
11
10
|
from django.core.exceptions import ValidationError
|
|
12
11
|
from django.core.validators import FileExtensionValidator
|
|
13
12
|
from endoreg_db.utils.file_operations import get_uuid_filename
|
|
@@ -25,24 +24,19 @@ import logging
|
|
|
25
24
|
import shutil
|
|
26
25
|
from pathlib import Path
|
|
27
26
|
|
|
28
|
-
from
|
|
29
|
-
|
|
27
|
+
from ....utils import (
|
|
28
|
+
STORAGE_DIR,
|
|
29
|
+
RAW_PDF_DIR_NAME,
|
|
30
|
+
RAW_PDF_DIR,
|
|
30
31
|
)
|
|
31
32
|
|
|
32
33
|
logger = logging.getLogger("pdf_import")
|
|
33
34
|
|
|
34
|
-
RAW_PDF_DIR_NAME = "raw_pdf"
|
|
35
|
-
RAW_PDF_DIR = STORAGE_LOCATION / RAW_PDF_DIR_NAME
|
|
36
|
-
|
|
37
|
-
if not RAW_PDF_DIR.exists():
|
|
38
|
-
RAW_PDF_DIR.mkdir(parents=True)
|
|
39
|
-
|
|
40
|
-
|
|
41
35
|
class RawPdfFile(AbstractPdfFile):
|
|
42
36
|
file = models.FileField(
|
|
43
37
|
upload_to=f"{RAW_PDF_DIR_NAME}/",
|
|
44
38
|
validators=[FileExtensionValidator(allowed_extensions=["pdf"])],
|
|
45
|
-
storage=FileSystemStorage(location=
|
|
39
|
+
storage=FileSystemStorage(location=STORAGE_DIR.resolve().as_posix()),
|
|
46
40
|
)
|
|
47
41
|
|
|
48
42
|
patient = models.ForeignKey(
|
|
@@ -13,12 +13,14 @@ from django.core.files.storage import FileSystemStorage
|
|
|
13
13
|
from endoreg_db.utils.validate_endo_roi import validate_endo_roi
|
|
14
14
|
from ..base_classes.utils import (
|
|
15
15
|
anonymize_frame,
|
|
16
|
-
RAW_VIDEO_DIR_NAME,
|
|
17
|
-
VIDEO_DIR,
|
|
18
|
-
STORAGE_LOCATION,
|
|
19
16
|
)
|
|
20
17
|
from ..base_classes.abstract_video import AbstractVideoFile
|
|
18
|
+
from ....utils import (
|
|
21
19
|
|
|
20
|
+
RAW_VIDEO_DIR_NAME,
|
|
21
|
+
VIDEO_DIR,
|
|
22
|
+
STORAGE_DIR,
|
|
23
|
+
)
|
|
22
24
|
if TYPE_CHECKING:
|
|
23
25
|
# import Queryset
|
|
24
26
|
from django.db.models import QuerySet
|
|
@@ -35,7 +37,7 @@ class RawVideoFile(AbstractVideoFile):
|
|
|
35
37
|
file = models.FileField(
|
|
36
38
|
upload_to=RAW_VIDEO_DIR_NAME,
|
|
37
39
|
validators=[FileExtensionValidator(allowed_extensions=["mp4"])], # FIXME
|
|
38
|
-
storage=FileSystemStorage(location=
|
|
40
|
+
storage=FileSystemStorage(location=STORAGE_DIR.resolve().as_posix()),
|
|
39
41
|
)
|
|
40
42
|
|
|
41
43
|
patient = models.ForeignKey(
|
|
@@ -5,9 +5,9 @@ from django.core.files.storage import FileSystemStorage
|
|
|
5
5
|
from typing import TYPE_CHECKING
|
|
6
6
|
import cv2
|
|
7
7
|
from ..base_classes import AbstractVideoFile
|
|
8
|
-
from
|
|
8
|
+
from ....utils import (
|
|
9
9
|
VIDEO_DIR_NAME,
|
|
10
|
-
|
|
10
|
+
STORAGE_DIR,
|
|
11
11
|
FRAME_PROCESSING_BATCH_SIZE,
|
|
12
12
|
)
|
|
13
13
|
|
|
@@ -27,7 +27,7 @@ class Video(AbstractVideoFile):
|
|
|
27
27
|
file = models.FileField(
|
|
28
28
|
upload_to=VIDEO_DIR_NAME,
|
|
29
29
|
validators=[FileExtensionValidator(allowed_extensions=["mp4"])], # FIXME
|
|
30
|
-
storage=FileSystemStorage(location=
|
|
30
|
+
storage=FileSystemStorage(location=STORAGE_DIR.resolve().as_posix()),
|
|
31
31
|
)
|
|
32
32
|
|
|
33
33
|
patient = models.ForeignKey(
|