def main():
    # ensure consistent preference settings
    Prefs.blackBackground = False

    # get locations for previous and new outputs
    params = Parameters()
    params.loadLastParams()
    output_folder_old, output_folder = mbio.rerun_location_chooser(
        params.input_image_path)
    params.loadParametersFromJson(
        os.path.join(output_folder_old, 'parameters used.json'))
    params.setOutputPath(output_folder)

    # present user with the familiar setup UI, with options that don't make sense/aren't yet implemented disabled
    params = mbui.analysis_parameters_gui(rerun_analysis=True, params=params)

    # get original image file (for overlays etc.)
    if not os.path.isfile(params.input_image_path):
        mbui.warning_dialog([
            "The original data can't be found at the location specified in saved parameters. ",
            "(Possibly something as simple as a change in network drive mapping has occurred)",
            "Please specify the location of the original image file..."
        ])
        params.setInputImagePath(
            mbio.input_file_location_chooser(params.output_path))

    import_opts, params = mbui.choose_series(params.input_image_path, params)
    imps = bf.openImagePlus(import_opts)
    imp = imps[0]

    if imp.getNSlices() > 1:
        mbui.warning_dialog([
            "More than one Z plane detected.",
            "I will do a maximum projection before proceeding", "Continue?"
        ])
        imp = ZProjector.run(imp, "max all")

    params = mbio.get_metadata(params)
    params.setCurvatureLengthUm(
        round(params.curvature_length_um / params.pixel_physical_size) *
        params.pixel_physical_size)
    params.persistParameters()
    IJ.run(imp, "Set Scale...", "distance=0 known=0 pixel=1 unit=pixel")
    imp.show()
    if imp.getNChannels() > 1:
        imp.setPosition(params.membrane_channel_number, 1, 1)
    mbui.autoset_zoom(imp)
    IJ.run("Enhance Contrast", "saturated=0.35")

    # prompt user to select ROI
    original_imp = Duplicator().run(imp)
    _, crop_params = mbui.crop_to_ROI(imp, params)
    imp.show()

    if crop_params is not None:
        params.perform_spatial_crop = True
        mbui.autoset_zoom(imp)
        imp.updateAndDraw()
        review_crop = mb.check_cropping(output_folder_old, params)
        keep_crop = not review_crop
        if review_crop:
            keep_crop = mbui.crop_review()
        if not keep_crop:
            imp.changes = False
            imp.close()
            imp = original_imp
        else:
            original_imp.close()
    else:
        original_imp.close()

    # prompt user to do time cropping
    imp, start_end_tuple = mbui.time_crop(imp, params)
    params.setTimeCropStartEnd(start_end_tuple)

    # import edges
    membrane_edges = mbio.load_qcd_edges2(
        os.path.join(output_folder_old, "user_defined_edges.zip"))
    mbio.save_qcd_edges2(membrane_edges, params.output_path)

    calculated_objects = CalculatedObjects()
    calculated_objects.membrane_edges = membrane_edges
    if params.time_crop_start_end[0] is not None:
        calculated_objects.timelist = [
            idx * params.frame_interval
            for idx in range(params.time_crop_start_end[0],
                             params.time_crop_start_end[1] + 1)
        ]
    else:
        calculated_objects.timelist = [
            idx * params.frame_interval for idx in range(imp.getNFrames())
        ]

    split_channels = mbfs.split_image_plus(imp, params)
    membrane_channel_imp = split_channels[0]
    actin_channel_imp = split_channels[1]
    segmentation_channel_imp = None
    if params.photobleaching_correction:
        if os.path.isfile(
                os.path.join(output_folder_old, 'binary_membrane_stack.tif')):
            segmentation_binary_path = os.path.join(
                output_folder_old, 'binary_membrane_stack.tif')
            segmentation_channel_imp = IJ.openImage(segmentation_binary_path)
        else:
            segmentation_channel_imp = split_channels[2]
            segmentation_channel_imp = mb.make_and_clean_binary(
                segmentation_channel_imp, params.threshold_method)
        split_channels[2] = segmentation_channel_imp

    calculated_objects = mbfs.calculate_outputs(params, calculated_objects,
                                                split_channels)

    # output colormapped images and kymographs
    fig_imp_list = mbfs.generate_and_save_figures(imp, calculated_objects,
                                                  params, membrane_channel_imp,
                                                  segmentation_channel_imp)
    mbfs.save_csvs(calculated_objects, params)

    params.saveParametersToJson(
        os.path.join(params.output_path, "parameters used.json"))
    imp.changes = False
    IJ.setTool("zoom")
    if params.close_on_completion:
        for fig_imp in fig_imp_list:
            fig_imp.close()
            imp.close()

    return
