Tools for Adaptive Feedback Microscopy

"""  
Author: Sebastian Rhode
Date: 2016_11_29
File: Wizard_RareEventDetection_DLLs.czmac
Version: 4.1

Optimzed for the use with Celldiscoverer 7 and DF2.
Please adapt Focussing commands, especially FindSurface when using with other stands

1) - Select Overview Scan Experiment
2) - Select appropriate Image Analysis Pipeline
3) - Select Detailed Scan Experiment
4) - Specify the output folder for the image and data tables

Requires the following DLLs to be found inside the Zen program folder:

- RETools.dll
- TileTools.dll
"""

# import custom DLLs required for Rare Event Detection
import clr
clr.AddReference('RETools.dll')
clr.AddReference('TileTools.dll')
import RETools
import Tiles

ZEN Blue Python Script for Rare Event Detection

# Activate Zen.Application
RareEventDialog = ZenWindow()
RareEventDialog.Initialize('Rare Event Detection - Version : ' + str(version), 650, 750, True, True)

# add components to dialog
RareEventDialog.AddLabel('1) Select Overview Experiment  ------------------------------')
RareEventDialog.AddDropDown('overview_exp', 'Overview Scan Experiment', expfiles, 0)
RareEventDialog.AddDropDown('objectiveOV', 'Objective OvervIew Scan', objectives.Names, 1)
RareEventDialog.AddDropDown('optovarOV', 'After-Mag OverViewScan', optovars.Names, 2)
RareEventDialog.AddCheckbox('SWAF_before_overview', 'OPTION - (Find Surface) & SWAF before Overview', True)
RareEventDialog.AddLabel('2) Select Image Analysis to detect objects  -----------------')
RareEventDialog.AddDropDown('ip_pipe', 'Image Analysis Pieline', ipfiles, 0)
RareEventDialog.AddLabel('3) Select Detail Scan Experiment  ---------------------------')
RareEventDialog.AddDropDown('detailed_exp', 'Detailed Scan Experiment', expfiles, 1)
RareEventDialog.AddDropDown('objectiveDT', 'Objective Detailed Scan', objectives.Names, 2)
RareEventDialog.AddDropDown('optovarDT', 'After-Mag Detailed Scan', optovars.Names, 2)
RareEventDialog.AddCheckbox('checkoffset', 'OPTION - Check offset between FS and SWAF', False)
RareEventDialog.AddCheckbox('manualoffset', 'OPTION - Enter Offset manually', False)
RareEventDialog.AddDoubleRange('offsetvalue', 'Enter manual Offset [micron]', 0, 0, 100)
RareEventDialog.AddLabel('4) Specify Output Folder to save the images -----------------')
RareEventDialog.AddFolderBrowser('outfolder','Output Folder for Images and Data Tables', imgfolder) 

# show the window
result = RareEventDialog.Show()
if result.HasCanceled:
    message = 'Macro was canceled by user.'
    print message
    raise SystemExit
# use the correct objective and optovar for the overview scan
RETools.RareEventTools.SetObjectivebyName(objOV, False)
RETools.RareEventTools.SetOptovarbyName(optoOV, False)

if SWAF_beforeOV==True:
    try:
        # initial focussing via FindSurface to assure a good starting position
        # requires DF2 for Obsever or Celldiscoverer 7 --> otherwise comment line !!!
        Zen.Acquisition.FindSurface()
    except:
        print 'Was not able to run Find Surface.'
    
    try:
        # run the SWAF using the settings from the OVScan --> check SWAF  for overview experiment !!!
        Zen.Acquisition.FindAutofocus(OVScan)
    except:
        print 'Was not able to run SWAF using the seetings: ', OverViewExpName

# get the resulting z-position
znew = Zen.Devices.Focus.ActualPosition

# try to adapt the Tile Experiment with new Z-Position
try:
    Tiles.TileTools.ModifyTileRegionsZonly(OVScan, znew)
    print 'Adapted Z-Position of Tile OverView. New Z = ',znew
except:
    print 'Was not able to adapt Z-Position of Overview Scan Experiment.'
