def run():
    global pmWin
    global imgData
    helpText = "This is Point Marker, " + \
               "a program for marking points in images.\n\n" + \
               ">> Press OK to Select a file for storing points infomation.\n"+\
               ">> TIF-Images within the same directory will be auto-loaded."
    MessageDialog(IJ.getInstance(),"Point Marker Guide", helpText)

    fileChooser = OpenDialog("Point Marker: Choose working directory and file")
    outfilePath = fileChooser.getPath()
    imgDir = fileChooser.getDirectory()
    if not imgDir:  return
    imgPaths = []
    if imgDir:
        for root, directories, filenames in os.walk(imgDir):
            for filename in filenames:
                if not filename.endswith(".tif"):
                    continue
                imgPaths.append(os.path.join(root, filename))

    pointsTable1 = readPoints(outfilePath)

    imgData = PointMarkerData(imgPaths, outfilePath, pointsTable1)

    IJ.setTool("multipoint")
    PointRoi.setDefaultSize(3)

    pmWin = PointMarkerWin(imgData)
    pmWin.win.setLocation(IJ.getInstance().getLocation())
    prepareNewImage(imgData)
def getOptions():
    global listener, xlist, ylist, zlist, manager
    gd = GenericDialog("Target Selection")
    gd.addChoice('type', ['point', 'circle', 'spiral'], 'point')
    gd.addNumericField("                power (%)", 85, 0)
    gd.addNumericField("                duration (ms)", 1, 0)
    gd.addNumericField("                radius(circle/spiral)", 5, 0)
    gd.addNumericField("                # revolutions (circle/spiral)", 3, 0)
    gd.addNumericField(
        "                add CAMERA_TRIGGER after every (entries)", 1, 0)
    gd.addNumericField("                Prewait between entries (ms)", 5000, 0)
    gd.addNumericField("                Z-start of stack (um)", 0, 0)
    gd.addNumericField("                Z-step of stack (um)", 5, 0)
    gd.addMessage('Press ENTER to save\n')
    gd.addMessage('Press ESC to restart\n')
    gd.showDialog()
    profileType = gd.getNextChoice()
    power = gd.getNextNumber()
    duration = gd.getNextNumber()
    r = gd.getNextNumber()
    Nturns = gd.getNextNumber()
    camTriggerEvery = gd.getNextNumber()
    prewait = gd.getNextNumber()
    zStart = gd.getNextNumber()
    zStep = gd.getNextNumber()
    if gd.wasCanceled():
        IJ.setTool(Toolbar.RECTANGLE)
        return
    else:
        return r, power, profileType, duration, Nturns, camTriggerEvery, zStart, zStep, prewait
def run():
    global pmWin
    global imgData
    helpText = "This is Point Marker, " + \
               "a program for marking points in images.\n\n" + \
               ">> Press OK to Select a file for storing points infomation.\n"+\
               ">> TIF-Images within the same directory will be auto-loaded."
    MessageDialog(IJ.getInstance(), "Point Marker Guide", helpText)

    fileChooser = OpenDialog("Point Marker: Choose working directory and file")
    outfilePath = fileChooser.getPath()
    imgDir = fileChooser.getDirectory()
    if not imgDir: return
    imgPaths = []
    if imgDir:
        for root, directories, filenames in os.walk(imgDir):
            for filename in filenames:
                if not filename.endswith(".tif"):
                    continue
                imgPaths.append(os.path.join(root, filename))

    pointsTable1 = readPoints(outfilePath)

    imgData = PointMarkerData(imgPaths, outfilePath, pointsTable1)

    IJ.setTool("multipoint")
    PointRoi.setDefaultSize(3)

    pmWin = PointMarkerWin(imgData)
    pmWin.win.setLocation(IJ.getInstance().getLocation())
    prepareNewImage(imgData)
Exemple #4
0
def twist_and_unwrap(imp):
    """from the output of angular projection, define an axis along which to unzip the vessel and return this unzipped image"""
    tile_imp = make_tiled_imp(imp)
    tile_imp.show()
    IJ.setTool("freeline")
    WaitForUserDialog(
        "Input required...",
        "Please draw the line down which unwrapping should occur...").show()
    roi = tile_imp.getRoi()
    if roi is None:
        raise ValueError
    unwrap_poly = roi.getPolygon()
    unwrap_poly_xs = [x for x in unwrap_poly.xpoints]
    unwrap_poly_ys = [y for y in unwrap_poly.ypoints]
    # extend to the top and bottom of the image:
    unwrap_poly_xs.insert(0, unwrap_poly_xs[0])
    unwrap_poly_xs.append(unwrap_poly_xs[-1])
    if unwrap_poly_ys[0] < unwrap_poly_ys[-1]:
        unwrap_poly_ys.insert(0, 1)
        unwrap_poly_ys.append(imp.getHeight())
    else:
        unwrap_poly_ys.insert(0, imp.getHeight())
        unwrap_poly_ys.append(1)
    unwrap_axis = [(x, y) for (x, y) in zip(unwrap_poly_xs, unwrap_poly_ys)]

    unwrapped_projection_imp = do_unwrap(tile_imp,
                                         unwrap_axis,
                                         imp_title=imp.getTitle())
    return unwrapped_projection_imp, unwrap_axis
def perform_cropping(imp, info, output_folder, default_path):
    imp.show()
    imp.setC(info.get_mosaic_labeled_ch())
    IJ.run("Enhance Contrast", "saturated=0.35")
    zcrop_imp, z_lims = z_crop(imp)
    info.set_z_crop_frames(z_lims)
    info.set_mosaic_labeled_ch(imp.getC())
    IJ.setTool("rect")
    zcrop_imp.hide()
    imp2 = ZProjector.run(zcrop_imp, "max")
    imp2.show()
    imp2.setC(info.get_mosaic_labeled_ch())
    crop_roi = None
    while crop_roi is None:
        WaitForUserDialog("Select XY region to crop...").show()
        crop_roi = imp2.getRoi()
    if crop_roi.getType():
        info.set_xy_crop_rect(
            str([(x, y) for x, y in zip(crop_roi.getPolygon().xpoints,
                                        crop_roi.getPolygon().ypoints)]))
    else:
        info.set_xy_crop_rect(crop_roi.getBounds().toString())
    imp2.close()
    zcrop_imp.show()
    zcrop_imp.setRoi(crop_roi)
    IJ.run("Crop", "")
    if crop_roi.getType():
        IJ.run(zcrop_imp, "Make Inverse", "")
        inv_roi = zcrop_imp.getRoi()
        IJ.run(zcrop_imp, "Set...", "value=0 stack")
        IJ.run(zcrop_imp, "Make Inverse", "")


#	zcrop_imp = z_crop_finetune(zcrop_imp, info);
    return imp, zcrop_imp, info, info.get_input_file_path()
def crop_to_ROI(imp, params):
	"""prompt user to select ROI for subsequent analysis"""
	roi = None;
	if params.perform_spatial_crop:
		if params.spatial_crop is not None:
			roi = params.parse_roistr_to_roi();
			imp.setRoi(roi);
		else:
			IJ.setTool("rect");
			MyWaitForUser("Crop", "If desired, select an area ROI to crop to...");
			roi = imp.getRoi();
	crop_params = None;
	original_imp = Duplicator().run(imp);
	if roi is not None:
		if not roi.isArea():
			raise TypeError("selected ROI should be an area");
		if roi.getType():
			crop_params = str([(x, y) for x, y in 
							zip(roi.getPolygon().xpoints, roi.getPolygon().ypoints)]);
			IJ.run(imp, "Make Inverse", "");
			roi = imp.getRoi();
			fill_val = mb.calculate_percentile(imp, roi, 25);
			IJ.run(imp, "Set...", "value=" + str(round(fill_val)) + " stack");
			IJ.run(imp, "Make Inverse", "");
		else:
			crop_params = roi.getBounds().toString();
		IJ.run(imp, "Crop", "");
		imp.killRoi();
		params.setSpatialCrop(crop_params)
	else:
		params.setSpatialCrop(None);
	return original_imp, crop_params;