Beispiel #2
0
def generate_edges(imp, params, calculated_objects, repeat_fraction=1):
    """generate edges automatically, then clean up with user step if necessary"""
    # binarise/segment
    extra_prompt_str = ""
    if params.inner_outer_comparison:
        if repeat_fraction == 1:
            extra_prompt_str = " OUTER"
            params.setOutputPath(
                os.path.join(os.path.dirname(params.output_path), "outer"))
            os.mkdir(params.output_path)
        else:
            extra_prompt_str = " INNER"
            params.setOutputPath(os.path.join(params.output_path, "inner"))
            os.mkdir(params.output_path)
    anchors = mbui.prompt_for_points(
        imp, "Select channel + extrema",
        "Select the membrane-label channel, and position \n" +
        "exactly TWO points at extremes of" + extra_prompt_str + " membrane",
        2)
    midpoint = mbui.prompt_for_points(
        imp, "Choose midpoint",
        "Now select a point halfway between the extremes, distant from \n the membrane in the direction of bleb formation. ",
        1)
    membrane_channel = imp.getChannel()
    params.setMembraneChannelNumber(membrane_channel)
    params.persistParameters()
    params.setManualAnchorMidpoint(midpoint)
    anchors = mb.order_anchors(anchors, midpoint)
    params.setManualAnchorPositions(anchors)
    split_channels = split_image_plus(imp, params)
    membrane_test_channel_imp = Duplicator().run(split_channels[0])
    segmentation_channel_imp = split_channels[-1]

    # perform binary manipulations
    segmentation_channel_imp = mb.make_and_clean_binary(
        segmentation_channel_imp, params.threshold_method)

    # generate edge - this needs to be looped over slices
    membrane_edges = []
    alternate_edges = []
    fixed_anchors_list = []
    previous_anchors = []
    for fridx in range(0, imp.getNFrames()):
        imp.setPosition(membrane_channel, 1, fridx + 1)
        segmentation_channel_imp.setPosition(fridx + 1)
        # 	fix anchors:
        IJ.run(segmentation_channel_imp, "Create Selection", "")
        roi = segmentation_channel_imp.getRoi()
        fixed_anchors = mb.fix_anchors_to_membrane(anchors, roi, params)
        fixed_midpoint = midpoint[0]
        # evolve anchors...
        if not params.inner_outer_comparison and not params.constrain_anchors:
            previous_anchors, anchors = mb.evolve_anchors(
                previous_anchors, fixed_anchors)
        # identify which side of the segmented roi to use and perform interpolation/smoothing:
        membrane_edge, alternate_edge = mb.get_membrane_edge(
            roi, fixed_anchors, fixed_midpoint)
        fixed_anchors = mb.order_anchors(fixed_anchors, midpoint)
        fixed_anchors_list.append(fixed_anchors)
        membrane_edge = mb.check_edge_order(fixed_anchors, membrane_edge)
        alternate_edge = mb.check_edge_order(fixed_anchors, alternate_edge)
        imp.show()
        imp.setRoi(membrane_edge)
        IJ.run(imp, "Interpolate", "interval=1.0 smooth adjust")
        IJ.run(imp, "Fit Spline", "")
        #membrane_edge = mb.selectionInterpolateAndFitSpline(membrane_edge);
        membrane_edge = imp.getRoi()
        imp.setRoi(alternate_edge)
        IJ.run(imp, "Interpolate", "interval=1.0 smooth adjust")
        IJ.run(imp, "Fit Spline", "")
        alternate_edge = imp.getRoi()
        #alternate_edge = mb.selectionInterpolateAndFitSpline(alternate_edge);
        membrane_edges.append(membrane_edge)
        alternate_edges.append(alternate_edge)

    # perform user QC before saving anything
    if params.perform_user_qc:
        imp.hide()
        if imp.getNFrames() > 1:
            membrane_edges, fixed_anchors_list = mbui.perform_user_qc(
                membrane_test_channel_imp, membrane_edges, alternate_edges,
                fixed_anchors_list, params)
        else:
            membrane_edges, fixed_anchors_list = mbui.perform_user_qc(
                imp, membrane_edges, alternate_edges, fixed_anchors_list,
                params)
        imp.show()
    else:
        mbio.save_qcd_edges2(membrane_edges, params.output_path)

    calculated_objects.membrane_edges = membrane_edges
    calculated_objects.fixed_anchors_list = fixed_anchors_list

    return calculated_objects, params, split_channels
