cvips
commited on
Commit
·
bdb6d79
1
Parent(s):
7978786
biomedparse+biomedllama_3b_multimodal
Browse files
app.py
CHANGED
@@ -208,64 +208,6 @@ def extract_modality_and_prompts(llm_output):
|
|
208 |
|
209 |
return detected_modality, relevant_prompts
|
210 |
|
211 |
-
def extract_modality_from_llm(llm_output):
|
212 |
-
"""Extract modality from LLM output and map it to BIOMEDPARSE_MODES"""
|
213 |
-
llm_output = llm_output.lower()
|
214 |
-
|
215 |
-
modality_keywords = {
|
216 |
-
'ct': {
|
217 |
-
'abdomen': 'CT-Abdomen',
|
218 |
-
'chest': 'CT-Chest',
|
219 |
-
'liver': 'CT-Liver'
|
220 |
-
},
|
221 |
-
'mri': {
|
222 |
-
'abdomen': 'MRI-Abdomen',
|
223 |
-
'cardiac': 'MRI-Cardiac',
|
224 |
-
'heart': 'MRI-Cardiac',
|
225 |
-
'flair': 'MRI-FLAIR-Brain',
|
226 |
-
't1': 'MRI-T1-Gd-Brain',
|
227 |
-
'contrast': 'MRI-T1-Gd-Brain',
|
228 |
-
'brain': 'MRI-FLAIR-Brain'
|
229 |
-
},
|
230 |
-
'x-ray': {'chest': 'X-Ray-Chest'},
|
231 |
-
'ultrasound': {'cardiac': 'Ultrasound-Cardiac', 'heart': 'Ultrasound-Cardiac'},
|
232 |
-
'endoscopy': {'': 'Endoscopy'},
|
233 |
-
'fundus': {'': 'Fundus'},
|
234 |
-
'dermoscopy': {'': 'Dermoscopy'},
|
235 |
-
'oct': {'': 'OCT'},
|
236 |
-
'pathology': {'': 'Pathology'}
|
237 |
-
}
|
238 |
-
|
239 |
-
for modality, subtypes in modality_keywords.items():
|
240 |
-
if modality in llm_output:
|
241 |
-
for keyword, specific_modality in subtypes.items():
|
242 |
-
if not keyword or keyword in llm_output:
|
243 |
-
return specific_modality
|
244 |
-
return next(iter(subtypes.values()))
|
245 |
-
|
246 |
-
return None
|
247 |
-
|
248 |
-
def extract_clinical_findings(llm_output, modality):
|
249 |
-
"""Extract relevant clinical findings that match available anatomical sites in BIOMEDPARSE_MODES"""
|
250 |
-
available_sites = BIOMEDPARSE_MODES.get(modality, [])
|
251 |
-
findings = []
|
252 |
-
|
253 |
-
# Convert sites to lowercase for case-insensitive matching
|
254 |
-
sites_lower = {site.lower(): site for site in available_sites}
|
255 |
-
|
256 |
-
# Look for each available site in the LLM output
|
257 |
-
for site_lower, original_site in sites_lower.items():
|
258 |
-
if site_lower in llm_output.lower():
|
259 |
-
findings.append(original_site)
|
260 |
-
|
261 |
-
# Add additional findings from MODALITY_PROMPTS if available
|
262 |
-
if modality in MODALITY_PROMPTS:
|
263 |
-
for prompt in MODALITY_PROMPTS[modality]:
|
264 |
-
if prompt.lower() in llm_output.lower() and prompt not in findings:
|
265 |
-
findings.append(prompt)
|
266 |
-
|
267 |
-
return findings
|
268 |
-
|
269 |
def on_mode_dropdown_change(selected_mode):
|
270 |
if selected_mode in IMAGE_INFERENCE_MODES:
|
271 |
return [
|
@@ -376,49 +318,49 @@ def process_image(image_path, user_prompt, modality=None):
|
|
376 |
detected_modality = "X-Ray-Chest" # Fallback modality
|
377 |
relevant_prompts = MODALITY_PROMPTS["X-Ray-Chest"]
|
378 |
|
379 |
-
results = []
|
380 |
-
analysis_results = []
|
381 |
-
colors = [(255,0,0), (0,255,0), (0,0,255), (255,255,0), (255,0,255)]
|
382 |
|
383 |
-
# Add color mapping to analysis with more natural language
|
384 |
-
color_descriptions = []
|
385 |
-
for idx, prompt in enumerate(relevant_prompts):
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
|
391 |
-
for idx, prompt in enumerate(relevant_prompts):
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
|
414 |
-
if not results:
|
415 |
-
|
416 |
|
417 |
detailed_analysis = ""
|
418 |
if llm_model and llm_tokenizer:
|
419 |
try:
|
420 |
# Add color legend with more natural language
|
421 |
-
detailed_analysis += "\n\n As shown in the images outputs details:\n \n" + "\n".join(color_descriptions)
|
422 |
|
423 |
analysis_prompt = f"Give the modality, organ, analysis, abnormalities (if any), treatment (if abnormalities are present) for this image. Focus more on the user question. which is: {user_prompt}"
|
424 |
msgs = [{'role': 'user', 'content': [pil_image, analysis_prompt]}]
|
@@ -434,6 +376,44 @@ def process_image(image_path, user_prompt, modality=None):
|
|
434 |
detailed_analysis += new_text
|
435 |
|
436 |
# Add segmentation details in a more natural way
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
437 |
detailed_analysis += "\n\nIn the segmentation analysis:"
|
438 |
if color_descriptions:
|
439 |
detailed_analysis += " " + " ".join(color_descriptions) + "."
|
|
|
208 |
|
209 |
return detected_modality, relevant_prompts
|
210 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
211 |
def on_mode_dropdown_change(selected_mode):
|
212 |
if selected_mode in IMAGE_INFERENCE_MODES:
|
213 |
return [
|
|
|
318 |
detected_modality = "X-Ray-Chest" # Fallback modality
|
319 |
relevant_prompts = MODALITY_PROMPTS["X-Ray-Chest"]
|
320 |
|
321 |
+
# results = []
|
322 |
+
# analysis_results = []
|
323 |
+
# colors = [(255,0,0), (0,255,0), (0,0,255), (255,255,0), (255,0,255)]
|
324 |
|
325 |
+
# # Add color mapping to analysis with more natural language
|
326 |
+
# color_descriptions = []
|
327 |
+
# for idx, prompt in enumerate(relevant_prompts):
|
328 |
+
# color = colors[idx % len(colors)]
|
329 |
+
# color_name = {(255,0,0): "red", (0,255,0): "green", (0,0,255): "blue",
|
330 |
+
# (255,255,0): "yellow", (255,0,255): "magenta"}[color]
|
331 |
+
# color_descriptions.append(f"The {prompt} is highlighted in {color_name} color")
|
332 |
|
333 |
+
# for idx, prompt in enumerate(relevant_prompts):
|
334 |
+
# try:
|
335 |
+
# mask_list = interactive_infer_image(model, pil_image, [prompt])
|
336 |
+
# if mask_list is None or len(mask_list) == 0:
|
337 |
+
# analysis_results.append(f"No mask generated for '{prompt}'")
|
338 |
+
# continue
|
339 |
|
340 |
+
# pred_mask = mask_list[0]
|
341 |
+
# # Check if mask is valid using numpy's any() function
|
342 |
+
# if pred_mask is None or not np.any(pred_mask):
|
343 |
+
# analysis_results.append(f"Empty mask generated for '{prompt}'")
|
344 |
+
# continue
|
345 |
|
346 |
+
# overlay_image = image.copy()
|
347 |
+
# color = colors[idx % len(colors)]
|
348 |
+
# mask_indices = pred_mask > 0.5
|
349 |
+
# if np.any(mask_indices): # Use np.any() for boolean array check
|
350 |
+
# overlay_image[mask_indices] = color
|
351 |
+
# results.append(overlay_image)
|
352 |
+
# except Exception as e:
|
353 |
+
# print(f"Error processing finding {prompt}: {str(e)}")
|
354 |
+
# analysis_results.append(f"Failed to process '{prompt}': {str(e)}")
|
355 |
|
356 |
+
# if not results:
|
357 |
+
# results = [image] # Return original image if no overlays were created
|
358 |
|
359 |
detailed_analysis = ""
|
360 |
if llm_model and llm_tokenizer:
|
361 |
try:
|
362 |
# Add color legend with more natural language
|
363 |
+
# detailed_analysis += "\n\n As shown in the images outputs details:\n \n" + "\n".join(color_descriptions)
|
364 |
|
365 |
analysis_prompt = f"Give the modality, organ, analysis, abnormalities (if any), treatment (if abnormalities are present) for this image. Focus more on the user question. which is: {user_prompt}"
|
366 |
msgs = [{'role': 'user', 'content': [pil_image, analysis_prompt]}]
|
|
|
376 |
detailed_analysis += new_text
|
377 |
|
378 |
# Add segmentation details in a more natural way
|
379 |
+
results = []
|
380 |
+
analysis_results = []
|
381 |
+
colors = [(255,0,0), (0,255,0), (0,0,255), (255,255,0), (255,0,255)]
|
382 |
+
|
383 |
+
# Add color mapping to analysis with more natural language
|
384 |
+
color_descriptions = []
|
385 |
+
for idx, prompt in enumerate(relevant_prompts):
|
386 |
+
if prompt in detailed_analysis.lower():
|
387 |
+
color = colors[idx % len(colors)]
|
388 |
+
color_name = {(255,0,0): "red", (0,255,0): "green", (0,0,255): "blue",
|
389 |
+
(255,255,0): "yellow", (255,0,255): "magenta"}[color]
|
390 |
+
color_descriptions.append(f"The {prompt} is highlighted in {color_name} color")
|
391 |
+
|
392 |
+
for idx, prompt in enumerate(relevant_prompts):
|
393 |
+
try:
|
394 |
+
mask_list = interactive_infer_image(model, pil_image, [prompt])
|
395 |
+
if mask_list is None or len(mask_list) == 0:
|
396 |
+
analysis_results.append(f"No mask generated for '{prompt}'")
|
397 |
+
continue
|
398 |
+
|
399 |
+
pred_mask = mask_list[0]
|
400 |
+
# Check if mask is valid using numpy's any() function
|
401 |
+
if pred_mask is None or not np.any(pred_mask):
|
402 |
+
analysis_results.append(f"Empty mask generated for '{prompt}'")
|
403 |
+
continue
|
404 |
+
|
405 |
+
overlay_image = image.copy()
|
406 |
+
color = colors[idx % len(colors)]
|
407 |
+
mask_indices = pred_mask > 0.5
|
408 |
+
if np.any(mask_indices): # Use np.any() for boolean array check
|
409 |
+
overlay_image[mask_indices] = color
|
410 |
+
results.append(overlay_image)
|
411 |
+
except Exception as e:
|
412 |
+
print(f"Error processing finding {prompt}: {str(e)}")
|
413 |
+
analysis_results.append(f"Failed to process '{prompt}': {str(e)}")
|
414 |
+
|
415 |
+
if not results:
|
416 |
+
results = [image] # Return original image if no overlays were created
|
417 |
detailed_analysis += "\n\nIn the segmentation analysis:"
|
418 |
if color_descriptions:
|
419 |
detailed_analysis += " " + " ".join(color_descriptions) + "."
|