def show_and_select_colonies():
	original_image.show()
	IJ.run("Point Tool...", "type=Hybrid color=Red size=Small");
	if len(x_centroid_list) != 0:
		points = ij.gui.PointRoi(x_centroid_list, y_centroid_list, len(x_centroid_list))
		original_image.setRoi(points, True)
		
	IJ.setTool('multipoint')
	dial = WaitForUserDialog('Please select colonies.')
Exemple #8
0
def perform_manual_qc(imp, rois, important_channel=1):
    """given cell rois generated by automatic methods, allow user to delete/add/redraw as appropriate"""
    for ch in range(imp.getNChannels()):
        imp.setC(ch + 1)
        sat_frac = 0.99 if (ch + 1) == important_channel else 0.01
        IJ.run(imp, "Enhance Contrast", "saturated={}".format(sat_frac))

    imp.setC(important_channel)
    IJ.setTool("freehand")
    proceed = False
    roim = RoiManager()
    roim.runCommand("Show all with labels")
    for roi in rois:
        roim.addRoi(roi)
    auto_rois_only = rois
    while not proceed:
        dialog = NonBlockingGenericDialog("Perform manual segmentation")
        dialog.setOKLabel("Proceed to next image...")
        dialog.addMessage("Perform manual correction of segmentation: ")
        dialog.addMessage(
            "Draw around cells and add to the region of interest manager (Ctrl+T). "
        )
        dialog.addMessage("Delete and redraw cells as appropriate. ")
        dialog.addMessage(
            "Then press \"proceed to next image\" when all cells have been added. "
        )
        dialog.showDialog()
        if dialog.wasCanceled():
            print("Manual segmentation canceled")
            return auto_rois_only
        elif dialog.wasOKed():
            if roim.getCount() == 0:
                rois = []
                confirm_dialog = GenericDialog("Continue?")
                confirm_dialog.addMessage(
                    "No rois selected in this FOV. Are you sure you want to proceed?"
                )
                confirm_dialog.setOKLabel("Yes, proceed")
                confirm_dialog.setCancelLabel("No, not yet")
                confirm_dialog.showDialog()
                if confirm_dialog.wasOKed():
                    proceed = True
            else:
                rois = roim.getRoisAsArray()
                proceed = True
    roim.reset()
    roim.close()
    for ch in range(imp.getNChannels()):
        imp.setC(ch + 1)
        IJ.run(imp, "Enhance Contrast", "saturated={}".format(0.35))
    imp.setC(important_channel)
    return rois
def getColonyCenter(brightfield):
	'''Returns the center of the colony based on the brightfield image.
	This will be automated in the future when we have better images. '''
	
	brightfield.show()
	IJ.setTool("point")
	WaitForUserDialog("Please select the center of the homeland. Click OK when done.").show()
	brightfield.hide()
	point = brightfield.getRoi()
	boundingRectangle = point.getBounds()
	xCoord = boundingRectangle.getX()
	yCoord = boundingRectangle.getY()
	return (xCoord, yCoord)
def getHomelandDiameter(fluorescence):
	'''Determine the homeland diameter based on the fluorescence data.'''
	
	fluorescence.show()
	IJ.setTool("line")
	WaitForUserDialog("Please select the diameter of the homeland. Click OK when done.").show()
	fluorescence.hide()
	diameter = fluorescence.getRoi().getLength()
	# Make it uncalibrated for the next step
	pixelWidth = fluorescence.getCalibration().pixelWidth
	uncalibratedDiameter  = diameter/pixelWidth

	return uncalibratedDiameter
def z_crop(imp):
    """trim a z stack based on interactively-defined start and end points"""
    IJ.setTool("zoom")
    IJ.run("Brightness/Contrast...")
    imp.setZ(1)
    WaitForUserDialog("Choose first z plane and click OK...").show()
    start_z = imp.getZ()
    WaitForUserDialog("Now choose last z plane and click OK...").show()
    end_z = imp.getZ()
    frames = imp.getNFrames()
    channels = imp.getNChannels()
    imp.killRoi()
    dupimp = Duplicator().run(imp, 1, channels, start_z, end_z, 1, frames)
    imp.hide()
    dupimp.show()
    return dupimp, (start_z, end_z)
Exemple #12
0
 def run(self):
     IJ.resetEscape()
     IJ.setTool("point")
     listener = ML()
     self.imp.show()
     canvas = self.imp.getWindow().getCanvas()
     canvas.addMouseListener(listener)
     # wait for mouse click
     while (not listener.mouseWasPressed) and (not IJ.escapePressed()):
         Thread.sleep(200)  # todo: how to make this better?
     canvas.removeMouseListener(listener)
     if IJ.escapePressed():
         IJ.log("command has been aborted")
     else:
         print listener.x, listener.y
         self.pos = [listener.x, listener.y]
def prompt_for_points(imp, title, message, n_points):
	"""prompt the user to provide a number of points on the image"""
	imp.killRoi();
	if (n_points == 1): 
		IJ.setTool("point");
	else:
		IJ.setTool("multipoint");
	selected_points = 0;
	while (selected_points != n_points):
		MyWaitForUser(title, message);
		roi = imp.getRoi();
		if roi is not None:
			selected_points = len(roi.getContainedPoints());
		if ((roi is None) or (selected_points != n_points)):
			MyWaitForUser("Error!", "Wrong number of points selected! Please try again...");
			imp.killRoi();
	return [(p.x, p.y) for p in roi.getContainedPoints()];
Exemple #14
0
def getOptions():
    global listener, xlist, ylist, zlist, manager
    gd = GenericDialog("Target Selection")
    gd.addMessage('Mandatory parameters\n')
    gd.addChoice('type', ['point', 'circle', 'spiral'], 'point')
    gd.addNumericField("                power (%)", 85, 0)
    gd.addNumericField("                duration (millisec)", 3, 0)
    gd.addNumericField("                interval between entries (ms)", 5000,
                       0)
    gd.addNumericField("                Z-start of stack (microns)", 0, 0)
    gd.addNumericField("                Z-step of stack (microns)", 5, 0)
    gd.addMessage('Optional\n')
    gd.addNumericField("                radius of a circle/spiral", 5, 0)
    gd.addNumericField("                num. of turns per circle/spiral", 3, 0)
    gd.addNumericField("                take image after every .. entries", 1,
                       0)
    gd.addNumericField("                add offset to X coordinates", 0, 0)
    gd.addNumericField("                add offset to Y coordinates", 0, 0)
    gd.addNumericField(
        "                imaging stack # for excitation onset (0,1,..)", 0, 0)
    gd.addMessage('Press ENTER to save the coordinate file\n')
    gd.addMessage('Press ESC to restart\n')
    gd.showDialog()
    profileType = gd.getNextChoice()
    power = gd.getNextNumber()
    duration = gd.getNextNumber()
    prewait = gd.getNextNumber()
    zStart = gd.getNextNumber()
    zStep = gd.getNextNumber()
    r = gd.getNextNumber()
    Nturns = gd.getNextNumber()
    camTriggerEvery = gd.getNextNumber()
    xOffset = gd.getNextNumber()
    yOffset = gd.getNextNumber()
    tmIndex = gd.getNextNumber()
    if gd.wasCanceled():
        IJ.setTool(Toolbar.RECTANGLE)
        return
    else:
        return r, power, profileType, duration, Nturns, camTriggerEvery, zStart, zStep, prewait, xOffset, yOffset, tmIndex
Exemple #15
0
def manual_analysis(imp, file_name, output_folder):
    """perform analysis based on manually drawn cells"""
    cal = imp.getCalibration()
    channel_imps = ChannelSplitter.split(imp)
    gfp_imp = channel_imps[0]
    IJ.setTool("freehand")
    proceed = False
    roim = RoiManager()
    roim.runCommand("Show all with labels")
    dialog = NonBlockingGenericDialog("Perform manual segmentation")
    dialog.setOKLabel("Proceed to next image...")
    dialog.addMessage("Perform manual segmentation: ")
    dialog.addMessage(
        "Draw around cells and add to the region of interest manager (Ctrl+T)")
    dialog.addMessage(
        "You can see what you've added so far if you check \"show all\" on the ROI manager"
    )
    dialog.addMessage(
        "Then press \"proceed to next image\" when all cells have been added")
    dialog.showDialog()
    if dialog.wasCanceled():
        raise KeyboardInterrupt("Run canceled")
    elif dialog.wasOKed():
        rois = roim.getRoisAsArray()
        roim.reset()
        roim.close()
        out_stats = generate_cell_shape_results(rois, gfp_imp, cal, file_name)
        print("Number of cells identified = {}".format(len(out_stats)))
        # save output
        save_qc_image(
            imp, rois, "{}_plus_overlay.tiff".format(
                os.path.join(output_folder,
                             os.path.splitext(file_name)[0])))
        save_cell_rois(rois, output_folder, os.path.splitext(file_name)[0])
        imp.changes = False
        imp.close()
        save_output_csv(out_stats, output_folder)
        return out_stats
    return None
