def gfp_analysis(imp, file_name, output_folder): """perform analysis based on gfp intensity thresholding""" cal = imp.getCalibration() channel_imps = ChannelSplitter.split(imp) gfp_imp = channel_imps[0] gfp_imp.setTitle("GFP") threshold_imp = Duplicator().run(gfp_imp) threshold_imp.setTitle("GFP_threshold_imp") ecad_imp = channel_imps[1] ecad_imp.setTitle("E-cadherin") nuc_imp = channel_imps[2] IJ.run(threshold_imp, "Make Binary", "method=Otsu background=Dark calculate") IJ.run(threshold_imp, "Fill Holes", "") erode_count = 2 for _ in range(erode_count): IJ.run(threshold_imp, "Erode", "") threshold_imp = keep_blobs_bigger_than(threshold_imp, min_size_pix=1000) threshold_imp = my_kill_borders(threshold_imp) rois = generate_cell_rois(threshold_imp) out_stats = generate_cell_shape_results(rois, gfp_imp, cal, file_name) print("Number of cells identified = {}".format(len(out_stats))) threshold_imp.changes = False threshold_imp.close() # 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
def get_no_nuclei_fully_enclosed(roi, full_nuclei_imp, overlap_threshold=0.65): """for a given cell roi and ImagePlus with binary nuclei, return how many nuclei lie ENTIRELY within the cell""" bbox = roi.getBounds() full_nuclei_imp.setRoi(roi) cropped_nuc_imp = full_nuclei_imp.crop() roi.setLocation(0, 0) cropped_nuc_imp.setRoi(roi) cropped_nuc_imp.killRoi() roim = RoiManager(False) mxsz = cropped_nuc_imp.getWidth() * cropped_nuc_imp.getHeight() pa = ParticleAnalyzer( ParticleAnalyzer.ADD_TO_MANAGER, ParticleAnalyzer.AREA | ParticleAnalyzer.SLICE | ParticleAnalyzer.CENTROID, None, 0, mxsz) pa.setRoiManager(roim) pa.analyze(cropped_nuc_imp) cell_imp = IJ.createImage("Cell binary", cropped_nuc_imp.getWidth(), cropped_nuc_imp.getHeight(), 1, 8) IJ.run(cell_imp, "Select All", "") IJ.run(cell_imp, "Set...", "value=0 slice") cell_imp.setRoi(roi) IJ.run(cell_imp, "Set...", "value=255 slice") no_enclosed_nuclei = 0 for idx, nuc_roi in enumerate(roim.getRoisAsArray()): test_imp = Duplicator().run(cell_imp) test_imp.setRoi(nuc_roi) IJ.run(test_imp, "Set...", "value=255 slice") test_imp.killRoi() IJ.run(test_imp, "Create Selection", "") IJ.run(test_imp, "Make Inverse", "") test_roi = test_imp.getRoi() test_roi_stats = test_roi.getStatistics() cell_roi_stats = roi.getStatistics() nuc_roi_stats = nuc_roi.getStatistics() if test_roi_stats.area < ( cell_roi_stats.area + (1 - overlap_threshold) * nuc_roi_stats.area ): # i.e. if more than (100*overlap_threshold)% of nucleus is inside cell... no_enclosed_nuclei += 1 test_imp.changes = False test_imp.close() roi.setLocation(bbox.getX(), bbox.getY()) cropped_nuc_imp.changes = False cropped_nuc_imp.close() cell_imp.changes = False cell_imp.close() return no_enclosed_nuclei
def cut(event): roi = imp.getRoi() if roi != None: newRoi = roi.clone() Dup = Duplicator().run(imp, 1, imp.getNChannels(), 1, imp.getNSlices(), 1, imp.getNFrames()) newRoi.setLocation(0,0) Dup.setRoi(newRoi) Dup.setTitle(Men.getTextField() + str(Men.getCounter())) Dup.show() #Men.setCounter() Men.addOlay(roi) imp.setOverlay(Men.getOverlay()) #setOverlay(Roi roi, java.awt.Color strokeColor, int strokeWidth, java.awt.Color fillColor) imp.getOverlay().drawLabels(True) # drawNumbers imp.deleteRoi() #make cell instance and add to position instance p.addCell(cell(p.getMainPath(), p, Men.getCounter(), Dup)) # cell(mainPath, position, ID, imp): Dup.close() Men.increaseCounter()
def cross_planes_approx_median_filter(stack_imp, filter_radius_um=5.0): """relatively computationally cheap, slightly crude approximation of median filter""" title = stack_imp.getTitle(); xy_imp = Duplicator().run(stack_imp); xy_imp.setTitle("xy {}".format(title)); xz_imp = Duplicator().run(stack_imp); xz_imp.setTitle("xz {}".format(title)); xz_imp = rot3d(xz_imp, 'x'); zy_imp = Duplicator().run(stack_imp); zy_imp.setTitle("zy {}".format(title)); zy_imp = rot3d(zy_imp, 'y'); stack_imp.changes = False; stack_imp.close(); xy_imp = stack_median_filter(xy_imp, radius_um=filter_radius_um); xz_imp = stack_median_filter(xz_imp, radius_um=filter_radius_um); zy_imp = stack_median_filter(zy_imp, radius_um=filter_radius_um); xz_imp = rot3d(xz_imp, 'x'); zy_imp = rot3d(zy_imp, '-y'); ic = ImageCalculator(); dummy = ic.run("Add create 32-bit stack", xy_imp, xz_imp); xz_imp.close(); xy_imp.close(); output_imp = ic.run("Add create 32-bit stack", dummy, zy_imp); zy_imp.close(); dummy.close(); output_imp.show(); IJ.run(output_imp, "Divide...", "value=3 stack"); output_imp.setTitle("Cross-plane median filtered {} (r={} um)".format(title, filter_radius_um).replace(".tif", "")); print("Image size after applying approx median filter = ({}x{}x{})".format(output_imp.getWidth(), output_imp.getHeight(), output_imp.getNSlices())); return output_imp;
def split_and_rotate(imp, info): """return image to segment on, image to project out, and images to display""" # for now, assume that these are ISVs and that embryo is mounted in familiar fashion. First of these can be developed out... print("Image dimensions at start of split and rotate = ({}x{}x{}) pix". format(imp.getWidth(), imp.getHeight(), imp.getNSlices())) if imp.isVisible(): IJ.run("Enhance Contrast", "saturated=0.35") seg_ch_idx, proj_ch_idx = ui.choose_segmentation_and_projection_channels( info) channels = ChannelSplitter().split(imp) seg_imp = Duplicator().run(channels[seg_ch_idx]) # use Duplicator to decouple - can do smarter to save memory? proj_imp = Duplicator().run(channels[proj_ch_idx]) rot_seg_imp = utils.rot3d(seg_imp, axis='x') rot_seg_imp.setTitle("rot_seg_imp") rot_proj_imp = utils.rot3d(proj_imp, axis='x') rot_proj_imp.setTitle("rot_proj_imp") egfp_mch_imps = [] egfp_idx = 0 if "gfp" in info.ch1_label.lower() else 1 mch_idx = int(not (egfp_idx)) # assume two channel... for ch_idx in [egfp_idx, mch_idx]: if ch_idx == seg_ch_idx: egfp_mch_imps.append(Duplicator().run(rot_seg_imp)) elif ch_idx == proj_ch_idx: egfp_mch_imps.append(Duplicator().run(rot_proj_imp)) else: egfp_mch_imps.append( utils.rot3d(Duplicator().run(channels[ch_idx]), axis='x')) imp.changes = False imp.close() seg_imp.changes = False proj_imp.changes = False seg_imp.close() proj_imp.close() print("Image dimensions at start of split and rotate = ({}x{}x{}) pix". format(rot_proj_imp.getWidth(), rot_proj_imp.getHeight(), rot_proj_imp.getNSlices())) return rot_seg_imp, rot_proj_imp, egfp_mch_imps
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 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
def runOneFile(fullFilePath): global gNumChannels global gAlignBatchVersion if not os.path.isfile(fullFilePath): bPrintLog( '\nERROR: runOneFile() did not find file: ' + fullFilePath + '\n', 0) return 0 bPrintLog( time.strftime("%H:%M:%S") + ' starting runOneFile(): ' + fullFilePath, 1) enclosingPath = os.path.dirname(fullFilePath) head, tail = os.path.split(enclosingPath) enclosingPath += '/' #make output folders destFolder = enclosingPath + tail + '_channels/' if not os.path.isdir(destFolder): os.makedirs(destFolder) destMaxFolder = destFolder + 'max/' if not os.path.isdir(destMaxFolder): os.makedirs(destMaxFolder) if gDoAlign: destAlignmentFolder = destFolder + 'alignment/' if not os.path.isdir(destAlignmentFolder): os.makedirs(destAlignmentFolder) if gSave8bit: eightBitFolder = destFolder + 'channels8/' if not os.path.isdir(eightBitFolder): os.makedirs(eightBitFolder) eightBitMaxFolder = eightBitFolder + 'max/' if not os.path.isdir(eightBitMaxFolder): os.makedirs(eightBitMaxFolder) # open image imp = Opener().openImage(fullFilePath) # get parameters of image (width, height, nChannels, nSlices, nFrames) = imp.getDimensions() bitDepth = imp.getBitDepth() infoStr = imp.getProperty("Info") #get all .tif tags if not infoStr: infoStr = '' infoStr += 'bAlignBatch_Version=' + str(gAlignBatchVersion) + '\n' infoStr += 'bAlignBatch_Time=' + time.strftime( "%Y%m%d") + '_' + time.strftime("%H%M%S") + '\n' msgStr = 'w:' + str(width) + ' h:' + str(height) + ' slices:' + str(nSlices) \ + ' channels:' + str(nChannels) + ' frames:' + str(nFrames) + ' bitDepth:' + str(bitDepth) bPrintLog(msgStr, 1) path, filename = os.path.split(fullFilePath) shortName, fileExtension = os.path.splitext(filename) # # look for num channels in ScanImage infoStr if gGetNumChanFromScanImage: for line in infoStr.split('\n'): #scanimage.SI4.channelsSave = [1;2] scanimage4 = find(line, 'scanimage.SI4.channelsSave =') == 0 #state.acq.numberOfChannelsSave=2 scanimage3 = find(line, 'state.acq.numberOfChannelsSave=') == 0 if scanimage3: #print 'line:', line equalIdx = find(line, '=') line2 = line[equalIdx + 1:] if gGetNumChanFromScanImage: gNumChannels = int(line2) bPrintLog( 'over-riding gNumChannels with: ' + str(gNumChannels), 2) if scanimage4: #print ' we have a scanimage 4 file ... now i need to exptract the number of channel' #print 'line:', line equalIdx = find(line, '=') line2 = line[equalIdx + 1:] for delim in ';[]': line2 = line2.replace(delim, ' ') if gGetNumChanFromScanImage: gNumChannels = len(line2.split()) bPrintLog( 'over-riding gNumChannels with: ' + str(gNumChannels), 2) # show imp.show() # split channels if necc. and grab the original window names if gNumChannels == 1: origImpWinStr = imp.getTitle() #use this when only one channel origImpWin = WindowManager.getWindow( origImpWinStr) #returns java.awt.Window if gNumChannels == 2: winTitle = imp.getTitle() bPrintLog('Deinterleaving 2 channels...', 1) IJ.run('Deinterleave', 'how=2 keep') #makes ' #1' and ' #2', with ' #2' frontmost origCh1WinStr = winTitle + ' #1' origCh2WinStr = winTitle + ' #2' origCh1Imp = WindowManager.getImage(origCh1WinStr) origCh2Imp = WindowManager.getImage(origCh2WinStr) origCh1File = destFolder + shortName + '_ch1.tif' origCh2File = destFolder + shortName + '_ch2.tif' # work on a copy, mostly for alignment with cropping copy = Duplicator().run(imp) #copy.copyAttributes(imp) #don't copy attributes, it copies the name (which we do not want) copy.show() # # crop (on copy) if gDoCrop: bPrintLog('making cropping rectangle (left,top,width,height) ', 1) bPrintLog( str(gCropLeft) + ' ' + str(gCropTop) + ' ' + str(gCropWidth) + ' ' + str(gCropHeight), 2) roi = Roi(gCropLeft, gCropTop, gCropWidth, gCropHeight) #left,top,width,height copy.setRoi(roi) time.sleep( 0.5 ) # otherwise, crop SOMETIMES failes. WHAT THE F**K FIJI DEVELOPERS, REALLY, WHAT THE F**K #bPrintLog('cropping', 1) IJ.run('Crop') infoStr += 'bCropping=' + str(gCropLeft) + ',' + str( gCropTop) + ',' + str(gCropWidth) + ',' + str(gCropHeight) + '\n' # # remove calibration ( on original) if gRemoveCalibration: cal = imp.getCalibration() calCoeff = cal.getCoefficients() if calCoeff: msgStr = 'Calibration is y=a+bx' + ' a=' + str( calCoeff[0]) + ' b=' + str(calCoeff[1]) bPrintLog(msgStr, 1) #remove calibration bPrintLog('\tRemoving Calibration', 2) imp.setCalibration(None) #without these, 8-bit conversion goes to all 0 !!! what the f**k !!! #bPrintLog('calling imp.resetStack() and imp.resetDisplayRange()', 2) imp.resetStack() imp.resetDisplayRange() #get and print out min/max origMin = StackStatistics(imp).min origMax = StackStatistics(imp).max msgStr = '\torig min=' + str(origMin) + ' max=' + str(origMax) bPrintLog(msgStr, 2) # 20150723, 'shift everybody over by linear calibration intercept calCoeff[0] - (magic number) if 1: # [1] was this #msgStr = 'Subtracting original min '+str(origMin) + ' from stack.' #bPrintLog(msgStr, 2) #subArgVal = 'value=%s stack' % (origMin,) #IJ.run('Subtract...', subArgVal) # [2] now this #msgStr = 'Adding calCoeff[0] '+str(calCoeff[0]) + ' from stack.' #bPrintLog(msgStr, 2) #addArgVal = 'value=%s stack' % (int(calCoeff[0]),) #IJ.run('Add...', addArgVal) # [3] subtract a magic number 2^15-2^7 = 32768 - 128 magicNumber = gLinearShift #2^15 - 128 msgStr = 'Subtracting a magic number (linear shift) ' + str( magicNumber) + ' from stack.' bPrintLog(msgStr, 2) infoStr += 'bLinearShift=' + str(gLinearShift) + '\n' subArgVal = 'value=%s stack' % (gLinearShift, ) IJ.run(imp, 'Subtract...', subArgVal) # 20150701, set any pixel <0 to 0 if 0: ip = imp.getProcessor() # returns a reference pixels = ip.getPixels() # returns a reference msgStr = '\tSet all pixels <0 to 0. This was added 20150701 ...' bPrintLog(msgStr, 2) pixels = map(lambda x: 0 if x < 0 else x, pixels) bPrintLog('\t\t... done', 2) #get and print out min/max newMin = StackStatistics(imp).min newMax = StackStatistics(imp).max msgStr = '\tnew min=' + str(newMin) + ' max=' + str(newMax) bPrintLog(msgStr, 2) #append calibration to info string infoStr += 'bCalibCoeff_a = ' + str(calCoeff[0]) + '\n' infoStr += 'bCalibCoeff_b = ' + str(calCoeff[1]) + '\n' infoStr += 'bNewMin = ' + str(newMin) + '\n' infoStr += 'bNewMax = ' + str(newMax) + '\n' # # set up if gNumChannels == 1: impWinStr = copy.getTitle() #use this when only one channel impWin = WindowManager.getWindow(impWinStr) #returns java.awt.Window if gNumChannels == 2: winTitle = copy.getTitle() bPrintLog('Deinterleaving 2 channels...', 1) IJ.run('Deinterleave', 'how=2 keep') #makes ' #1' and ' #2', with ' #2' frontmost ch1WinStr = winTitle + ' #1' ch2WinStr = winTitle + ' #2' ch1Imp = WindowManager.getImage(ch1WinStr) ch2Imp = WindowManager.getImage(ch2WinStr) ch1File = destFolder + shortName + '_ch1.tif' ch2File = destFolder + shortName + '_ch2.tif' # # alignment if gDoAlign and gNumChannels == 1 and copy.getNSlices() > 1: infoStr += 'AlignOnChannel=1' + '\n' #snap to middle slice if gAlignOnMiddleSlice: middleSlice = int( math.floor(copy.getNSlices() / 2)) #int() is necc., python is f*****g picky else: middleSlice = gAlignOnThisSlice copy.setSlice(middleSlice) transformationFile = destAlignmentFolder + shortName + '.txt' bPrintLog('MultiStackReg aligning:' + impWinStr, 1) stackRegParams = 'stack_1=[%s] action_1=Align file_1=[%s] stack_2=None action_2=Ignore file_2=[] transformation=[Rigid Body] save' % ( impWin, transformationFile) IJ.run('MultiStackReg', stackRegParams) infoStr += 'AlignOnSlice=' + str(middleSlice) + '\n' #20150723, we just aligned on a cropped copy, apply alignment to original imp origImpTitle = imp.getTitle() stackRegParams = 'stack_1=[%s] action_1=[Load Transformation File] file_1=[%s] stack_2=None action_2=Ignore file_2=[] transformation=[Rigid Body]' % ( origImpTitle, transformationFile) IJ.run('MultiStackReg', stackRegParams) if gDoAlign and gNumChannels == 2 and ch1Imp.getNSlices( ) > 1 and ch2Imp.getNSlices() > 1: #apply to gAlignThisChannel alignThisWindow = '' applyAlignmentToThisWindow = '' if gAlignThisChannel == 1: infoStr += 'AlignOnChannel=1' + '\n' transformationFile = destAlignmentFolder + shortName + '_ch1.txt' alignThisWindow = ch1WinStr applyAlignmentToThisWindow = ch2WinStr else: infoStr += 'AlignOnChannel=2' + '\n' transformationFile = destAlignmentFolder + shortName + '_ch2.txt' alignThisWindow = ch2WinStr applyAlignmentToThisWindow = ch1WinStr alignThisImp = WindowManager.getImage(alignThisWindow) #snap to middle slice if gAlignOnMiddleSlice: middleSlice = int( math.floor(alignThisImp.getNSlices() / 2)) #int() is necc., python is f*****g picky else: middleSlice = gAlignOnThisSlice alignThisImp.setSlice(middleSlice) infoStr += 'bAlignOnSlice=' + str(middleSlice) + '\n' bPrintLog('MultiStackReg aligning:' + alignThisWindow, 1) stackRegParams = 'stack_1=[%s] action_1=Align file_1=[%s] stack_2=None action_2=Ignore file_2=[] transformation=[Rigid Body] save' % ( alignThisWindow, transformationFile) IJ.run('MultiStackReg', stackRegParams) # 20150723, we just aligned on a copy, apply alignment to both channels of original # ch1 bPrintLog('MultiStackReg applying alignment to:' + origCh1WinStr, 1) stackRegParams = 'stack_1=[%s] action_1=[Load Transformation File] file_1=[%s] stack_2=None action_2=Ignore file_2=[] transformation=[Rigid Body]' % ( origCh1WinStr, transformationFile) IJ.run('MultiStackReg', stackRegParams) # ch2 bPrintLog('MultiStackReg applying alignment to:' + origCh2WinStr, 1) stackRegParams = 'stack_1=[%s] action_1=[Load Transformation File] file_1=[%s] stack_2=None action_2=Ignore file_2=[] transformation=[Rigid Body]' % ( origCh2WinStr, transformationFile) IJ.run('MultiStackReg', stackRegParams) #apply alignment to other window #bPrintLog('MultiStackReg applying alignment to:' + applyAlignmentToThisWindow, 1) #applyAlignThisImp = WindowManager.getImage(applyAlignmentToThisWindow) #stackRegParams = 'stack_1=[%s] action_1=[Load Transformation File] file_1=[%s] stack_2=None action_2=Ignore file_2=[] transformation=[Rigid Body]' %(applyAlignmentToThisWindow,transformationFile) #IJ.run('MultiStackReg', stackRegParams) elif gDoAlign: bPrintLog('Skipping alignment, there may be only one slice?', 3) # # save if gNumChannels == 1: imp.setProperty("Info", infoStr) impFile = destFolder + shortName + '.tif' #bPrintLog('Saving:' + impFile, 1) bSaveStack(imp, impFile) #max project bSaveZProject(imp, destMaxFolder, shortName) if gNumChannels == 2: #ch1 origCh1Imp.setProperty("Info", infoStr) #bPrintLog('Saving:' + ch1File, 1) bSaveStack(origCh1Imp, ch1File) #max project bSaveZProject(origCh1Imp, destMaxFolder, shortName + '_ch1') #ch2 origCh2Imp.setProperty("Info", infoStr) #bPrintLog('Saving:' + ch2File, 1) bSaveStack(origCh2Imp, ch2File) #max project bSaveZProject(origCh2Imp, destMaxFolder, shortName + '_ch2') # # post convert to 8-bit and save if gSave8bit: if bitDepth == 16: if gNumChannels == 1: bPrintLog('Converting to 8-bit:' + impWinStr, 1) IJ.selectWindow(impWinStr) #IJ.run('resetMinAndMax()') IJ.run("8-bit") impFile = eightBitFolder + shortName + '.tif' bPrintLog('Saving 8-bit:' + impFile, 2) bSaveStack(imp, impFile) #max project bSaveZProject(imp, eightBitMaxFolder, shortName) if gNumChannels == 2: # bPrintLog('Converting to 8-bit:' + origCh1WinStr, 1) IJ.selectWindow(origCh1WinStr) IJ.run("8-bit") impFile = eightBitFolder + shortName + '_ch1.tif' bPrintLog('Saving 8-bit:' + impFile, 2) bSaveStack(origCh1Imp, impFile) #max project bSaveZProject(origCh1Imp, eightBitMaxFolder, shortName + '_ch1') # bPrintLog('Converting to 8-bit:' + origCh2WinStr, 1) IJ.selectWindow(origCh2WinStr) #IJ.run('resetMinAndMax()') IJ.run("8-bit") impFile = eightBitFolder + shortName + '_ch2.tif' bPrintLog('Saving 8-bit:' + impFile, 2) bSaveStack(origCh2Imp, impFile) #max project bSaveZProject(origCh2Imp, eightBitMaxFolder, shortName + '_ch2') # # close original window imp.changes = 0 imp.close() #copy copy.changes = 0 copy.close() # # close ch1/ch2 if gNumChannels == 2: #original origCh1Imp.changes = 0 origCh1Imp.close() origCh2Imp.changes = 0 origCh2Imp.close() #copy ch1Imp.changes = 0 ch1Imp.close() ch2Imp.changes = 0 ch2Imp.close() bPrintLog( time.strftime("%H:%M:%S") + ' finished runOneFile(): ' + fullFilePath, 1)
centers.append([xcenter, ycenter]) # print("Spot "+str(count)+" center: "+str(centers[count])) count += 1 # work on a copy of the image from ij.plugin import Duplicator imp2 = Duplicator().run(imp, 1, channels, 1, 1, 1, 1) # clear the existing channel imp2.setDisplayMode(IJ.COLOR) imp2.setC(targetChannel) IJ.run(imp2, "Select All", "") IJ.setBackgroundColor(0, 0, 0) IJ.run(imp2, "Clear", "slice") # draw white circles to simulate cells IJ.setForegroundColor(255, 255, 255) for point in centers: drawSpot(point, celldiam) # save the simulated image IJ.saveAs(imp2, "Tiff", os.path.join(srcDir, basename + " sim " + str(trial) + ".tif")) imp2.close() # print("Finished simulations.") # close the original imp.close()
#imp.getCalibration() # DBG if crop_image: imp.setRoi(int(xLoc-math.floor(winCrop/2)),int(yLoc-math.floor(winCrop/2)),winCrop,winCrop) # Create a ROI and crop it. else: imp.setRoi(0,0,imp.width,imp.height) # Create a ROI and crop it. crop = imp.crop("stack") ij.process.ImageConverter(crop).convertToGray32() tmp1 = Duplicator().run(crop, chDNA, chDNA, 1, crop.getNSlices(), 1, crop.getNFrames()) #Stack.setChannel(chDNA); run("Duplicate...", "channels=2 title=cropDNA duplicate"); tmp2 = Duplicator().run(crop, chDNA, chDNA, 1, crop.getNSlices(), 1, crop.getNFrames()) #run("Duplicate...", "title=tmp2 duplicate"); # === Band pass filtering IJ.run(tmp1, "Gaussian Blur...", "sigma=%f stack" % sd1) #selectWindow("tmp1"); run("Gaussian Blur...", "sigma="+sd1+" stack"); IJ.run(tmp2, "Gaussian Blur...", "sigma=%f stack" % sd2) #selectWindow("tmp2"); run("Gaussian Blur...", "sigma="+sd2+" stack"); cropDNA_bPass = ImageCalculator().run("Subtract create 32-bit stack", tmp1, tmp2) #imageCalculator("Subtract create 32-bit stack", "tmp1","tmp2"); rename("cropDNA_bPass"); tmp1.close() tmp2.close() # === Create stack to be processed # From https://stackoverflow.com/questions/48213759/combine-channels-in-imagej-jython crop_channels = ij.plugin.ChannelSplitter.split(crop) # selectWindow("crop"); run("Split Channels"); if len(crop_channels)>=2: res_st = ij.plugin.RGBStackMerge().mergeHyperstacks([cropDNA_bPass, ]+[c for c in crop_channels], True) #run("Merge Channels...", "c1=cropDNA_bPass c2=C1-crop c3=C2-crop create") else : IJ.log("NOT IMPLEMENTED ERROR") raise NotImplementedError # === 3D drift correction (we are working with res_st as input image) res_st.setRoi(int(winCrop/2)-int(winDrift/2), int(winCrop/2)-int(winDrift/2), winDrift, winDrift) if run_DC: dc_st = correctDrift.run_cli(res_st, only_compute=False, multi_time_scale=False, verbose=False)
def runOneFile(fullFilePath): global gFileType global gNumChannels global gAlignBatchVersion if not os.path.isfile(fullFilePath): bPrintLog('\nERROR: runOneFile() did not find file: ' + fullFilePath + '\n',0) return 0 bPrintLog(time.strftime("%H:%M:%S") + ' starting runOneFile(): ' + fullFilePath, 1) enclosingPath = os.path.dirname(fullFilePath) head, tail = os.path.split(enclosingPath) enclosingPath += '/' #make output folders destFolder = enclosingPath + tail + '_channels/' if not os.path.isdir(destFolder): os.makedirs(destFolder) destMaxFolder = destFolder + 'max/' if not os.path.isdir(destMaxFolder): os.makedirs(destMaxFolder) if gDoAlign: destAlignmentFolder = destFolder + 'alignment/' if not os.path.isdir(destAlignmentFolder): os.makedirs(destAlignmentFolder) if gSave8bit: eightBitFolder = destFolder + 'channels8/' if not os.path.isdir(eightBitFolder): os.makedirs(eightBitFolder) eightBitMaxFolder = eightBitFolder + 'max/' if not os.path.isdir(eightBitMaxFolder): os.makedirs(eightBitMaxFolder) if gFileType=='tif': # open .tif image imp = Opener().openImage(fullFilePath) else: # open .lsm cmdStr = 'open=%s autoscale color_mode=Default view=Hyperstack stack_order=XYCZT' % (fullFilePath,) IJ.run('Bio-Formats Importer', cmdStr) lsmpath, lsmfilename = os.path.split(fullFilePath) lsWindow = lsmfilename imp = WindowManager.getImage(lsWindow) # get parameters of image (width, height, nChannels, nSlices, nFrames) = imp.getDimensions() bitDepth = imp.getBitDepth() infoStr = imp.getProperty("Info") #get all .tif tags if not infoStr: infoStr = '' infoStr += 'bAlignBatch_Version=' + str(gAlignBatchVersion) + '\n' infoStr += 'bAlignBatch_Time=' + time.strftime("%Y%m%d") + '_' + time.strftime("%H%M%S") + '\n' msgStr = 'w:' + str(width) + ' h:' + str(height) + ' slices:' + str(nSlices) \ + ' channels:' + str(nChannels) + ' frames:' + str(nFrames) + ' bitDepth:' + str(bitDepth) bPrintLog(msgStr, 1) path, filename = os.path.split(fullFilePath) shortName, fileExtension = os.path.splitext(filename) # # look for num channels in ScanImage infoStr if gGetNumChanFromScanImage: for line in infoStr.split('\n'): #scanimage.SI4.channelsSave = [1;2] scanimage4 = find(line, 'scanimage.SI4.channelsSave =') == 0 #state.acq.numberOfChannelsSave=2 scanimage3 = find(line, 'state.acq.numberOfChannelsSave=') == 0 if scanimage3: #print 'line:', line equalIdx = find(line, '=') line2 = line[equalIdx+1:] if gGetNumChanFromScanImage: gNumChannels = int(line2) bPrintLog('over-riding gNumChannels with: ' + str(gNumChannels), 2) if scanimage4: #print ' we have a scanimage 4 file ... now i need to exptract the number of channel' #print 'line:', line equalIdx = find(line, '=') line2 = line[equalIdx+1:] for delim in ';[]': line2 = line2.replace(delim, ' ') if gGetNumChanFromScanImage: gNumChannels = len(line2.split()) bPrintLog('over-riding gNumChannels with: ' + str(gNumChannels), 2) # show imp.show() # split channels if necc. and grab the original window names if gNumChannels == 1: origImpWinStr = imp.getTitle() #use this when only one channel origImpWin = WindowManager.getWindow(origImpWinStr) #returns java.awt.Window if gNumChannels == 2: winTitle = imp.getTitle() bPrintLog('Deinterleaving 2 channels...', 1) IJ.run('Deinterleave', 'how=2 keep') #makes ' #1' and ' #2', with ' #2' frontmost origCh1WinStr = winTitle + ' #1' origCh2WinStr = winTitle + ' #2' origCh1Imp = WindowManager.getImage(origCh1WinStr) origCh2Imp = WindowManager.getImage(origCh2WinStr) origCh1File = destFolder + shortName + '_ch1.tif' origCh2File = destFolder + shortName + '_ch2.tif' # work on a copy, mostly for alignment with cropping copy = Duplicator().run(imp) #copy.copyAttributes(imp) #don't copy attributes, it copies the name (which we do not want) copy.show() # # crop (on copy) if gDoCrop: bPrintLog('making cropping rectangle (left,top,width,height) ',1) bPrintLog(str(gCropLeft) + ' ' + str(gCropTop) + ' ' +str(gCropWidth) + ' ' +str(gCropHeight), 2) roi = Roi(gCropLeft, gCropTop, gCropWidth, gCropHeight) #left,top,width,height copy.setRoi(roi) time.sleep(0.5) # otherwise, crop SOMETIMES failes. WHAT THE F**K FIJI DEVELOPERS, REALLY, WHAT THE F**K #bPrintLog('cropping', 1) IJ.run('Crop') infoStr += 'bCropping=' + str(gCropLeft) + ',' + str(gCropTop) + ',' + str(gCropWidth) + ',' + str(gCropHeight) + '\n' # # remove calibration ( on original) if gRemoveCalibration: cal = imp.getCalibration() calCoeff = cal.getCoefficients() if calCoeff: msgStr = 'Calibration is y=a+bx' + ' a=' + str(calCoeff[0]) + ' b=' + str(calCoeff[1]) bPrintLog(msgStr, 1) #remove calibration bPrintLog('\tRemoving Calibration', 2) imp.setCalibration(None) #without these, 8-bit conversion goes to all 0 !!! what the f**k !!! #bPrintLog('calling imp.resetStack() and imp.resetDisplayRange()', 2) imp.resetStack() imp.resetDisplayRange() #get and print out min/max origMin = StackStatistics(imp).min origMax = StackStatistics(imp).max msgStr = '\torig min=' + str(origMin) + ' max=' + str(origMax) bPrintLog(msgStr, 2) # 20150723, 'shift everybody over by linear calibration intercept calCoeff[0] - (magic number) if 1: # [1] was this #msgStr = 'Subtracting original min '+str(origMin) + ' from stack.' #bPrintLog(msgStr, 2) #subArgVal = 'value=%s stack' % (origMin,) #IJ.run('Subtract...', subArgVal) # [2] now this #msgStr = 'Adding calCoeff[0] '+str(calCoeff[0]) + ' from stack.' #bPrintLog(msgStr, 2) #addArgVal = 'value=%s stack' % (int(calCoeff[0]),) #IJ.run('Add...', addArgVal) # [3] subtract a magic number 2^15-2^7 = 32768 - 128 magicNumber = gLinearShift #2^15 - 128 msgStr = 'Subtracting a magic number (linear shift) '+str(magicNumber) + ' from stack.' bPrintLog(msgStr, 2) infoStr += 'bLinearShift=' + str(gLinearShift) + '\n' subArgVal = 'value=%s stack' % (gLinearShift,) IJ.run(imp, 'Subtract...', subArgVal) # 20150701, set any pixel <0 to 0 if 0: ip = imp.getProcessor() # returns a reference pixels = ip.getPixels() # returns a reference msgStr = '\tSet all pixels <0 to 0. This was added 20150701 ...' bPrintLog(msgStr, 2) pixels = map(lambda x: 0 if x<0 else x, pixels) bPrintLog('\t\t... done', 2) #get and print out min/max newMin = StackStatistics(imp).min newMax = StackStatistics(imp).max msgStr = '\tnew min=' + str(newMin) + ' max=' + str(newMax) bPrintLog(msgStr, 2) #append calibration to info string infoStr += 'bCalibCoeff_a = ' + str(calCoeff[0]) + '\n' infoStr += 'bCalibCoeff_b = ' + str(calCoeff[1]) + '\n' infoStr += 'bNewMin = ' + str(newMin) + '\n' infoStr += 'bNewMax = ' + str(newMax) + '\n' # # set up if gNumChannels == 1: impWinStr = copy.getTitle() #use this when only one channel impWin = WindowManager.getWindow(impWinStr) #returns java.awt.Window if gNumChannels == 2: winTitle = copy.getTitle() bPrintLog('Deinterleaving 2 channels...', 1) IJ.run('Deinterleave', 'how=2 keep') #makes ' #1' and ' #2', with ' #2' frontmost ch1WinStr = winTitle + ' #1' ch2WinStr = winTitle + ' #2' ch1Imp = WindowManager.getImage(ch1WinStr) ch2Imp = WindowManager.getImage(ch2WinStr) ch1File = destFolder + shortName + '_ch1.tif' ch2File = destFolder + shortName + '_ch2.tif' # # alignment if gDoAlign and gNumChannels == 1 and copy.getNSlices()>1: infoStr += 'AlignOnChannel=1' + '\n' #snap to middle slice if gAlignOnMiddleSlice: middleSlice = int(math.floor(copy.getNSlices() / 2)) #int() is necc., python is f*****g picky else: middleSlice = gAlignOnThisSlice copy.setSlice(middleSlice) transformationFile = destAlignmentFolder + shortName + '.txt' bPrintLog('MultiStackReg aligning:' + impWinStr, 1) stackRegParams = 'stack_1=[%s] action_1=Align file_1=[%s] stack_2=None action_2=Ignore file_2=[] transformation=[Rigid Body] save' %(impWin,transformationFile) IJ.run('MultiStackReg', stackRegParams) infoStr += 'AlignOnSlice=' + str(middleSlice) + '\n' #20150723, we just aligned on a cropped copy, apply alignment to original imp origImpTitle = imp.getTitle() stackRegParams = 'stack_1=[%s] action_1=[Load Transformation File] file_1=[%s] stack_2=None action_2=Ignore file_2=[] transformation=[Rigid Body]' %(origImpTitle,transformationFile) IJ.run('MultiStackReg', stackRegParams) if gDoAlign and gNumChannels == 2 and ch1Imp.getNSlices()>1 and ch2Imp.getNSlices()>1: #apply to gAlignThisChannel alignThisWindow = '' applyAlignmentToThisWindow = '' if gAlignThisChannel == 1: infoStr += 'AlignOnChannel=1' + '\n' transformationFile = destAlignmentFolder + shortName + '_ch1.txt' alignThisWindow = ch1WinStr applyAlignmentToThisWindow = ch2WinStr else: infoStr += 'AlignOnChannel=2' + '\n' transformationFile = destAlignmentFolder + shortName + '_ch2.txt' alignThisWindow = ch2WinStr applyAlignmentToThisWindow = ch1WinStr alignThisImp = WindowManager.getImage(alignThisWindow) #snap to middle slice if gAlignOnMiddleSlice: middleSlice = int(math.floor(alignThisImp.getNSlices() / 2)) #int() is necc., python is f*****g picky else: middleSlice = gAlignOnThisSlice alignThisImp.setSlice(middleSlice) infoStr += 'bAlignOnSlice=' + str(middleSlice) + '\n' bPrintLog('MultiStackReg aligning:' + alignThisWindow, 1) stackRegParams = 'stack_1=[%s] action_1=Align file_1=[%s] stack_2=None action_2=Ignore file_2=[] transformation=[Rigid Body] save' %(alignThisWindow,transformationFile) IJ.run('MultiStackReg', stackRegParams) # 20150723, we just aligned on a copy, apply alignment to both channels of original # ch1 bPrintLog('MultiStackReg applying alignment to:' + origCh1WinStr, 1) stackRegParams = 'stack_1=[%s] action_1=[Load Transformation File] file_1=[%s] stack_2=None action_2=Ignore file_2=[] transformation=[Rigid Body]' %(origCh1WinStr,transformationFile) IJ.run('MultiStackReg', stackRegParams) # ch2 bPrintLog('MultiStackReg applying alignment to:' + origCh2WinStr, 1) stackRegParams = 'stack_1=[%s] action_1=[Load Transformation File] file_1=[%s] stack_2=None action_2=Ignore file_2=[] transformation=[Rigid Body]' %(origCh2WinStr,transformationFile) IJ.run('MultiStackReg', stackRegParams) #apply alignment to other window #bPrintLog('MultiStackReg applying alignment to:' + applyAlignmentToThisWindow, 1) #applyAlignThisImp = WindowManager.getImage(applyAlignmentToThisWindow) #stackRegParams = 'stack_1=[%s] action_1=[Load Transformation File] file_1=[%s] stack_2=None action_2=Ignore file_2=[] transformation=[Rigid Body]' %(applyAlignmentToThisWindow,transformationFile) #IJ.run('MultiStackReg', stackRegParams) elif gDoAlign: bPrintLog('Skipping alignment, there may be only one slice?',3) # # save if gNumChannels == 1: imp.setProperty("Info", infoStr); impFile = destFolder + shortName + '.tif' #bPrintLog('Saving:' + impFile, 1) bSaveStack(imp, impFile) #max project bSaveZProject(imp, destMaxFolder, shortName) if gNumChannels == 2: #ch1 origCh1Imp.setProperty("Info", infoStr); #bPrintLog('Saving:' + ch1File, 1) bSaveStack(origCh1Imp, ch1File) #max project bSaveZProject(origCh1Imp, destMaxFolder, shortName+'_ch1') #ch2 origCh2Imp.setProperty("Info", infoStr); #bPrintLog('Saving:' + ch2File, 1) bSaveStack(origCh2Imp, ch2File) #max project bSaveZProject(origCh2Imp, destMaxFolder, shortName+'_ch2') # # post convert to 8-bit and save if gSave8bit: if bitDepth == 16: if gNumChannels == 1: bPrintLog('Converting to 8-bit:' + impWinStr, 1) IJ.selectWindow(impWinStr) #IJ.run('resetMinAndMax()') IJ.run("8-bit") impFile = eightBitFolder + shortName + '.tif' bPrintLog('Saving 8-bit:' + impFile, 2) bSaveStack(imp, impFile) #max project bSaveZProject(imp, eightBitMaxFolder, shortName) if gNumChannels == 2: # bPrintLog('Converting to 8-bit:' + origCh1WinStr, 1) IJ.selectWindow(origCh1WinStr) IJ.run("8-bit") impFile = eightBitFolder + shortName + '_ch1.tif' bPrintLog('Saving 8-bit:' + impFile, 2) bSaveStack(origCh1Imp, impFile) #max project bSaveZProject(origCh1Imp, eightBitMaxFolder, shortName+'_ch1') # bPrintLog('Converting to 8-bit:' + origCh2WinStr, 1) IJ.selectWindow(origCh2WinStr) #IJ.run('resetMinAndMax()') IJ.run("8-bit") impFile = eightBitFolder + shortName + '_ch2.tif' bPrintLog('Saving 8-bit:' + impFile, 2) bSaveStack(origCh2Imp, impFile) #max project bSaveZProject(origCh2Imp, eightBitMaxFolder, shortName+'_ch2') # # close original window imp.changes = 0 imp.close() #copy copy.changes = 0 copy.close() # # close ch1/ch2 if gNumChannels == 2: #original origCh1Imp.changes = 0 origCh1Imp.close() origCh2Imp.changes = 0 origCh2Imp.close() #copy ch1Imp.changes = 0 ch1Imp.close() ch2Imp.changes = 0 ch2Imp.close() bPrintLog(time.strftime("%H:%M:%S") + ' finished runOneFile(): ' + fullFilePath, 1)
def generate_background_rois(input_mask_imp, params, membrane_edges, dilations=5, threshold_method=None, membrane_imp=None): """automatically identify background region based on auto-thresholded image, existing membrane edges and position of midpoint anchor""" if input_mask_imp is None and membrane_imp is not None: segmentation_imp = Duplicator().run(membrane_imp) # do thresholding using either previous method if threhsold_method is None or using (less conservative?) threshold method if (threshold_method is None or not (threshold_method in params.listThresholdMethods())): mask_imp = make_and_clean_binary(segmentation_imp, params.threshold_method) else: mask_imp = make_and_clean_binary(segmentation_imp, threshold_method) segmentation_imp.close() else: input_mask_imp.killRoi() mask_imp = Duplicator().run(input_mask_imp) rois = [] IJ.setForegroundColor(0, 0, 0) roim = RoiManager(True) rt = ResultsTable() for fridx in range(mask_imp.getNFrames()): mask_imp.setT(fridx + 1) # add extra bit to binary mask from loaded membrane in case user refined edges... # flip midpoint anchor across the line joining the two extremes of the membrane, # and fill in the triangle made by this new point and those extremes poly = membrane_edges[fridx].getPolygon() l1 = (poly.xpoints[0], poly.ypoints[0]) l2 = (poly.xpoints[-1], poly.ypoints[-1]) M = (0.5 * (l1[0] + l2[0]), 0.5 * (l1[1] + l2[1])) Mp1 = (params.manual_anchor_midpoint[0][0] - M[0], params.manual_anchor_midpoint[0][1] - M[1]) p2 = (M[0] - Mp1[0], M[1] - Mp1[1]) new_poly_x = list(poly.xpoints) new_poly_x.append(p2[0]) new_poly_y = list(poly.ypoints) new_poly_y.append(p2[1]) mask_imp.setRoi(PolygonRoi(new_poly_x, new_poly_y, PolygonRoi.POLYGON)) IJ.run(mask_imp, "Fill", "slice") mask_imp.killRoi() # now dilate the masked image and identify the unmasked region closest to the midpoint anchor ip = mask_imp.getProcessor() dilations = 5 for d in range(dilations): ip.dilate() ip.invert() mask_imp.setProcessor(ip) mxsz = mask_imp.getWidth() * mask_imp.getHeight() pa = ParticleAnalyzer( ParticleAnalyzer.ADD_TO_MANAGER | ParticleAnalyzer.SHOW_PROGRESS, ParticleAnalyzer.CENTROID, rt, 0, mxsz) pa.setRoiManager(roim) pa.analyze(mask_imp) ds_to_anchor = [ math.sqrt((x - params.manual_anchor_midpoint[0][0])**2 + (y - params.manual_anchor_midpoint[0][1])**2) for x, y in zip( rt.getColumn(rt.getColumnIndex("X")).tolist(), rt.getColumn(rt.getColumnIndex("Y")).tolist()) ] if len(ds_to_anchor) > 0: roi = roim.getRoi(ds_to_anchor.index(min(ds_to_anchor))) rois.append(roi) else: rois.append(None) roim.reset() rt.reset() roim.close() mask_imp.close() return rois
def gfp_analysis(imp, file_name, output_folder, gfp_channel_number=1, dapi_channel_number=3, red_channel_number=2, threshold_method='Otsu', do_manual_qc=False, min_size_pix=1000): """perform analysis based on gfp intensity thresholding""" try: cal = imp.getCalibration() channel_imps = ChannelSplitter.split(imp) gfp_imp = channel_imps[gfp_channel_number - 1] gfp_imp.setTitle("GFP") threshold_imp = Duplicator().run(gfp_imp) threshold_imp.setTitle("GFP_threshold_imp") ecad_imp = channel_imps[red_channel_number - 1] ecad_imp.setTitle("E-cadherin") nuc_imp = channel_imps[dapi_channel_number - 1] nuclei_locations, full_nuclei_imp, ws_seeds_imp = get_nuclei_locations( nuc_imp, cal, distance_threshold_um=10, size_threshold_um2=100) ws_seeds_imp.changes = False ws_seeds_imp.close() full_nuclei_imp.hide() IJ.run(threshold_imp, "Make Binary", "method={} background=Dark calculate".format(threshold_method)) IJ.run(threshold_imp, "Fill Holes", "") erode_count = 2 for _ in range(erode_count): IJ.run(threshold_imp, "Erode", "") for _ in range(erode_count): IJ.run(threshold_imp, "Dilate", "") threshold_imp = keep_blobs_bigger_than(threshold_imp, min_size_pix) threshold_imp = my_kill_borders(threshold_imp) rois = generate_cell_rois(threshold_imp) threshold_imp.changes = False threshold_imp.close() rois = filter_cells_by_relative_nuclear_area( rois, full_nuclei_imp, relative_nuclear_area_threshold=0.75) if do_manual_qc: rois = perform_manual_qc(imp, rois, important_channel=gfp_channel_number) no_nuclei_centroids = [ get_no_nuclei_in_cell(roi, nuclei_locations) for roi in rois ] no_enclosed_nuclei = [ get_no_nuclei_fully_enclosed(roi, full_nuclei_imp) for roi in rois ] full_nuclei_imp.changes = False full_nuclei_imp.close() out_stats = generate_cell_shape_results( rois, gfp_imp, cal, file_name, no_nuclei_centroids=no_nuclei_centroids, no_enclosed_nuclei=no_enclosed_nuclei) 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) except Exception as e: print("Ran into a problem analysing {}: {}. Skipping to next cell...". format(file_name, e.message)) out_stats = [] pass return out_stats
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); # 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"); # 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); 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"); split_channels = mbfs.split_image_plus(imp, params); membrane_test_channel_imp = Duplicator().run(split_channels[0]); segmentation_channel_imp = split_channels[-1]; # import edges imp.hide(); membrane_edges = mbio.load_qcd_edges2(os.path.join(output_folder_old, "user_defined_edges.zip")); dummy_anchors = [params.manual_anchor_positions for _ in membrane_edges] membrane_edges, fixed_anchors = mbui.perform_user_qc(membrane_test_channel_imp, membrane_edges, membrane_edges, dummy_anchors, params); imp.show(); rgbstack = ImageStack(imp.getWidth(), imp.getHeight()); for tidx in range(imp.getNFrames()): imp.setT(tidx+1); ip = imp.getProcessor(); rgbip = ip.convertToRGB(); rgbstack.addSlice(rgbip); rgbimp = ImagePlus(("RGB " + imp.getTitle()), rgbstack); imp.close(); rgbimp.show(); IJ.run("Colors...", "foreground=yellow background=white selection=yellow"); for tidx in range(rgbimp.getNSlices()): rgbimp.setSlice(tidx+1); rgbimp.setRoi(membrane_edges[tidx]); IJ.run(rgbimp, "Draw", "slice"); IJ.run("Colors...", "foreground=red background=white selection=yellow"); for tidx in range(rgbimp.getNSlices()): rgbimp.setSlice(tidx+1); for anchor in params.manual_anchor_positions: rgbimp.setRoi(PointRoi(anchor[0], anchor[1])); IJ.run(rgbimp, "Draw", "slice"); params.saveParametersToJson(os.path.join(params.output_path, "parameters used.json")); params.persistParameters(); rgbimp.changes = False;