# execute detailed experiment at the position of every detected object
for i in range(0, num_POI, 1):

    # get the object information from the position table
    POI_ID = SingleObj.GetValue(i,0) # get the ID of the object - IDs start with 2 !!!
    xpos = SingleObj.GetValue(i,colID['BCcolx']) # get X-stage position from table
    ypos = SingleObj.GetValue(i,colID['BCcoly']) # get Y-stage position from table
    
    # move to the current position
    Zen.Devices.Stage.MoveTo(xpos + dx_LSM, ypos + dy_LSM) # comment this, if one uses a simulated experiment
    print 'Moving Stage to Object ID:', POI_ID, ' at :', round(xpos,2), round(ypos,2)

    if useRecallFocus == False:
        # Initial FindSurface before the Detail Scan starts
        try:
            Zen.Acquisition.FindSurface()
        except:
            'Was not able to run Find Surface.'
        # calculate new focus position plus offset and move z-drive
        zpos = Zen.Devices.Focus.ActualPosition + dzFS
        print 'Move to Z-Position: ', round(zpos,2)
        Zen.Devices.Focus.MoveTo(zpos)
    
    elif useRecallFocus == True:
        # alternative solution - use RecallFocus
        try:
            Zen.Acquisition.RecallFocus()
        except:
            print 'Was not able to run Recall Focus.'
        zpos = Zen.Devices.Focus.ActualPosition
        print 'New z-position after Recall Focus: ', zpos
    # load the predefined detailed scan experiment 
    DetailScan = Zen.Acquisition.Experiments.GetByName(DetailExpName)
    
    # only modify the Tile Properties if required IAS features BoundWidth and BoundHeight were found
    # if experiment is a Tile Experiment
    if DetailIsTileExp == True:
        
        # Modify tile center position - get bounding rectangle width & height in microns
        bcwidth =  SingleObj.GetValue(i, colID['BCWidthcolx'])
        bcheight = SingleObj.GetValue(i, colID['BCHeightcoly'])
        print 'Width and Height : ', str(round(bcwidth,2)), str(round(bcheight,2))
        print 'Modifying Tile Properties XYZ Position and width & height.'
        # Modify the XYZ position of the tile region on-the-fly
        Tiles.TileTools.ModifyTileRegionsXYZ(DetailScan, xpos, ypos, zpos)
        # Modify ConturSize for the tile according to the size of the bounding rectangle
        Tiles.TileTools.ModifyTileRegionsSize(DetailScan, bcwidth, bcheight)
        print 'New Tile Properties: ', round(xpos,2), round(ypos,2), round(zpos,2), round(bcwidth,2), round(bcheight,2)
    
    # execute the experiment
    print 'Running Detail Scan Experiment at new XYZ position.'
    
    # run the Detail Scan
    output_detailscan = Zen.Acquisition.Execute(DetailScan)
    DetailScan.Close()

    # get the image data name
    dtscan_name = output_detailscan.Name
    # save the image data to the selected folder and close the image
    output_detailscan.Save(OutputFolder + '\\' + output_detailscan.Name)
    output_detailscan.Close()
    # rename the CZI regarding to the object ID - Attention - IDs start with 2 !!!
    newname_dtscan = 'DTScan_ID' + str(POI_ID) + '.czi'
    if verbose:
        print 'Renaming File: ' + dtscan_name + ' to: ' + newname_dtscan + '\n'  
    File.Move(OutputFolder + '\\' + dtscan_name, OutputFolder + '\\' + newname_dtscan)
import csv
from System import Array
import sys
sys.path.append(r'c:\Projects\OAD\External_Python_Scripts_for_OAD')
import FijiTableTools as ft
from System.IO import File, Directory, Path

# define the resulr file to be read
txtfile = r'c:\Projects\RareEvent\Overview_10X_GFP_Results_Fiji.txt'

# initialize ZenTable object
table = ZenTable()

# read the result table and convert into a Zentable
table = ft.ReadResultTable(txtfile, 1, '\t', 'FijiTable', table)

# change the name of the table
table.Name = Path.GetFileNameWithoutExtension(Path.GetFileName(txtfile))

# show the table
Zen.Application.Documents.Add(table)
# clear all tile regions and positions
ZenExperimentExtensions.AddEllipseTileRegion(experiment, centerX, centerY, width, height, z)

# add a rectangular tile region to the experiment
ZenExperimentExtensions.AddPolygonTileRegion(experiment, polygonPoints, z)

# add an elipsoid tile region to the experiment
ZenExperimentExtensions.AddRectangleTileRegion(experiment, centerX, centerY, width, height, z)

# add a polygon tile region to the experiment using a point list
ZenExperimentExtensions.AddSinglePosition(experiment, x, y, z)

# add a single XYZ position
ZenExperimentExtensions.ClearTileRegionsAndPositions(experiment)

# modify the z-position of the
ZenExperimentExtensions.GetTileRegionInfos(experiment)
 
# get a lits with all the ZEN experiments 
ZenExperimentExtensions.GetZenExperimentFileNames(documentsFolder)

# check if an experiments contains tiles
ZenExperimentExtensions.IsTilesExperiment(experiment)

# modify the size of the tile regions
ZenExperimentExtensions.ModifyTileRegionsSize(experiment, newWidth, newHeight)

# modify the z-positions for the tile regions
ZenExperimentExtensions.ModifyTileRegionsZ(experiment, newZ)
namespace MyFirstExtension
{
    using Zeiss.Micro;
    using Zeiss.Micro.Reflection;
    using Zeiss.Micro.Scripting;
    using Zeiss.Micro.Application.Configuration;
    using Zeiss.Micro.Diagnostics;