def qc_background_regions(intensity_imp, bg_rois):
	"""allow the user to view and correct automatically-determined background regions"""
	imp = Duplicator().run(intensity_imp);
	imp.setTitle("Background region QC");
	imp.show();
	imp.setPosition(1);
	autoset_zoom(imp);
	imp.setRoi(bg_rois[0]);
	IJ.setTool("freehand");
	
	notOK = True;
	while notOK:
		listener = UpdateRoiImageListener(bg_rois, is_area=True);
		imp.addImageListener(listener);
		dialog = NonBlockingGenericDialog("Background region quality control");
		dialog.enableYesNoCancel("Continue", "Use this region for all t");
		dialog.setCancelLabel("Cancel analysis");
		dialog.addMessage("Please redraw background regions as necessary...")
		dialog.showDialog();
		if dialog.wasCanceled():
			raise KeyboardInterrupt("Run canceled");
		elif not(dialog.wasOKed()):
			this_roi = imp.getRoi();
			bg_rois = [this_roi for _ in listener.getRoiList()];
			imp.removeImageListener(listener);
		else:
			last_roi = imp.getRoi();
			qcd_bg_rois = listener.getRoiList();
			if imp.getNFrames() > imp.getNSlices():
				qcd_bg_rois[imp.getT() - 1] = last_roi;
			else:
				qcd_bg_rois[imp.getZ() - 1] = last_roi;
			notOK = False;
	imp.removeImageListener(listener);
	imp.changes = False;
	imp.close();
	
	return qcd_bg_rois;
def z_crop_finetune(imp, info):
    """define z cropping to allow freehand definition of lower bounds"""
    imp.setC(info.get_mosaic_labeled_ch())
    rot_imp = rot3d(imp, axis='x')
    imp.close()
    rot_imp.show()
    IJ.setTool("freehand")
    WaitForUserDialog("Select XZ region to crop...").show()
    crop_roi = rot_imp.getRoi()
    if crop_roi is None:
        return
    if crop_roi.getType():
        info.set_zx_crop_rect(
            str([(x, y) for x, y in zip(crop_roi.getPolygon().xpoints,
                                        crop_roi.getPolygon().ypoints)]))
    else:
        info.set_zx_crop_rect(crop_roi.getBounds().toString())
    if crop_roi.getType():
        IJ.run(zcrop_imp, "Make Inverse", "")
        inv_roi = zcrop_imp.getRoi()
        IJ.run(zcrop_imp, "Set...", "value=0 stack")
        IJ.run(zcrop_imp, "Make Inverse", "")
    imp = rot3d(rot_imp, axis='x')
    return imp