def perform_user_qc(in_imp, edges, alt_edges, fixed_anchors_list, params):
	"""allow the user to intervene to fix erroneously identified membrane edges"""
	n_frames = in_imp.getNFrames();
	n_channels = in_imp.getNChannels();
	output_folder = params.output_path;
	current_edges = edges;
	rgbstack = ImageStack(in_imp.getWidth(), in_imp.getHeight());
	if n_frames > 1:
		for tidx in range(n_frames): 
			in_imp.setT(tidx+1);
			ip = in_imp.getProcessor();
			rgbip = ip.convertToRGB();
			rgbstack.addSlice(rgbip);
	else:
		for cidx in range(n_channels):
			in_imp.setC(cidx+1);
			ip = in_imp.getProcessor();
			rgbip = ip.convertToRGB();
			rgbstack.addSlice(rgbip);
	imp = ImagePlus(("RGB " + in_imp.getTitle()), rgbstack);
	IJ.run("Colors...", "foreground=red background=white selection=yellow");
	for tidx in range(imp.getNSlices()):
		imp.setSlice(tidx+1);
		for anchor in params.manual_anchor_positions:
			imp.setRoi(PointRoi(anchor[0], anchor[1]));
			IJ.run(imp, "Draw", "slice");
	imp.show();
	autoset_zoom(imp);
	imp.setPosition(1);
	imp.setRoi(current_edges[0]);
	if n_frames > 1:
		listener = UpdateRoiImageListener(current_edges);
		imp.addImageListener(listener);
	IJ.setTool("freeline");
	do_flip = True;
	while do_flip:
		dialog = NonBlockingGenericDialog("User quality control");
		dialog.enableYesNoCancel("Continue", "Flip all edges");
		dialog.setCancelLabel("Cancel analysis");
		dialog.addMessage("Please redraw the membrane edges as necessary, \n" + 
						"making sure to draw beyond anchor points at either end...\n" + 
						"Click OK when done. ");
		p = Panel();
		but = Button("Flip this edge");
		al = Listener(edges, alt_edges, imp);
		but.addActionListener(al);
		p.add(but);
		dialog.addPanel(p);
		dialog.showDialog();
		if dialog.wasCanceled():
			raise KeyboardInterrupt("Run canceled");
		elif dialog.wasOKed():
			do_flip = False;
		else:
			print("flip edges");
			do_flip = True;
			if n_frames > 1:
				imp.removeImageListener(listener);
			current_edges = alt_edges if (current_edges == edges) else edges;
			imp.setPosition(1);
			imp.setRoi(current_edges[0]);
			if n_frames > 1:
				listener = UpdateRoiImageListener(current_edges);
				imp.addImageListener(listener);

	last_roi = imp.getRoi();
	if n_frames > 1:
		qcd_edges = listener.getRoiList();
		if imp.getNFrames() > imp.getNSlices():
			qcd_edges[imp.getT() - 1] = last_roi;
		else:
			qcd_edges[imp.getZ() - 1] = last_roi;
		imp.removeImageListener(listener);
	else:
		qcd_edges = [last_roi];
	mbio.save_qcd_edges2(qcd_edges, output_folder);
	# next four lines are a quick and dirty hack...
	if n_frames > 1:
		nframes = imp.getNFrames() if imp.getNFrames()>imp.getNSlices() else imp.getNSlices();
	else:
		nframes = n_frames;
	for fridx in range(0, nframes):
		if (qcd_edges[fridx].getType()==Roi.FREELINE) or (qcd_edges[fridx].getType()==Roi.POLYLINE):
			if (fridx == 0) or params.constrain_anchors:
				anchors = params.manual_anchor_positions;
			else:
				anchors = fixed_anchors_list[fridx - 1];
			fixed_anchors = mb.fix_anchors_to_membrane(anchors, qcd_edges[fridx], params);
			fixed_anchors = mb.order_anchors(fixed_anchors, params.manual_anchor_midpoint);
			fixed_anchors_list[fridx] = fixed_anchors;
			poly =  qcd_edges[fridx].getInterpolatedPolygon(0.25, False);
			polypoints = [(x,y) for x,y in zip(poly.xpoints, poly.ypoints)];
			idx = [polypoints.index(fixed_anchors[0]), polypoints.index(fixed_anchors[1])];
			idx.sort();
			polypoints = polypoints[idx[0]:idx[1]];
			newedge = PolygonRoi([x for (x,y) in polypoints], 
									[y for (x,y) in polypoints], 
									Roi.POLYLINE);
			newedge = mb.check_edge_order(anchors, newedge);
			imp.setPosition(fridx + 1);
			imp.setRoi(newedge);
			IJ.run(imp, "Interpolate", "interval=1.0 smooth adjust");
			IJ.run(imp, "Fit Spline", "");
			qcd_edges[fridx] = imp.getRoi();
	mbio.save_qcd_edges2(qcd_edges, output_folder);
	imp.changes = False;
	imp.close();
	return qcd_edges, fixed_anchors_list;