    [ApplicationExtension("6CB9D0FC-0EFA-4B74-A8D4-17411DB835CF", "MyFirstExtension", 
        ExtensionFlags.Free | ExtensionFlags.SetupUI, "First Extension for Demo")]

    internal class MyFirstExtension : ApplicationExtension
    {
        readonly ZenWrapperLM zen = ZenWrapperLM.Instance;

        const string ExtensionName = "MyFirstExtension";
        const string MyControlName = "First Extension";
        MyControlViewModel myControlViewModel;

        // The functions to Initialize/Uninitialize the Extension are responsible to add and remove ZEN-specific WPF windows.
        // Therefore we have to add as many controls and their Action Classes to the project as we will need. 
        protected override void InitializeCore(object application,
                                                   ExtensionInitializeMode extensionInitializeMode,
                                                   object parameters)
        {
            this.myControlViewModel = new MyControlViewModel();
            // add extension to ZEN when activated inside the extension manager
            UIToolItem toolAction = zen.Windows.AddToolWindow
                (ExtensionName, MyControlName, "MyFirstExtension; MyFirstExtension.MyControl", this.myControlViewModel);
            // this parameter manages whether the control will be expanded when the extension is started
            toolAction.IsExpanded = true;
        }

        protected override void UninitializeCore(ExtensionUninitializeMode extensionUninitializeMode)
        {
            // add extension to ZEN when activated inside the extension manager
            zen.Windows.RemoveToolWindow(ExtensionName, MyControlName);
        }

    }
}
### -------------------- PreScript ---------------------------------------------- ###


from System import Array

posx = []
posy = []
posz = []
intensities = []

# adapt experiment experiment parameters
numZ = 15

# create header fo logfile
logfile = ZenService.Xtra.System.AppendLogLine('S\tT\tZ\tID\tMaxInt\tX\tY')

# extract the XYZ values for the brightest object from the lists
def getIDfromIntensities(intensities, posx, posy, posz):
    
    max_value = max(intensities)
    max_index = intensities.index(max_value)
    posx_bright = posx[max_index]
    posy_bright = posy[max_index]
    posz_bright = posz[max_index]

    return max_index, posx_bright, posy_bright, posz_bright
### -------------------- LoopScript --------------------------------------------- ###


# get the current time point
currT = ZenService.Experiment.CurrentTimePointIndex
# the scene index is still 1-based!
currSceneIndex = ZenService.Experiment.CurrentSceneIndex

# get total number of objects and frame number
numobj = ZenService.Analysis.All.RegionsCount
zindex = ZenService.Experiment.CurrentZSliceIndex

# add current z-position to list
posz.append(ZenService.HardwareActions.ReadFocusPosition())

# get current object positions and intensity arrays for all detected objects
positionsX = ZenService.Analysis.Single.BoundCenterXStage
positionsY = ZenService.Analysis.Single.BoundCenterYStage
curr_intensities = ZenService.Analysis.Single.IntensityMean_mCher

try:
    maxint = max(curr_intensities) # get the maximum intensity value and append the list
    intensities.append(maxint)
    # get ID of the brightest detected particle, append position list with the XY positions
    ID = Array.IndexOf(curr_intensities, max(curr_intensities))
    posx.append(positionsX[ID])
    posy.append(positionsY[ID])
except:
    maxint = 0.0
    intensities.append(maxint) # in case no object was detected set values
    ID = -1
    posx.append(-1)
    posy.append(-1)
### -------------------CONTINUE - LoopScript ------------------------------------ ###

# when the last zplane of the stack was reached do something
if zindex == numZ:
    
    index_brightest_plane, posx_bright, posy_bright, posz_bright = getIDfromIntensities(intensities, posx, posy, posz)
    logfile = ZenService.Xtra.System.AppendLogLine('Brightest Plane:\tX=' + str(posx_bright) + \
        '\tY=' + str(posy_bright)+ '\tZ=' + str(posz_bright))
    posx = []
    posy = []
    posz = []
    intensities = []
    
    # do the update for the current position
    ZenService.Actions.MoveTileRegion(currSceneIndex-1, posx_bright, posy_bright)
    
    # log action to file
    logfile = ZenService.Xtra.System.AppendLogLine('Move Scene: ' + str(currSceneIndex) + \
        '\tX=' + str(posx_bright) + '\tY=' + str(posy_bright))



### -------------------- PostScript --------------------------------------------- ###


# show logfile at the end
ZenService.Xtra.System.ExecuteExternalProgram(r'C:\Program Files (x86)\Notepad++\notepad++.exe', logfile)

Tools for Adaptive Feedback Microscopy

By Sebastian Rhode

Tools for Adaptive Feedback Microscopy

  • 1,932