Exemple #18
0
def process(subFolder, outputDirectory, filename):
    #IJ.close()
    imp = IJ.openImage(inputDirectory + subFolder + '/' + rreplace(filename, "_ch00.tif", ".tif"))
    imp.show()


    # Finds the pixel length in microns from the xml metadata file
    file_list = [file for file in os.listdir(inputDirectory + subFolder) if file.endswith('.xml')]
    if len(file_list) > 0:
        xml = os.path.join(inputDirectory + subFolder, file_list[0])
        element_tree = ET.parse(xml)
        root = element_tree.getroot()
        for dimensions in root.iter('DimensionDescription'):
            num_pixels = int(dimensions.attrib['NumberOfElements'])
            if dimensions.attrib['Unit'] == "m":
                length = float(dimensions.attrib['Length']) * 1000000
            else:
                length = float(dimensions.attrib['Length'])
        pixel_length = length / num_pixels
    else:
        pixel_length = 0.877017

    log.write("Pixel Length:" + str(pixel_length) + "\n")

    IJ.run(imp, "Properties...",
           "channels=1 slices=1 frames=1 unit=um pixel_width=" + str(pixel_length) + " pixel_height=" + str(pixel_length) + " voxel_depth=25400.0508001")
    ic = ImageConverter(imp);
    ic.convertToGray8();
    #IJ.setThreshold(imp, 2, 255)


    # If wand tool is enabled, then this will prompt that to be used
    if enableWand:
        # Call threshold function to adjust threshold and select Organoid ROI
        IJ.run("Threshold...")
        WaitForUserDialog("Adjust Threshold to create mask").show()
        IJ.setTool("Wand")
        WaitForUserDialog("Click on Organoid Area for it to be selected. Best selection will be at the edge of the organoid to get entire organoid shape.").show()
        IJ.run("Clear Outside")

    if not enableWand:
        IJ.setAutoThreshold(imp, "Mean dark no-reset")
        IJ.run(imp, "Convert to Mask", "")
        IJ.run(imp, "Analyze Particles...", "size=100000-Infinity add select")
        rm = RoiManager.getInstance()
        imp = getCurrentImage()
        rm.select(imp, 0)
        IJ.setBackgroundColor(0, 0, 0)
        IJ.run(imp, "Clear Outside", "")

    IJ.run(imp, "Convert to Mask", "")
    IJ.run(imp, "Remove Outliers...", "radius=5" + " threshold=50" + " which=Dark")
    IJ.run(imp, "Remove Outliers...", "radius=5" + " threshold=50" + " which=Bright")

    # #Save the mask and open it
    IJ.saveAs("tiff", inputDirectory + '/mask')
    mask = IJ.openImage(inputDirectory + '/mask.tif')

    if enableWand:
        #Select ROI again to add it to the the ROI manager so that intensities and area is saved
        #IJ.run("Threshold...")
        IJ.setTool("Wand")
        WaitForUserDialog("Select Organoid area again for it to register within the ROI manager").show()
        rm = RoiManager()
        boundroi = ThresholdToSelection.run(mask)
        rm.addRoi(boundroi)


    if not displayImages:
        imp.changes = False
        imp.close()

    images = [None] * 5
    intensities = [None] * 5
    blobsarea = [None] * 5
    blobsnuclei = [None] * 5
    bigAreas = [None] * 5

    imp.close()

    #Loop to open all the channel images
    for chan in channels:
        v, x = chan
        images[x] = IJ.openImage(
            inputDirectory + subFolder + '/' + rreplace(filename, "_ch00.tif", "_ch0" + str(x) + ".tif"))


        # Apply Mask on all the images and save them into an array
        apply_mask = ImageCalculator()
        images[x] = apply_mask.run("Multiply create 32 bit", mask, images[x])
        ic = ImageConverter(images[x])
        ic.convertToGray8()
        imp = images[x]

        # Calculate the intensities for each channel as well as the organoid area
        for roi in rm.getRoisAsArray():
            imp.setRoi(roi)
            stats = imp.getStatistics(Measurements.MEAN | Measurements.AREA)
            intensities[x] = stats.mean
            bigAreas[x] = stats.area

    rm.close()

    # Opens the ch00 image and sets default properties
    apply_mask = ImageCalculator()
    imp = IJ.openImage(inputDirectory + subFolder + '/' + filename)
    imp = apply_mask.run("Multiply create 32 bit", mask, imp)
    IJ.run(imp, "Properties...",
           "channels=1 slices=1 frames=1 unit=um pixel_width=" + str(pixel_length) + " pixel_height=" + str(pixel_length) + " voxel_depth=25400.0508001")


    # Sets the threshold and watersheds. for more details on image processing, see https://imagej.nih.gov/ij/developer/api/ij/process/ImageProcessor.html

    ic = ImageConverter(imp);
    ic.convertToGray8();

    IJ.run(imp, "Remove Outliers...", "radius=2" + " threshold=50" + " which=Dark")

    IJ.run(imp, "Gaussian Blur...", "sigma=" + str(blur))

    IJ.setThreshold(imp, lowerBounds[0], 255)

    if displayImages:
        imp.show()
    IJ.run(imp, "Convert to Mask", "")
    IJ.run(imp, "Watershed", "")

    if not displayImages:
        imp.changes = False
        imp.close()

    # Counts and measures the area of particles and adds them to a table called areas. Also adds them to the ROI manager

    table = ResultsTable()
    roim = RoiManager(True)
    ParticleAnalyzer.setRoiManager(roim);
    pa = ParticleAnalyzer(ParticleAnalyzer.ADD_TO_MANAGER, Measurements.AREA, table, 15, 9999999999999999, 0.2, 1.0)
    pa.setHideOutputImage(True)
    # imp = impM

    # imp.getProcessor().invert()
    pa.analyze(imp)

    areas = table.getColumn(0)

    # This loop goes through the remaining channels for the other markers, by replacing the ch00 at the end with its corresponding channel
    # It will save all the area fractions into a 2d array called areaFractionsArray

    areaFractionsArray = [None] * 5
    for chan in channels:
        v, x = chan
        # Opens each image and thresholds

        imp = images[x]

        IJ.run(imp, "Properties...",
               "channels=1 slices=1 frames=1 unit=um pixel_width=" + str(pixel_length) + " pixel_height=" + str(pixel_length) + " voxel_depth=25400.0508001")

        ic = ImageConverter(imp);
        ic.convertToGray8();
        IJ.setThreshold(imp, lowerBounds[x], 255)


        if displayImages:
            imp.show()
            WaitForUserDialog("Title", "Adjust Threshold for Marker " + v).show()

        IJ.run(imp, "Convert to Mask", "")

        # Measures the area fraction of the new image for each ROI from the ROI manager.
        areaFractions = []
        for roi in roim.getRoisAsArray():
            imp.setRoi(roi)
            stats = imp.getStatistics(Measurements.AREA_FRACTION)
            areaFractions.append(stats.areaFraction)

        # Saves the results in areaFractionArray

        areaFractionsArray[x] = areaFractions

    roim.close()

    for chan in channels:
        v, x = chan

        imp = images[x]
        imp.deleteRoi()
        roim = RoiManager(True)
        ParticleAnalyzer.setRoiManager(roim);
        pa = ParticleAnalyzer(ParticleAnalyzer.ADD_TO_MANAGER, Measurements.AREA, table, 15, 9999999999999999, 0.2, 1.0)
        pa.analyze(imp)

        blobs = []
        for roi in roim.getRoisAsArray():
            imp.setRoi(roi)
            stats = imp.getStatistics(Measurements.AREA)
            blobs.append(stats.area)

        blobsarea[x] = sum(blobs) #take this out and use intial mask tissue area from the beginning
        blobsnuclei[x] = len(blobs)


        if not displayImages:
            imp.changes = False
            imp.close()
        roim.reset()
        roim.close()

        imp.close()

    # Creates the summary dictionary which will correspond to a single row in the output csv, with each key being a column

    summary = {}

    summary['Image'] = filename
    summary['Directory'] = subFolder

    # Adds usual columns

    summary['size-average'] = 0
    summary['#nuclei'] = 0
    summary['all-negative'] = 0

    summary['too-big-(>' + str(tooBigThreshold) + ')'] = 0
    summary['too-small-(<' + str(tooSmallThreshold) + ')'] = 0

    # Creates the fieldnames variable needed to create the csv file at the end.

    fieldnames = ['Name', 'Directory', 'Image', 'size-average', 'too-big-(>' + str(tooBigThreshold) + ')',
                  'too-small-(<' + str(tooSmallThreshold) + ')', '#nuclei', 'all-negative']

    # Adds the columns for each individual marker (ignoring Dapi since it was used to count nuclei)

    summary["organoid-area"] = bigAreas[x]
    fieldnames.append("organoid-area")

    for chan in channels:
        v, x = chan
        summary[v + "-positive"] = 0
        fieldnames.append(v + "-positive")

        summary[v + "-intensity"] = intensities[x]
        fieldnames.append(v + "-intensity")

        summary[v + "-blobsarea"] = blobsarea[x]
        fieldnames.append(v + "-blobsarea")

        summary[v + "-blobsnuclei"] = blobsnuclei[x]
        fieldnames.append(v + "-blobsnuclei")

    # Adds the column for colocalization between first and second marker

    if len(channels) > 2:
        summary[channels[1][0] + '-' + channels[2][0] + '-positive'] = 0
        fieldnames.append(channels[1][0] + '-' + channels[2][0] + '-positive')

    # Adds the columns for colocalization between all three markers

    if len(channels) > 3:
        summary[channels[1][0] + '-' + channels[3][0] + '-positive'] = 0
        summary[channels[2][0] + '-' + channels[3][0] + '-positive'] = 0
        summary[channels[1][0] + '-' + channels[2][0] + '-' + channels[3][0] + '-positive'] = 0

        fieldnames.append(channels[1][0] + '-' + channels[3][0] + '-positive')
        fieldnames.append(channels[2][0] + '-' + channels[3][0] + '-positive')
        fieldnames.append(channels[1][0] + '-' + channels[2][0] + '-' + channels[3][0] + '-positive')

    # Loops through each particle and adds it to each field that it is True for.

    areaCounter = 0
    for z, area in enumerate(areas):

        log.write(str(area))
        log.write("\n")

        if area > tooBigThreshold:
            summary['too-big-(>' + str(tooBigThreshold) + ')'] += 1
        elif area < tooSmallThreshold:
            summary['too-small-(<' + str(tooSmallThreshold) + ')'] += 1
        else:

            summary['#nuclei'] += 1
            areaCounter += area

            temp = 0
            for chan in channels:
                v, x = chan
                if areaFractionsArray[x][z] > areaFractionThreshold[
                    0]:  # theres an error here im not sure why. i remember fixing it before
                    summary[chan[0] + '-positive'] += 1
                    if x != 0:
                        temp += 1

            if temp == 0:
                summary['all-negative'] += 1

            if len(channels) > 2:
                if areaFractionsArray[1][z] > areaFractionThreshold[1]:
                    if areaFractionsArray[2][z] > areaFractionThreshold[2]:
                        summary[channels[1][0] + '-' + channels[2][0] + '-positive'] += 1

            if len(channels) > 3:
                if areaFractionsArray[1][z] > areaFractionThreshold[1]:
                    if areaFractionsArray[3][z] > areaFractionThreshold[3]:
                        summary[channels[1][0] + '-' + channels[3][0] + '-positive'] += 1
                if areaFractionsArray[2][z] > areaFractionThreshold[2]:
                    if areaFractionsArray[3][z] > areaFractionThreshold[3]:
                        summary[channels[2][0] + '-' + channels[3][0] + '-positive'] += 1
                        if areaFractionsArray[1][z] > areaFractionThreshold[1]:
                            summary[channels[1][0] + '-' + channels[2][0] + '-' + channels[3][0] + '-positive'] += 1

    # Calculate the average of the particles sizes

    if float(summary['#nuclei']) > 0:
        summary['size-average'] = round(areaCounter / summary['#nuclei'], 2)

    # Opens and appends one line on the final csv file for the subfolder (remember that this is still inside the loop that goes through each image)

    with open(outputDirectory + "/" + outputName + ".csv", 'a') as csvfile:

        writer = csv.DictWriter(csvfile, fieldnames=fieldnames, extrasaction='ignore', lineterminator='\n')
        if os.path.getsize(outputDirectory + "/" + outputName + ".csv") < 1:
            writer.writeheader()
        writer.writerow(summary)

    IJ.run(imp, "Close All", "")
