-
Notifications
You must be signed in to change notification settings - Fork 0
Cleanup Scanning Page #70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
98293b8
8d15530
746dda8
5f8e7b5
363cdb4
2fb9966
201db35
0e0d14d
1b36382
09c5f1b
fe8e922
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -138,22 +138,12 @@ <h2 class="card-title text-lg">Record Metadata</h2> | |
| min-width: 8rem; | ||
| } | ||
| </style> | ||
| <!-- Record Type --> | ||
| <!-- Image Type --> | ||
| <div class="form-control"> | ||
| <label class="label"> | ||
| <span class="label-text">Record Type <span class="text-error">*</span></span> | ||
| <span class="label-text">Image Type<span class="text-error">*</span></span> | ||
| </label> | ||
| <select id="record-type" class="select select-bordered select-sm"> | ||
| <option value="">Loading...</option> | ||
| </select> | ||
| </div> | ||
|
|
||
| <!-- Modality --> | ||
| <div class="form-control"> | ||
| <label class="label"> | ||
| <span class="label-text">Modality <span class="text-error">*</span></span> | ||
| </label> | ||
| <select id="modality" class="select select-bordered select-sm"> | ||
| <select id="image-type" class="select select-bordered select-sm"> | ||
| <option value="">Loading...</option> | ||
| </select> | ||
| </div> | ||
|
|
@@ -247,9 +237,8 @@ <h3 class="font-bold text-lg mb-2">Scanner Device Info</h3> | |
| aiFile: null, | ||
| requiresServerTransform: false, | ||
| transformOps: [], | ||
| aiImageTypeCode: null, | ||
| aiPatientOrientation: null, | ||
| valuesets: { | ||
| image_types: [], | ||
| record_types: [], | ||
| modalities: [] | ||
| } | ||
|
|
@@ -306,7 +295,7 @@ <h3 class="font-bold text-lg mb-2">Scanner Device Info</h3> | |
|
|
||
| async function createRecord(encounterId, formData) { | ||
| const csrftoken = getCsrfToken(); | ||
|
|
||
| const response = await fetch((window.script_name || '') + `/api/encounters/${encounterId}/records/`, { | ||
| method: 'POST', | ||
| headers: { | ||
|
|
@@ -583,38 +572,10 @@ <h3 class="font-bold text-lg mb-2">Scanner Device Info</h3> | |
| state.aiFile = file; | ||
| state.requiresServerTransform = false; | ||
| state.transformOps = []; | ||
| state.aiImageTypeCode = null; | ||
| state.aiPatientOrientation = null; | ||
| showFilePreview(file, file); | ||
| updateSubmitButton(); | ||
| } | ||
|
|
||
| function mapAIType(typePrediction) { | ||
| const mapping = { | ||
| 'Lateral': { | ||
| recordType: '201456002', | ||
| imageType: 'L', | ||
| patientOrientation: ['A', 'F'], | ||
| }, | ||
| 'Hip & Pelvis': { | ||
| recordType: '268425006', | ||
| imageType: 'P', | ||
| patientOrientation: null, | ||
| }, | ||
| 'Foot & Ankle': { | ||
| recordType: '1597004', | ||
| imageType: 'FA', | ||
| patientOrientation: null, | ||
| }, | ||
| 'Hand & Wrist': { | ||
| recordType: '39714003', | ||
| imageType: 'H', | ||
| patientOrientation: null, | ||
| }, | ||
| }; | ||
| return mapping[typePrediction] || null; | ||
| } | ||
|
|
||
| // ======================================== | ||
| // UI UPDATE FUNCTIONS | ||
| // ======================================== | ||
|
|
@@ -698,14 +659,13 @@ <h3 class="font-bold text-lg mb-2">Scanner Device Info</h3> | |
| options.forEach(opt => { | ||
| const option = document.createElement('option'); | ||
| option.value = opt.id; | ||
| option.textContent = opt.display; | ||
| option.textContent = `${opt.display} (${opt.id})`; | ||
|
aspiringLich marked this conversation as resolved.
Outdated
|
||
| select.appendChild(option); | ||
| }); | ||
| } | ||
|
|
||
| function clearFormFields() { | ||
| document.getElementById('record-type').value = ''; | ||
| document.getElementById('modality').value = ''; | ||
| document.getElementById('image-type').value = ''; | ||
| document.getElementById('operator').value = defaultOperatorDisplay; | ||
| // Reset acquisition date to today | ||
| document.getElementById('acquisition-date').valueAsDate = new Date(); | ||
|
|
@@ -717,10 +677,9 @@ <h3 class="font-bold text-lg mb-2">Scanner Device Info</h3> | |
| const hasSubject = state.subject !== null; | ||
| const hasEncounter = state.encounter !== null; | ||
| const hasFile = state.file !== null; | ||
| const hasRecordType = document.getElementById('record-type').value !== ''; | ||
| const hasModality = document.getElementById('modality').value !== ''; | ||
| const hasImageType = document.getElementById('image-type').value !== ''; | ||
|
|
||
| const canSubmit = hasSubject && hasEncounter && hasFile && hasRecordType && hasModality; | ||
| const canSubmit = hasSubject && hasEncounter && hasFile && hasImageType; | ||
| document.getElementById('submit-button').disabled = !canSubmit; | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [claude-sonnet-4.6 / @worker]
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, apply.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [github-copilot/claude-sonnet-4.6] Applied: probability display now uses |
||
| // Update AI and image manipulation buttons (need file and must be PNG) | ||
|
|
@@ -792,7 +751,7 @@ <h3 class="font-bold text-lg mb-2">Scanner Device Info</h3> | |
| // ======================================== | ||
| // IMAGE MANIPULATION FUNCTIONS | ||
| // ======================================== | ||
|
|
||
| // modify image by rotating / flipping | ||
| async function modifyImage(degrees, flip = false) { | ||
| if (!state.aiFile) return; | ||
|
|
@@ -934,8 +893,6 @@ <h3 class="font-bold text-lg mb-2">Scanner Device Info</h3> | |
| state.aiFile = null; | ||
| state.requiresServerTransform = false; | ||
| state.transformOps = []; | ||
| state.aiImageTypeCode = null; | ||
| state.aiPatientOrientation = null; | ||
| document.getElementById('file-preview').classList.add('hidden'); | ||
| clearFormFields(); | ||
| updateSubmitButton(); | ||
|
|
@@ -965,8 +922,6 @@ <h3 class="font-bold text-lg mb-2">Scanner Device Info</h3> | |
|
|
||
| state.file = file; | ||
| state.transformOps = []; | ||
|
zgypa marked this conversation as resolved.
|
||
| state.aiImageTypeCode = null; | ||
| state.aiPatientOrientation = null; | ||
| if (ext === 'png') { | ||
| state.requiresServerTransform = false; | ||
| state.previewFile = file; | ||
|
|
@@ -1046,17 +1001,17 @@ <h3 class="font-bold text-lg mb-2">Scanner Device Info</h3> | |
| try { | ||
| const result = await queryAI(state.aiFile); | ||
|
|
||
| // Map AI type_prediction to record_type select value | ||
| // Map AI type_prediction to image_type select value | ||
| if (result.type_prediction) { | ||
| const mapped = mapAIType(result.type_prediction); | ||
| const recordTypeSelect = document.getElementById('record-type'); | ||
| if (mapped && mapped.recordType) { | ||
| recordTypeSelect.value = mapped.recordType; | ||
| state.aiImageTypeCode = mapped.imageType; | ||
| state.aiPatientOrientation = mapped.patientOrientation; | ||
| let id = state.valuesets.image_types.find(x => x.display === result.type_prediction).id; | ||
| console.log(id); | ||
|
aspiringLich marked this conversation as resolved.
Outdated
|
||
|
|
||
| const imageTypeSelect = document.getElementById('image-type'); | ||
| if (id) { | ||
| imageTypeSelect.value = id; | ||
|
aspiringLich marked this conversation as resolved.
Outdated
|
||
| } | ||
| } | ||
|
|
||
| if (result.flip || result.rotation) { | ||
| try { | ||
| await modifyImage(result.rotation || 0, result.flip || false); | ||
|
|
@@ -1089,16 +1044,40 @@ <h3 class="font-bold text-lg mb-2">Scanner Device Info</h3> | |
| if (state.previewFile) { | ||
| formData.append('thumbnail_preview', state.previewFile, 'thumbnail_preview.png'); | ||
| } | ||
| formData.append('record_type', document.getElementById('record-type').value); | ||
| formData.append('modality', document.getElementById('modality').value); | ||
|
|
||
| if (state.aiImageTypeCode) { | ||
| formData.append('image_type', state.aiImageTypeCode); | ||
| } | ||
| if (state.aiPatientOrientation && state.aiPatientOrientation.length === 2) { | ||
| formData.append('patient_orientation', state.aiPatientOrientation[0]); | ||
| formData.append('patient_orientation', state.aiPatientOrientation[1]); | ||
| // FIXME: currently this is sorta hardcoded because we only support dental scans rn but this should | ||
| // be updated with more logic if we support more types of scans | ||
| // Find any modality where x.id == 'RG' | ||
|
|
||
| const set_record_type_and_modality = (record_type, modality) => { | ||
| console.assert(state.valuesets.record_types.find(x => x.id === record_type), `Expected record type ${record_type} to exist is valueset record_types`); | ||
|
aspiringLich marked this conversation as resolved.
Outdated
|
||
| formData.append('record_type', record_type); | ||
| console.assert(state.valuesets.modalities.find(x => x.id === modality), `Expected modality ${modality} to exist in valueset modalities`); | ||
| formData.append('modality', modality); | ||
| console.log(`Record type: ${record_type}, Modality: ${modality}`); | ||
|
aspiringLich marked this conversation as resolved.
Outdated
|
||
| }; | ||
|
|
||
| let image_type = document.getElementById('image-type').value; | ||
| switch (image_type) { | ||
| // Skeletal X-ray of ankle and foot, Radiographic imaging | ||
| case 'FA': set_record_type_and_modality('1597004', 'RG'); break; | ||
| // Skeletal X-ray of wrist and hand, Radiographic imaging | ||
| case 'H': set_record_type_and_modality('39714003', 'RG'); break; | ||
| // Cephalogram, Radiographic imaging | ||
| case 'L': set_record_type_and_modality('201456002', 'RG'); break; | ||
| // Pelvis X-ray, Radiographic imaging | ||
| case 'P': set_record_type_and_modality('268425006', 'RG'); break; | ||
| // Dental model, 3D Manufacturing Modeling System | ||
| case 'SM': set_record_type_and_modality('302189007', 'M3D'); break; | ||
| case 'FM': | ||
| case 'F': | ||
| throw new Error('Image type has no match in record type codings'); | ||
|
zgypa marked this conversation as resolved.
Outdated
|
||
| default: | ||
| throw new Error(`Unexpected image type ${image_type}. This is a bug.`); | ||
|
|
||
| } | ||
| formData.append('image_type', image_type); | ||
|
|
||
| if (state.requiresServerTransform && state.transformOps.length > 0) { | ||
| formData.append('image_transform_ops', JSON.stringify(state.transformOps)); | ||
| } | ||
|
|
@@ -1154,8 +1133,6 @@ <h3 class="font-bold text-lg mb-2">Scanner Device Info</h3> | |
| state.aiFile = null; | ||
| state.requiresServerTransform = false; | ||
| state.transformOps = []; | ||
| state.aiImageTypeCode = null; | ||
| state.aiPatientOrientation = null; | ||
| document.getElementById('file-upload').value = ''; | ||
| document.getElementById('file-preview').classList.add('hidden'); | ||
| document.getElementById('scan-status').textContent = ''; | ||
|
|
@@ -1179,17 +1156,18 @@ <h3 class="font-bold text-lg mb-2">Scanner Device Info</h3> | |
|
|
||
| // Load valuesets | ||
| try { | ||
| const [recordTypes, modalities] = await Promise.all([ | ||
| const [image_types, record_types, modalities] = await Promise.all([ | ||
| fetchValueset('image_types'), | ||
| fetchValueset('record_types'), | ||
| fetchValueset('modalities') | ||
| fetchValueset('modalities'), | ||
| ]); | ||
|
|
||
| state.valuesets.record_types = recordTypes; | ||
| state.valuesets.image_types = image_types; | ||
| state.valuesets.record_types = record_types; | ||
| state.valuesets.modalities = modalities; | ||
| console.log(state.valuesets); | ||
|
|
||
| populateSelect('record-type', recordTypes); | ||
| populateSelect('modality', modalities); | ||
| populateSelect('image-type', image_types); | ||
| } catch (error) { | ||
| console.error('Failed to load valuesets:', error); | ||
| alert('Failed to load form options. Please refresh the page.'); | ||
|
|
@@ -1215,7 +1193,7 @@ <h3 class="font-bold text-lg mb-2">Scanner Device Info</h3> | |
| }); | ||
|
|
||
| // Watch form fields for changes | ||
| ['record-type', 'modality'].forEach(id => { | ||
| ['image-type'].forEach(id => { | ||
| document.getElementById(id).addEventListener('change', updateSubmitButton); | ||
| }); | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.