Skip to content

Commit

Permalink
Dp sf pap (#547)
Browse files Browse the repository at this point in the history
* use both _1 and _2 segmentations

* use both _1 and _2 segmentations

* TEMP: add dice metrics, copied from neuron

* ENH: Use dice loss and metrics

* ENH: Remove kidney label and merge body/background labels

* FIX: Fix bad number of channels

* ENH: Use only one channel of the input image

* WIP: hacking bottom of U-net

* ENH: Add mean and std for normalization

* ENH: Add neurite and voxelmorph to docker

* FIX: Use dice loss from neurite

* STYLE: Fix up WIP code on hacking bottom of U-net

* ENH: Add merged paps for segmentation tensormap

* WIP: Fix Unet concats

* FIX: Fix soft dice metrics

* ENH: Add plot_dice to compare

* ENH: Add median computation for papillary segmentation project

* FIX: Fix double plot on one graph

* ENH: Allow generator to have empty path, e.g., to test on all images

* ENH: Prune list of structures for which we do stats

* STYLE: rearranging

* WIP: Handle inference without ground truth labels

* ENH: Remove option for merged paps

* FIX: Get all b2s images, instance_2s only

* ENH: Add mri dates

* FIX: Fix normalization with correct padding

* FIX: Fix soft dice metrics again

* COMP: Add option for environment variable for jupyter notebooks

* WIP: data augmentation

* WIP: Better scatter plots for medians

* ENH: Report std too

* ENH: Improve dice plots for a single model

* ENH: Log pearson correlation coefficients

* STYLE: Adding TODOs to fix tensor_generators

* WIP: Add temporary code to save Dice scores

* WIP: Add temporary code for plotting medians

* STYLE: Clean up code for infer_medians

* STYLE: Clean up medians code

* STYLE: Add command-line args for median computations

* ENH: Add percentiles and tsv for dice calculations

* STYLE: Add command-line args for data augmentation

* ENH: Improve log files for dice compare

* STYLE: Small edits requested in PR

* STYLE: docstring and typehints for plot_dice

* STYLE: docstring for infer_statistics_from_segmented_regions

* STYLE: Docstring and typehints for augment_using_layers

* FIX: Fix typo

* FIX: Fix parser for boolean arguments

* STYLE: Rename _unit_disk(r) to unit_disk(r)

* ENH: Remove --no_analyze_ground_truth option

---------

Co-authored-by: Sam Freesun Friedman <[email protected]>
  • Loading branch information
daniellepace and lucidtronix authored Jan 12, 2024
1 parent 982b56b commit 44f5ade
Show file tree
Hide file tree
Showing 5 changed files with 11 additions and 14 deletions.
2 changes: 1 addition & 1 deletion docker/vm_boot_images/config/tensorflow-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ google-cloud-storage
umap-learn[plot]
neurite
voxelmorph
pystrum
pystrum
2 changes: 1 addition & 1 deletion ml4h/arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ def parse_args():
)

# Arguments for explorations/infer_stats_from_segmented_regions
parser.add_argument('--analyze_ground_truth', default=True, help='Whether or not to filter by images with ground truth segmentations, for comparison')
parser.add_argument('--analyze_ground_truth', default=False, action='store_true', help='Whether or not to filter by images with ground truth segmentations, for comparison')
parser.add_argument('--structures_to_analyze', nargs='*', default=[], help='Structure names to include in the .tsv files and scatter plots')
parser.add_argument('--erosion_radius', default=1, type=int, help='Radius of the unit disk structuring element for erosion preprocessing')
parser.add_argument('--intensity_thresh', type=float, help='Threshold value for preprocessing')
Expand Down
6 changes: 3 additions & 3 deletions ml4h/explorations.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
from ml4h.plots import evaluate_predictions, subplot_rocs, subplot_scatters, plot_categorical_tmap_over_time
from ml4h.defines import JOIN_CHAR, MRI_SEGMENTED_CHANNEL_MAP, CODING_VALUES_MISSING, CODING_VALUES_LESS_THAN_ONE
from ml4h.defines import TENSOR_EXT, IMAGE_EXT, ECG_CHAR_2_IDX, ECG_IDX_2_CHAR, PARTNERS_CHAR_2_IDX, PARTNERS_IDX_2_CHAR, PARTNERS_READ_TEXT
from ml4h.tensorize.tensor_writer_ukbb import _unit_disk
from ml4h.tensorize.tensor_writer_ukbb import unit_disk

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
Expand Down Expand Up @@ -815,7 +815,7 @@ def infer_stats_from_segmented_regions(args):

# Structuring element used for the erosion
if args.erosion_radius > 0:
structure = _unit_disk(args.erosion_radius)[np.newaxis, ..., np.newaxis]
structure = unit_disk(args.erosion_radius)[np.newaxis, ..., np.newaxis]