def main():
    # define here which membrane indices will be used in the analysis, with last index the "control" index
    membrane_indices = [-1, 0, 1, 3]

    # for now, work with frontmost open image...
    imp = IJ.getImage()
    im_title = imp.getTitle()
    settings = MembraneEvolutionAnalysisSettings(
        membrane_indices=membrane_indices)
    settings.loadPersistedSettings()

    timestamp = datetime.strftime(datetime.now(), '%Y-%m-%d %H-%M-%S')
    DirectoryChooser.setDefaultDirectory((settings.output_path))
    dc = DirectoryChooser('Select the root folder for saving output')
    output_root = dc.getDirectory()
    if output_root is None:
        raise IOError('no output path chosen')
    settings.output_path = output_root

    # get calibration
    cal = imp.getCalibration()
    if cal.getTimeUnit() == "sec":
        cal.setTimeUnit('s')

    # pop up a dialog prompting for selection of zero time point, frame interval, and time step for analysis
    time_steps_not_ok = True
    while time_steps_not_ok:
        dialog = NonBlockingGenericDialog("Determine time parameters...")
        dialog.addNumericField("0 timepoint frame (1-index): ",
                               settings.zero_timepoint_frame, 0)
        dialog.addNumericField("Acquisition time step (s): ",
                               cal.frameInterval,
                               2)  # assume stored in seconds
        dialog.addNumericField(
            "Time step for analysis (s): ",
            cal.frameInterval * settings.analysis_frame_step, 2)
        dialog.showDialog()

        if dialog.wasCanceled():
            return

        zero_f = dialog.getNextNumber()
        acq_t_step = dialog.getNextNumber()
        analysis_t_step = dialog.getNextNumber()
        if acq_t_step != 0 and analysis_t_step != 0:
            analysis_frame_step = analysis_t_step / acq_t_step

            if round(analysis_frame_step) == analysis_frame_step:
                time_steps_not_ok = False
                settings.zero_timepoint_frame = zero_f
                settings.analysis_frame_step = analysis_frame_step
        if time_steps_not_ok:
            warning_dlg = GenericDialog("Error!")
            warning_dlg.addMessage(
                "Analysis time step must be an integer multiple of acquisition time steps, and neither should be zero!!"
            )
            warning_dlg.setOKLabel("Try again...")
            warning_dlg.showDialog()

            if warning_dlg.wasCanceled():
                return

    start_frame = int(((zero_f - 1) % analysis_frame_step) + 1)
    end_frame = int(imp.getNFrames() -
                    (imp.getNFrames() - zero_f) % analysis_frame_step)
    frames = [
        f + 1
        for f in range(start_frame - 1, end_frame, int(analysis_frame_step))
    ]
    print("frames = " + str(frames))
    imp.killRoi()
    analysis_imp = SubstackMaker().makeSubstack(
        imp,
        str(start_frame) + "-" + str(end_frame) + "-" +
        str(int(analysis_frame_step)))
    imp.changes = False
    imp.close()
    analysis_imp.show()
    drawn_membranes = [
        TimepointsMembranes(input_image_title=im_title,
                            time_point_s=(t - 1) * acq_t_step) for t in frames
    ]
    membranes_listener = UpdateRoiImageListener(drawn_membranes)
    analysis_imp.addImageListener(membranes_listener)

    # now attach roi listener to store all 0th membranes after showing a waitforuserdialog to prompt continuation
    IJ.setTool("freeline")
    for membrane_idx in membrane_indices:
        #		if membrane_idx>50:
        #			IJ.setTool("line");
        analysis_imp.killRoi()
        membranes_listener.resetLastFrame()
        membranes_listener.setCurrentMembraneIndex(membrane_idx)
        analysis_imp.setZ(1)
        continue_dlg = WaitForUserDialog(
            "Continue?", "Click OK once all the " + str(membrane_idx) +
            "-index membranes have been drawn")
        continue_dlg.show()
        membranes_listener.imageUpdated(analysis_imp)
        drawn_membranes = membranes_listener.getDrawnMembraneTimepointsList()
        json_path = os.path.join(output_root,
                                 "Membranes " + timestamp + ".json")
        f = open(json_path, 'w+')
        try:
            json.dump(drawn_membranes, f, default=encode_membrane)
        finally:
            f.close()
        # save csv containing mebrane measurements for current membrane index
        csv_path = os.path.join(
            output_root, ("Membrane measurements " + timestamp + ".csv"))
        if membrane_idx == membrane_indices[0]:
            try:
                f = open(csv_path, 'wb')
                writer = csv.writer(f)
                writer.writerow([
                    "Membrane index", ("Time point, " + cal.getTimeUnit()),
                    ("Membrane length, " + cal.getUnit()),
                    ("Euclidean length, " + cal.getUnit()),
                    "Membrane sinuoisty"
                ])
            finally:
                f.close()
        try:
            f = open(csv_path, 'ab')
            writer = csv.writer(f)
            for mems in drawn_membranes:
                mem = mems.getMembrane(membrane_idx)
                if mem is not None:
                    writer.writerow([
                        membrane_idx, mems.time_point_s,
                        mem.getPathLength() * cal.pixelWidth,
                        mem.getEuclidean() * cal.pixelWidth,
                        mem.getSinuosity()
                    ])
        finally:
            f.close()

    settings.persistSettings()
    settings.save_settings()
    print("Finished getting all membranes with indices " +
          str(membrane_indices))
    analysis_imp.close()
        win.setLocation(int(xpos_det), int(ypos_det))
        getOptions(dest)
    else:
        pass

    firstpass = False

    imp = IJ.getImage()
    image_name = imp.title
    bit_depth = bit_tester(image_name)
    colorscale()

    #set a manual background value#
    if man_bck_det is True:
        if current_image != image_name:
            IJ.setTool("oval")
            region = "Select Background"
            selection(region)
            to_transport_channel()
            man_bck_list=[]
            for channel in channel_iterator:
            	channel_first = int(channel)
            	IJ.setSlice(channel_first)
            	man_bck_list.append(selection_mean())
           	background = man_bck_list[0]
           	to_transport_channel()

    if mean_max_det is True:
        IJ.setTool("polygon")
    else:
        IJ.setTool("rectangle")
Exemple #21
0
        emissionWL.append(WL)
except ValueError:
    raise Exception("Couldn't find the EmissionWavelength info in the metadata")

# Make the maximum intensity projection
# and show it for user input.
project = ZProjector()
project.setMethod(ZProjector.MAX_METHOD)
project.setImage(imp)
project.doProjection()
projection = project.getProjection()
projection.show()

# Wait for the user to draw a line
# and check if line ROI.
IJ.setTool("line");
myWait = WaitForUserDialog ("waitForUser", "Make a line with the region of interest and press OK")
myWait.show()

roi = projection.getRoi()

# Check if roi is a line
# otherwise exit
if not (roi.isLine()):
    raise Exception("Line selection required")

# Loop through existing files to avoid
# overwriting. Will increment the number
# at the end. Saves the MIP with input.
fileName      = shortTitle + "ROI" + str(num);
overlayOutput = os.path.join(output,"MAX_" + fileName)
if numSlices > 1:
	for i in range(numSlices - 1):
		stack.deleteSlice(1)
image.setStack(stack)


IJ.run("Set Measurements...", "  redirect=None decimal=3");

numTimesToMeasure = 5
# Draw the radius N times and record the result
centerList = []
radiusList = []

for i in range(numTimesToMeasure):
	IJ.run("Select None")
	IJ.setTool('line')
	WaitForUserDialog('Draw the radius.').show()
	# Get the center and the radius selected
	currentROI = image.getRoi()
	cx, cy = currentROI.x1, currentROI.y1
	rx, ry = currentROI.x2, currentROI.y2
	# Always assumes you draw from center to radius! If you do
	# not, bad things happen.
	centerList.append([cx, cy])
	radius = ((cx-rx)**2 + (cy-ry)**2)**0.5
	radiusList.append(radius)
	
	IJ.run('Measure')

cx_list = [f[0] for f in centerList]
cy_list = [f[1] for f in centerList]
Exemple #23
0
    if f != "":
        array = get_array(f[0])
        if f[1] == "b":
            color = "black"
        else:
            color = "white"
        draw(i, j, array, color)


def draw_field(field, selectedX, selectedY):
    for j in range(0, 8):
        for i in range(0, 8):
            draw_one(i, j, field, selectedX, selectedY)


IJ.setTool(Toolbar.HAND)
field = initial_field()
currentX = -1
currentY = -1
draw_field(field, currentX, currentY)
canvas = WindowManager.getCurrentImage().getCanvas()
clicked = 0