Beispiel #4
0
def calculate_outputs(params,
                      calculated_objects,
                      split_channels,
                      inner_outer_intensity_data=None,
                      repeat_fraction=1):
    """generate curvatures, lengths, areas etc."""
    membrane_channel_imp = split_channels[0]
    actin_channel_imp = split_channels[1]
    segmentation_channel_imp = split_channels[2]
    # do calculations independent of source of edges
    actin_profiles = []
    curvature_profiles = []
    lengths_areas_and_arearois = [
        mb.bleb_area(medge, params.manual_anchor_midpoint[0])
        for medge in calculated_objects.membrane_edges
    ]
    mb_lengths = [
        laaroi[0] * params.pixel_physical_size
        for laaroi in lengths_areas_and_arearois
    ]
    full_membrane_lengths = [
        params.pixel_physical_size * edge.getLength()
        for edge in calculated_objects.membrane_edges
    ]
    euclidean_membrane_lengths = [
        params.pixel_physical_size * mb.vector_length(
            (edge.getPolygon().xpoints[0], edge.getPolygon().ypoints[0]),
            (edge.getPolygon().xpoints[-1], edge.getPolygon().ypoints[-1]))
        for edge in calculated_objects.membrane_edges
    ]
    mb_areas = [
        laaroi[1] * math.pow(params.pixel_physical_size, 2)
        for laaroi in lengths_areas_and_arearois
    ]
    mb_area_rois = [laaroi[2] for laaroi in lengths_areas_and_arearois]
    # save membrane channel with original anchors, fixed anchors and membrane edge for assessment of performance
    mbfig.save_membrane_edge_image(membrane_channel_imp,
                                   calculated_objects.fixed_anchors_list,
                                   calculated_objects.membrane_edges,
                                   mb_area_rois, params)

    # perform analysis of background regions
    bg_rois = mb.generate_background_rois(None,
                                          params,
                                          calculated_objects.membrane_edges,
                                          threshold_method='MinError',
                                          membrane_imp=membrane_channel_imp)
    # resegment, allowing more conservative guess at bg region, or...
    #bg_rois = mb.generate_background_rois(segmentation_channel_imp, params, calculated_objects.membrane_edges); # use existing segmentation
    # do qc
    if params.qc_background_rois:
        bg_rois = mbui.qc_background_regions(actin_channel_imp, bg_rois)
    mbio.save_qcd_edges2(bg_rois, params.output_path, "background regions.zip")
    calculated_objects.background_sd_profile = mb.get_stddevs_by_frame_and_region(
        actin_channel_imp, bg_rois)

    t0_actin_mean = None
    for fridx in range(membrane_channel_imp.getNFrames()):
        # generate curvature - this needs to be looped over slices
        membrane_edge = calculated_objects.membrane_edges[fridx]
        curv_profile = mb.calculate_curvature_profile(membrane_edge, params)
        curvature_profiles.append(curv_profile)

        # generate actin-channel line profile if actin channel present
        if actin_channel_imp is None:
            actin_channel_imp = Duplicator().run(membrane_channel_imp)
        actin_channel_imp.setPosition(fridx + 1)
        actin_channel_imp, t0_actin_mean = mb.apply_photobleach_correction_framewise(
            params,
            actin_channel_imp,
            segmentation_channel_imp,
            t0_value=t0_actin_mean)
        actin_profile = mb.maximum_line_profile(
            actin_channel_imp, membrane_edge,
            int(
                round(params.intensity_profile_width_um /
                      params.pixel_physical_size)))
        actin_profiles.append(actin_profile)

        if params.inner_outer_comparison:
            mean_intensity = float(sum([a for (
                (x, y), a) in actin_profile])) / len(actin_profile)
            calculated_objects.inner_outer_data.outer_means.append(
                mean_intensity
            ) if repeat_fraction == 1 else calculated_objects.inner_outer_data.inner_means.append(
                mean_intensity)
            sd = math.sqrt(
                sum((x - mean_intensity)**2
                    for ((x, y), a) in actin_profile) / len(actin_profile))
            calculated_objects.inner_outer_data.outer_sds.append(
                sd
            ) if repeat_fraction == 1 else calculated_objects.inner_outer_data.inner_sds.append(
                sd)

    calculated_objects.curvature_profiles = curvature_profiles
    calculated_objects.actin_profiles = actin_profiles
    calculated_objects.bleb_perimeter_lengths = mb_lengths
    calculated_objects.bleb_areas = mb_areas
    calculated_objects.full_membrane_lengths = full_membrane_lengths
    calculated_objects.euclidean_membrane_lengths = euclidean_membrane_lengths
    params.setPhysicalCurvatureUnit(params.pixel_unit + u'\u02C9' + u'\u00B9')

    return calculated_objects