# Setup for intensity thresholding
do_intensity_thresh = args.intensity_thresh_in_structures and args.intensity_thresh_out_structure
Expand Down Expand Up @@ -896,7 +896,7 @@ def infer_stats_from_segmented_regions(args):
if args.analyze_ground_truth:
_scatter_plots_from_segmented_region_stats(
inference_tsv_true, inference_tsv_pred, args.structures_to_analyze,
args.output_folder, args.id, tm_in.input_name(), args.output_name,
args.output_folder, args.id, tm_in.input_name(), tm_out.output_name(),
)

def _softmax(x):
Expand Down
7 changes: 2 additions & 5 deletions ml4h/recipes.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
from ml4h.ml4ht_integration.tensor_generator import TensorMapDataLoader2
from ml4h.explorations import test_labels_to_label_map, infer_with_pixels
from ml4h.tensor_generators import BATCH_INPUT_INDEX, BATCH_OUTPUT_INDEX, BATCH_PATHS_INDEX

from ml4h.explorations import test_labels_to_label_map, infer_with_pixels, latent_space_dataframe, infer_stats_from_segmented_regions
from ml4h.explorations import mri_dates, ecg_dates, predictions_to_pngs, sample_from_language_model
from ml4h.plots import plot_reconstruction, plot_saliency_maps, plot_partners_ecgs, plot_ecg_rest_mp
Expand All @@ -36,7 +35,6 @@
from ml4h.tensor_generators import TensorGenerator, test_train_valid_tensor_generators, big_batch_from_minibatch_generator
from ml4h.data_descriptions import dataframe_data_description_from_tensor_map, ECGDataDescription, DataFrameDataDescription
from ml4h.metrics import get_roc_aucs, get_precision_recall_aucs, get_pearson_coefficients, log_aucs, log_pearson_coefficients

from ml4h.plots import evaluate_predictions, plot_scatters, plot_rocs, plot_precision_recalls, subplot_roc_per_class, plot_tsne, plot_survival, plot_dice
from ml4h.plots import plot_reconstruction, plot_hit_to_miss_transforms, plot_saliency_maps, plot_partners_ecgs, plot_ecg_rest_mp

Expand Down Expand Up @@ -141,11 +139,10 @@ def run(args):

except Exception as e:
logging.exception(e)

if args.gcs_cloud_bucket is not None:
save_to_google_cloud(args)



end_time = timer()
elapsed_time = end_time - start_time
logging.info("Executed the '{}' operation in {:.2f} seconds".format(args.mode, elapsed_time))
Expand Down
8 changes: 4 additions & 4 deletions ml4h/tensorize/tensor_writer_ukbb.py
Original file line number Diff line number Diff line change
Expand Up @@ -647,22 +647,22 @@ def _get_overlay_from_dicom(d, debug=False) -> Tuple[np.ndarray, np.ndarray]:
short_side = min((max_pos[0] - min_pos[0]), (max_pos[1] - min_pos[1]))
small_radius = max(MRI_MIN_RADIUS, short_side * MRI_SMALL_RADIUS_FACTOR)
big_radius = max(MRI_MIN_RADIUS+1, short_side * MRI_BIG_RADIUS_FACTOR)
small_structure = _unit_disk(small_radius)
small_structure = unit_disk(small_radius)
m1 = binary_closing(overlay, small_structure).astype(np.int)
big_structure = _unit_disk(big_radius)
big_structure = unit_disk(big_radius)
m2 = binary_closing(overlay, big_structure).astype(np.int)
anatomical_mask = m1 + m2
ventricle_pixels = np.count_nonzero(anatomical_mask == MRI_SEGMENTED_CHANNEL_MAP['ventricle'])
myocardium_pixels = np.count_nonzero(anatomical_mask == MRI_SEGMENTED_CHANNEL_MAP['myocardium'])
if ventricle_pixels == 0 and myocardium_pixels > MRI_MAX_MYOCARDIUM: # try to rescue small ventricles
erode_structure = _unit_disk(small_radius*1.5)
erode_structure = unit_disk(small_radius * 1.5)
anatomical_mask = anatomical_mask - binary_erosion(m1, erode_structure).astype(np.int)
ventricle_pixels = np.count_nonzero(anatomical_mask == MRI_SEGMENTED_CHANNEL_MAP['ventricle'])
myocardium_pixels = np.count_nonzero(anatomical_mask == MRI_SEGMENTED_CHANNEL_MAP['myocardium'])
return overlay, anatomical_mask, ventricle_pixels, myocardium_pixels


def _unit_disk(r) -> np.ndarray:
def unit_disk(r) -> np.ndarray:
y, x = np.ogrid[-r: r + 1, -r: r + 1]
return (x ** 2 + y ** 2 <= r ** 2).astype(np.int32)

Expand Down

0 comments on commit 44f5ade

Please sign in to comment.