while True:
    p = canvas.getCursorLoc()
    x = int(p.x / w)
    y = int(p.y / h)
    newClicked = canvas.getModifiers() & 16
    if clicked and not newClicked:
        if currentX >= 0:
            if x != currentX or y != currentY:
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;
Exemple #25
0
    checkbox = False
    while checkbox == False:
        gd = GenericDialog("Title here")
        gd.addStringField("id", "")
        gd.addCheckbox("Same Image", True)
        gd.showDialog()
        checkbox = gd.getNextBoolean()
        id = gd.getNextString()
        if checkbox == False:
            IJ.run("Open Next")
        else:
            break

    imp = IJ.getImage()
    IJ.setTool("multipoint")
    WaitForUserDialog("make 11 points").show()

    proi = imp.getRoi()
    p = proi.getPolygon()
    xpts = p.xpoints
    ypts = p.ypoints

    xpts.insert(0,
                1111)  # inserts a dummy variables so that numbers makes sense
    ypts.insert(0, 1111)

    thorax_width = distance(xpts[2], ypts[2], xpts[3], ypts[3])
    total_body_length = distance(xpts[1], ypts[1], xpts[5], ypts[5])
    abdomen_length = distance(xpts[1], ypts[1], xpts[4], ypts[4])
    abdomen_width = distance(xpts[6], ypts[6], xpts[7], ypts[7])
Exemple #26
0
ip = FloatProcessor(w, h)
pix = ip.getPixels()
for x in range(w):
    for y in range(h):
        pix[y * w + x] = projected_im_pix[y][x]

out_imp = ImagePlus("projected", ip)
out_imp.show()

egfp_imp_disp.show()
roi_stack.show()
#egfp_imp_disp.addImageListener(UpdateRoiImageListener(ring_rois));

unwrapped_imp = IJ.createImage("twisted unwrap", 2 * out_imp.getWidth(),
                               out_imp.getHeight(), 1, 32)
unwrapped_imp.show()
IJ.setTool("freeline")
WaitForUserDialog("input unwrap axis").show()
unwrap_poly = out_imp.getRoi().getPolygon()
unwrap_poly_xs

#print("unzip axis = " + str(unzip_axis));
#right_side_xs = unzip_axis;
#right_side_xs.append(out_imp.getWidth());
#right_side_xs.append(out_imp.getWidth());
#right_side_ys = [y+1 for y in range(out_imp.getHeight())];
#right_side_ys.append(out_imp.getHeight());
#right_side_ys.append(1);
#right_side_roi = PolygonRoi(right_side_xs, right_side_ys, Roi.POLYGON);
#out_imp.setRoi(right_side_roi);
    if f != '':
        array = get_array(f[0])
        if f[1] == 'b':
            color = 'black'
        else:
            color = 'white'
        draw(i, j, array, color)


def draw_field(field, selectedX, selectedY):
    for j in range(0, 8):
        for i in range(0, 8):
            draw_one(i, j, field, selectedX, selectedY)


IJ.setTool(Toolbar.HAND)
field = initial_field()
currentX = -1
currentY = -1
draw_field(field, currentX, currentY)
canvas = WindowManager.getCurrentImage().getCanvas()
clicked = 0

while True:
    p = canvas.getCursorLoc()
    x = int(p.x / w)
    y = int(p.y / h)
    newClicked = canvas.getModifiers() & 16
    if clicked and not newClicked:
        if currentX >= 0:
            if x != currentX or y != currentY:
Exemple #28
0
def run():
    ### Default arguments
    two_sarcomere_size = 25  # determined by filter used.
    rotation_angle = 0.0

    ### Get the image we'd like to work with.
    # Don't need to ask where to save the intermediate image since it'll just be saved in the matchedmyo folder anyway
    #   may change this though. In case they want to keep that image around.
    this_img = WindowManager.getCurrentImage()
    if this_img == None:
        ud = WaitForUserDialog(
            "Please select the image you would like to analyze.")
        ud.show()
        this_img = WindowManager.getCurrentImage()
    img_name = this_img.getTitle()

    matchedmyo_path = "/home/AD/dfco222/scratchMarx/matchedmyo/"  # this would be grabbed from the prompt
    gd = GenericDialog("Preprocessing Options")
    gd.addCheckbox("Automatic Resizing/Rotation", True)
    gd.addCheckbox("CLAHE", True)
    gd.addCheckbox("Normalization to Transverse Tubules", True)
    gd.showDialog()
    if gd.wasCanceled():
        return
    auto_resize_rotate = gd.getNextBoolean()
    clahe = gd.getNextBoolean()
    normalize = gd.getNextBoolean()

    if auto_resize_rotate:
        # Clear selection so it takes FFT of full image

        rotation_angle = auto_resize_angle_measure(this_img,
                                                   two_sarcomere_size)

    if clahe:
        clahe_args = "blocksize={} histogram=256 maximum=3 mask=*None* fast_(less_accurate)".format(
            two_sarcomere_size)
        IJ.run(this_img, "Enhance Local Contrast (CLAHE)", clahe_args)

    if normalize:
        # Ask the user to select a subsection of the image that looks healthy-ish.
        ud = WaitForUserDialog(
            "Please select a subsection exhibiting a measure of healthy TT structure using the Rectangle tool.\n"
            + " Only a single cell or several are needed.\n\n" +
            " Press 'OK' when finished.")
        ud.show()
        IJ.setTool("rectangle")

        # Duplicate the selected subsection.
        selection = this_img.crop()
        IJ.run(selection, "Duplicate...", "title=subsection.tif")

        # Grab the subsection image and rotate it.
        selection = WindowManager.getImage("subsection.tif")
        IJ.run(
            selection, "Rotate...",
            "angle={} grid=1 interpolation=Bicubic enlarge".format(
                rotation_angle))

        # Ask the user to select a bounding box that contains only tubules
        # NOTE: Need to get rid of initial selection since it's the entire image and it's annoying to click out of
        IJ.setTool("rectangle")
        IJ.run(selection, "Select None", "")
        ud = WaitForUserDialog(
            "Select a subsection of the image that contains only tubules and no membrane."
        )
        ud.show()

        # Grab the subsection ImagePlus
        selection = WindowManager.getCurrentImage()
        this_window = WindowManager.getActiveWindow()
        selection_small = selection.crop()
        IJ.run(selection, "Close", "")

        # NOTE: May not actually display this depending on how the macros work
        IJ.run(selection_small, "Duplicate...", "title=subsection_small.tif")

        # Smooth the selection using the single TT filter.
        # NOTE: It won't read in so we're just going to hard code it in since it's simple
        tt_filt_row = "0 0 0 1 1 1 1 1 1 0 0 0 0\n"
        tt_filt = ""
        for i in range(21):
            tt_filt += tt_filt_row
        IJ.run("Convolve...", "text1=[" + tt_filt + "] normalize")

        # Segment out the TTs from the 'gaps' using Gaussian Adaptive Thresholding.
        selection_small = WindowManager.getImage("subsection_small.tif")
        IJ.run(selection_small, "Duplicate...", "title=thresholded.tif")
        threshed = WindowManager.getImage("thresholded.tif")
        IJ.run(threshed, "Auto Local Threshold",
               "method=Bernsen radius=7 parameter_1=1 parameter_2=0 white")

        # Select the TTs from the thresholded image.
        IJ.run(threshed, "Create Selection", "")
        tt_selection = WindowManager.getImage("subsection_small.tif")
        IJ.selectWindow("thresholded.tif")
        IJ.selectWindow("subsection_small.tif")
        IJ.run(tt_selection, "Restore Selection", "")

        # Get TT intensity statistics.
        stat_options = IS.MEAN | IS.MIN_MAX | IS.STD_DEV
        stats = IS.getStatistics(tt_selection.getProcessor(), stat_options,
                                 selection_small.getCalibration())
        # Calculate pixel ceiling intensity value based on heuristic.
        # TODO: Add a catch for data type overflow.
        pixel_ceiling = stats.mean + 3 * stats.stdDev
        print "px ceil:", pixel_ceiling

        # Invert selection to get inter-sarcomeric gap intensity statistics.
        IJ.run(tt_selection, "Make Inverse", "")
        stat_options = IS.MEAN | IS.MIN_MAX | IS.STD_DEV
        stats = IS.getStatistics(tt_selection.getProcessor(), stat_options,
                                 selection_small.getCalibration())
        # Calculate pixel floor intensity value based on heuristic.
        pixel_floor = stats.mean - stats.stdDev
        # TODO: Add a catch for data type underflow.
        print "px floor:", pixel_floor

        # Threshold original image based on these values.
        IJ.selectWindow(this_img.getTitle())
        IJ.run(this_img, "Select All", "")
        IJ.setMinAndMax(pixel_floor, pixel_ceiling)
        IJ.run(this_img, "Apply LUT", "")

    ## Ask if it is acceptable.
    gd = GenericDialog("Acceptable?")
    gd.addMessage(
        "If the preprocessed image is acceptable for analysis, hit 'OK' to being analysis.\n"
        + " If the image is unacceptable or an error occurred, hit 'Cancel'")
    gd.showDialog()
    if gd.wasCanceled():
        return

    ## Save the preprocessed image.
    imp = IJ.getImage()
    fs = FileSaver(imp)
    img_save_dir = matchedmyo_path + "myoimages/"  # actually get from user at some point
    img_file_path = img_save_dir + img_name[:-4] + "_preprocessed.tif"
    if os.path.exists(img_save_dir) and os.path.isdir(img_save_dir):
        print "Saving image as:", img_file_path
        if os.path.exists(img_file_path):
            # use dialog box to ask if they want to overwrite
            gd = GenericDialog("Overwrite?")
            gd.addMessage(
                "A file exists with the specified path, \"{}\". Would you like to overwrite it?"
                .format(img_file_path))
            gd.enableYesNoCancel()
            gd.showDialog()
            if gd.wasCanceled():
                return
        elif fs.saveAsTiff(img_file_path):
            print "Preprocessed image saved successfully at:", '"' + img_file_path + '"'
    else:
        print "Folder does not exist or is not a folder!"

    ### Create the YAML file containing the parameters for classification
    ## Ask user for YAML input
    gd = GenericDialog("YAML Input")
    gd.addStringField("imageName", img_file_path, 50)
    #gd.addStringField("maskName", "None")
    gd.addStringField("outputParams_fileRoot", img_file_path[:-4], 50)
    gd.addStringField("outputParams_fileType", "tif")
    gd.addNumericField("outputParams_dpi", 300, 0)
    gd.addCheckbox("outputParams_saveHitsArray", False)
    gd.addStringField("outputParams_csvFile", matchedmyo_path + "results/")
    gd.addCheckbox("TT Filtering", True)
    gd.addToSameRow()
    gd.addCheckbox("LT Filtering", True)
    gd.addToSameRow()
    gd.addCheckbox("TA Filtering", True)
    gd.addNumericField("scopeResolutions_x", 5.0, 3)
    gd.addToSameRow()
    gd.addNumericField("scopeResolutions_y", 5.0, 3)
    gd.addMessage("Enter in filter rotation angles separated by commas.")
    gd.addStringField("", "-25, -20, -15, -10, -5, 0, 5, 10, 15, 20, 25", 50)
    gd.addCheckbox("returnAngles", False)
    gd.addCheckbox("returnPastedFilter", True)
    gd.showDialog()
    if gd.wasCanceled():
        return

    strings = [st.text for st in gd.getStringFields()]
    #if strings[1] == "None" or "":
    #	strings[1] = None
    nums = [float(num.text) for num in gd.getNumericFields()]
    nums[0] = int(nums[0])  # Have to make sure the dpi variable is an integer
    checks = [str(bool(boo.state)) for boo in gd.getCheckboxes()]
    iter_argument = ','.join(
        [str(float(it) - rotation_angle) for it in strings[4].split(',')])
    string_block = """imageName: {0[0]}
outputParams:
  fileRoot: {0[1]}
  fileType: {0[2]}
  dpi: {1[0]}
  saveHitsArray: {2[0]}
  csvFile: {0[3]}
preprocess: False
filterTypes:
  TT: {2[1]}
  LT: {2[2]}
  TA: {2[3]}
scopeResolutions:
  x: {1[1]}
  y: {1[2]}
iters: [{3}]
returnAngles: {2[4]}
returnPastedFilter: {2[5]}""".format(strings, nums, checks, iter_argument)
    im_title = this_img.getTitle()
    with cd(matchedmyo_path):
        yaml_file_path = "./YAML_files/" + im_title[:-4] + ".yml"
        with open("./YAML_files/" + im_title[:-4] + ".yml", "w") as ym:
            ym.write(string_block)
        print "Wrote YAML file to:", matchedmyo_path + yaml_file_path[2:]

    ### Run the matchedmyo code on the preprocessed image
    with cd(matchedmyo_path):
        #os.chdir(matchedmyo_path)
        #subprocess.call(["python3", matchedmyo_path+"matchedmyo.py", "fullValidation"])
        subprocess.call(
            ["python3", "matchedmyo.py", "run", "--yamlFile", yaml_file_path])
Exemple #29
0
def makeArrow(x1, y1, x2, y2):
    IJ.setTool("arrow")
    imp = IJ.getImage()
    imp.setRoi(Line(x1, y1, x2, y2))
Exemple #30
0
def duty_cycle(i, horizontal):
	IJ.open(i)
	IJ.run("Enhance Contrast...", "saturated=0.3 equalize")
	IJ.run("Smooth", "")
	'IJ.run("Anisotropic Diffusion 2D", "number=20 smoothings=1 keep=20 a1=0.50 a2=0.90 dt=20 edge=5")     # use instead of smooth for better results, slower
	imp = IJ.getImage()
	ImageConverter(imp).convertToGray8()
	file_base = str(imp.title)								# convert name into string
	file_base = file_base.split('.', 1)[0]					# remove all characters including and after .
	sample_id = file_base.split('_', 1)[0]
	height = imp.height
	width = imp.width
	IJ.run(imp, "Set Scale...", "distance=5000 known=1 pixel=1 unit=cm")
	IJ.setTool("line")
	for scan in range(1, num_scans):
		row_count = 0
		data=[]
		data2=[]
		last = 0
		filename = file_base + "_" + str(scan)
		
		if not horizontal:
			IJ.makeLine(0, scan*height/num_scans, width, scan*height/num_scans)				# horizontal line to measure vertical grating profile		
		else:
			IJ.makeLine(width*scan/num_scans, 9*height/10, width*scan/num_scans, 0)			# vertical line to measure horizontal grating profile
		
		IJ.run(imp, "Plot Profile", "")
		imp_plot = IJ.getImage()
		IJ.run(imp, "Find Peaks", setting)	# nw07 params: min._peak_amplitude=60 min._peak_distance=0 min._value=100 max._value=0 exclude list
		IJ.saveAs("Results", csvpath + filename + "_raw.csv")
		imp_plot.close()
		imp_plot = IJ.getImage()
		IJ.saveAs("Png", csvpath + "Peaks in Plot of " + filename + ".png")
		imp_plot.close()
		IJ.selectWindow(filename + "_raw.csv")
		IJ.run("Close")
		
		with open(csvpath + filename + "_raw.csv", "rb") as fin, open(csvpath + filename + "_peaks.csv", "wb") as fout:  
		    writer = csv.writer(fout)            
		    for row in csv.reader(fin):
		        if not row[2] == '':
		             writer.writerow(row)

		with open(csvpath + filename + "_peaks.csv", "rb") as File:
		    reader = csv.reader(File)
		    for row in reader:
		        row_count += 1
			if row_count == 1:
				continue
			data.append(tuple(row))								# Append all non-header rows into a list of data as a tuple of cells
		for row in sort_table(data, 2):
			data2.append(tuple(row))
		if len(data2) < 3:
			IJ.log(filename + " no peaks detected, skipping...")
			continue
		else:
			peaks = len(data2)
			last = data2[0]
			last = last[2]
			
			row_count = 0
			diff = 0
			colG = []
			blank = ""
			duty = zip(*data2)
			for row in data2:
				row_count += 1
				if row_count == 1:
					continue
				else:
					print row[2]
					print last
					diff = float(row[2]) - float(last)
					colG.append(diff)
					last = row[2]
			a, b = colG[::2], colG[1::2]
			avga = sum(a)/len(a)
			avgb = sum(b)/len(b)
			a_len_dev = len(a) - 1
			b_len_dev = len(b) - 1
			if b_len_dev > 1:
				a_stdev = sqrt(sum((x - avga)**2 for x in a) / a_len_dev)
				b_stdev = sqrt(sum((x - avgb)**2 for x in b) / b_len_dev)
			else:
				a_stdev = 1
				b_stdev = 1
			
			duty_cyc = avga/(avga+avgb)
			perc = duty_cyc*100
			invperc = 100 - perc
			inv_duty = 1 - duty_cyc
			duty_max = max(duty_cyc, inv_duty)
			duty_min = min(duty_cyc, inv_duty)
			percs = round(perc)
			percs = int(percs)
			percs = str(percs)
			invpercs = round(invperc)
			invpercs = int(invpercs)
			invpercs = str(invpercs)
		
			colG.insert(0, blank)
			a.insert(0, blank)
			b.insert(0, blank)
			b.insert(1, blank)
			
			i = 0
			while i < len(a):
					i += 2
					a.insert(i, blank)
			
			i = 1
			while i < len(b):
					i += 2
					b.insert(i, blank)
			
			duty.append(colG)
			duty.append(a)
			duty.append(b)	
			duty = zip(*duty)
			result = [sample_id, file_base, scan, duty_cyc, inv_duty, a_stdev, b_stdev, peaks, duty_max, duty_min]
			header = ["X0", "Y0", "X1", "Y1", "X2", "Y2", "diff", "a", "b"]
			results.append(result)
			with open(csvpath + filename + "_duty.csv", 'wb') as myfile:
				wr = csv.writer(myfile, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL)
				wr.writerow(header)
				wr.writerows(duty)
			print(filename + " duty cycle is " + percs + "/" + invpercs + "%.")
			IJ.log(filename + " duty cycle is " + percs + "/" + invpercs + "% (" + str(peaks) + " peaks found)")
			with open(csvpath + "results.csv", 'wb') as myfile:
				wr = csv.writer(myfile, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL)
				wr.writerows(results)		# Write the result data from all images into a single csv file
def main():
	### debug ###############################################################
	#print (sys.version_info);
	#print(sys.path);
	#file_path = "D:\\data\\Inverse blebbing\\MAX_2dpf marcksl1b-EGFP inj_TgLifeact-mCh_movie e4_split-bleb1.tif";
	#output_root = "D:\\data\\Inverse blebbing\\output";
	#from datetime import datetime
	#timestamp = datetime.strftime(datetime.now(), '%Y-%m-%d %H-%M-%S');
	#output_folder = os.path.join(output_root, (timestamp + ' output')); 
	#os.mkdir(output_folder); 
	########################################################################
	
	# ensure consistent preference settings
	Prefs.blackBackground = False;

	# prompt user for input parameters
	params = mbui.analysis_parameters_gui();

	# prompt user for file locations
	file_path, output_folder = mbio.file_location_chooser(params.input_image_path);
	params.setInputImagePath(file_path);
	params.setOutputPath(output_folder);

	# get image file
	import_opts, params = mbui.choose_series(file_path, params);
	imps = bf.openImagePlus(import_opts);
	imp = imps[0];

	# catch unexpected image dimensions - for now, project in Z...:
	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, crop_params = mbui.crop_to_ROI(imp, params);
	if crop_params is not None:
		params.perform_spatial_crop = True;
		mbui.autoset_zoom(imp);
	else:
		params.perform_spatial_crop = False;


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

	repeats = 1;
	inner_outer_comparisons = None;
	if params.inner_outer_comparison:
		inner_outer_comparisons = InnerOuterComparisonData();
		repeats = 2;

	IJ.selectWindow(imp.getTitle());
	IJ.run("Enhance Contrast", "saturated=0.35");
	for r in range(0, repeats):
		calculated_objects = CalculatedObjects();
		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())];
		calculated_objects, params, split_channels = mbfs.generate_edges(imp, params, calculated_objects, (r+1)/repeats);
		membrane_channel_imp = split_channels[0];
		actin_channel_imp = split_channels[1];
		segmentation_channel_imp = split_channels[2];

		calculated_objects = mbfs.calculate_outputs(params,
													calculated_objects, 
													split_channels, 
													repeat_fraction=(r+1)/repeats);
						
		# 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 or (params.inner_outer_comparison and r!=(repeats-1)):
			for fig_imp in fig_imp_list:
				fig_imp.close();
		elif params.close_on_completion and (r==(repeats-1)):
			imp.close();
	
	if params.inner_outer_comparison:
		tname = "Time, " + params.interval_unit;
		output_folder = os.path.dirname(params.output_path);
		profile = [[((inner, outer), (float(outer)/inner)) for inner, outer in zip(calculated_objects.inner_outer_data.inner_means, calculated_objects.inner_outer_data.outer_means)]];
		mbio.save_profile_as_csv(profile, 
								os.path.join(output_folder, "Intensity ratios.csv"), 
								"outer/inner", 
								xname="inner", 
								yname="outer",
								tname=tname, 
								time_list=calculated_objects.timelist);
		sd_profile = [[((inner, outer), (float(outer)/inner)) for inner, outer in zip(calculated_objects.inner_outer_data.inner_sds, calculated_objects.inner_outer_data.outer_sds)]];
		mbio.save_profile_as_csv(profile, 
								os.path.join(output_folder, "Intensity standard deviation ratios.csv"), 
								"outer sd/inner sd", 
								xname="inner sd", 
								yname="outer sd",
								tname=tname, 
								time_list=calculated_objects.timelist);
	return;
    #    return
    # Prevent further propagation of the key event:
    keyEvent.consume()


# MAIN code
imp = IJ.getImage()
killIt = False
if imp.getHeight() == 1024:  # half-chip size
    hOffset = 512
elif imp.getHeight() == 2048:  #full-chip image
    hOffset = 0
else:
    gdGoodBye = GenericDialog("Dimensions error")
    gdGoodBye.addMessage(
        'Image must be 2048x2048, or 2048x1024 pixels! \n I retire!')
    gdGoodBye.showDialog()
    killIt = True

if not killIt:
    IJ.setTool(Toolbar.RECTANGLE)
    manager = RoiManager.getInstance()
    if manager is None:
        manager = RoiManager()
    reset()
    listener = ML()
    keyLis = ListenToKey()
    win = imp.getWindow()
    win.getCanvas().addMouseListener(listener)
    win.getCanvas().addKeyListener(keyLis)
Exemple #33
0
        for time in timepoint_list:
            imp.setT(time)
            if channel == 1:
                background = selection_mean()
                background_c1.append(background)
            if channel == 2:
                background = selection_mean()
                background_c2.append(background)
    return background_c1, background_c2


background_c1 = []
background_c2 = []
if back_state == 'optional':
    print("optional")
    IJ.setTool("oval")
    region = "Select Background"
    selection(region)
    imp = IJ.getImage()
    roi_bck = imp.getRoi()
    background_c1, background_c2 = background_assay()
if back_state != 'optional':
    print("not Optional")
    with open(back_state, 'r') as csvfile:
        csvreader = csv.reader(csvfile)
        for row in csvreader:
            background_c1.append(float(row[0]))
            background_c2.append(float(row[1]))

# ok we can now access these variables.
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
metadata_file_path = os.path.splitext(image_file_path)[0] + ".txt"
metadata = import_iq3_metadata(metadata_file_path)
#imp2 = HyperStackConverter.toHyperStack(imp, int(metadata['n_channels']), int(metadata['z_pixels']), 1, "Composite");
print(metadata)
IJ.run(
    imp, "Properties...", "channels=" + str(int(metadata['n_channels'])) +
    " slices=" + str(int(metadata['z_pixels'])) + " frames=1 unit=" +
    str(metadata['x_unit']) + " pixel_width=" +
    str(metadata['x_physical_size']) + " pixel_height=" +
    str(metadata['y_physical_size']) + " voxel_depth=" +
    str(metadata['z_extent'] / metadata['z_pixels']))
imp.show()
imp, z_lims = z_crop(imp)
use_ch = imp.getC()
print(use_ch)
IJ.setTool("rect")
imp.hide()
imp2 = ZProjector.run(imp, "max")
imp2.show()
imp2.setC(use_ch + 1)
WaitForUserDialog("Select XY region to crop...").show()
crop_roi = imp2.getRoi()
imp2.close()
imp.show()
imp.setRoi(crop_roi)
IJ.run("Crop", "")
frames = imp.getNFrames()
slices = imp.getNSlices()
imp = Duplicator().run(imp, use_ch + 1, use_ch + 1, 1, slices, 1, frames)
imp.show()