Exemplo n.º 1
0
def main():

    bridge = Bridge()
    mmc = bridge.get_core()
    
    # Data set parameters
    path = Path('E://20201023//')
    name = 'test'

    # z stack parameters
    start_end_pos = -5
    mid_pos = 5
    step_size = .25
    relative = True

    # time series parameters
    exposure_time = 200  # in milliseconds
    
    num_z_positions = int(abs(mid_pos - start_end_pos)/step_size + 1)
    z_idx = list(range(num_z_positions))
    num_time_points = 10

    # setup cameras
    mmc.set_exposure(exposure_time)
    
    # setup z stage
    z_stage = mmc.get_focus_device()
    z_pos, pos_sequence = upload_stage_sequence(bridge, start_end_pos, mid_pos, step_size, relative)
    num_z_positions = len(pos_sequence)

    print(pos_sequence)

    # move to first position
    mmc.set_position(z_stage, pos_sequence[0])

    events = []
    z_idx_ = z_idx.copy()
    for i in range(num_time_points):
        for j in z_idx_:
            events.append({'axes': {'time':i, 'z': j}})
        z_idx_.reverse()

    with Acquisition(directory=path, name=name) as acq:
        acq.acquire(events)

    # turn off sequencing
    mmc.set_property(z_stage, "UseFastSequence", "No")
    mmc.set_property(z_stage, "UseSequence", "No")
Exemplo n.º 2
0
from pycromanager import Acquisition, multi_d_acquisition_events, Bridge, Dataset
from matplotlib import pyplot as plt
import numpy as np
import cv2
import time, math
import os, sys, re
from PIL import Image
from math import sqrt
from pathlib import Path

bridge = Bridge()

core = bridge.get_core()

mm = bridge.get_studio()
pm = mm.positions()
mmc = mm.core()
pos_list = pm.get_position_list()
#-------------------------------------------
directoryPATH = 'E:\KENZA Folder\CapstoneTests'
nameofSAVEDFILE = 'saving_name'


#--------------------------------------------
def merge_imagesVertical(file1, file2):
    """Merge two images into one vertical image
    :return: the merged Image object
    """
    image1 = file1
    image2 = file2
    vis = np.concatenate((image1, image2), axis=0)
Exemplo n.º 3
0
 def __init__(self, stageDevice):
     bridge = Bridge()
     self.mmc = bridge.get_core()
     self.mmc.set_xy_stage_device(stageDevice)
Exemplo n.º 4
0
def main():

    #------------------------------------------------------------------------------------------------------------------------------------
    #----------------------------------------------Begin setup of scan parameters--------------------------------------------------------
    #------------------------------------------------------------------------------------------------------------------------------------

    # lasers to use
    # 0 -> inactive
    # 1 -> active
    state_405 = 1
    state_488 = 0
    state_561 = 0
    state_635 = 1
    state_730 = 0

    # laser powers (0 -> 100%)
    power_405 = 10
    power_488 = 0
    power_561 = 0
    power_635 = 10
    power_730 = 0

    # exposure time
    exposure_ms = 5.

    # scan axis limits. Use stage positions reported by MM
    scan_axis_start_um = -26000.  #unit: um
    scan_axis_end_um = -25500.  #unit: um

    # tile axis limits. Use stage positions reported by MM
    tile_axis_start_um = -7000  #unit: um
    tile_axis_end_um = -6500.  #unit: um

    # height axis limits. Use stage positions reported by MM
    height_axis_start_um = 345.  #unit: um
    height_axis_end_um = 375.  #unit:  um

    # FOV parameters
    # ONLY MODIFY IF NECESSARY
    ROI = [0, 1024, 1599, 255]  #unit: pixels

    # setup file name
    save_directory = Path('E:/20201130/')
    save_name = Path('shaffer_lung_v1.h5')

    #------------------------------------------------------------------------------------------------------------------------------------
    #----------------------------------------------End setup of scan parameters----------------------------------------------------------
    #------------------------------------------------------------------------------------------------------------------------------------

    # instantiate the Python-Java bridge to MM
    bridge = Bridge()
    core = bridge.get_core()

    # turn off lasers
    core.set_config('Coherent-State', 'off')
    core.wait_for_config('Coherent-State', 'off')

    # set camera into 16bit readout mode
    core.set_property('Camera', 'ReadoutRate', '100MHz 16bit')
    time.sleep(1)

    # set camera into low noise readout mode
    core.set_property('Camera', 'Gain', '2-CMS')
    time.sleep(1)

    # set camera to trigger first mode
    # TO DO: photometrics claims this setting doesn't exist in PVCAM. Why is it necessary then?
    core.set_property('Camera', 'Trigger Timeout (secs)', 300)
    time.sleep(1)

    # set camera to internal trigger
    core.set_property('Camera', 'TriggerMode', 'Internal Trigger')
    time.sleep(1)

    # change core timeout for long stage moves
    core.set_property('Core', 'TimeoutMs', 100000)

    # crop FOV
    #core.set_roi(*ROI)

    # set exposure
    core.set_exposure(exposure_ms)

    # grab one image to determine actual framerate

    # get actual framerate from micromanager properties
    actual_readout_ms = float(core.get_property(
        'Camera', 'ActualInterval-ms'))  #unit: ms

    # camera pixel size
    pixel_size_um = .115  # unit: um

    # scan axis setup
    scan_axis_step_um = 0.4  # unit: um
    scan_axis_step_mm = scan_axis_step_um / 1000.  #unit: mm
    scan_axis_start_mm = scan_axis_start_um / 1000.  #unit: mm
    scan_axis_end_mm = scan_axis_end_um / 1000.  #unit: mm
    scan_axis_range_um = np.abs(scan_axis_end_um -
                                scan_axis_start_um)  # unit: um
    scan_axis_range_mm = scan_axis_range_um / 1000  #unit: mm
    actual_exposure_s = actual_readout_ms / 1000.  #unit: s
    scan_axis_speed = np.round(scan_axis_step_mm / actual_exposure_s,
                               2)  #unit: mm/s
    scan_axis_positions = np.rint(scan_axis_range_mm /
                                  scan_axis_step_mm).astype(
                                      int)  #unit: number of positions

    # tile axis setup
    tile_axis_overlap = 0.2  #unit: percentage
    tile_axis_range_um = np.abs(tile_axis_end_um -
                                tile_axis_start_um)  #unit: um
    tile_axis_range_mm = tile_axis_range_um / 1000  #unit: mm
    tile_axis_ROI = ROI[2] * pixel_size_um  #unit: um
    tile_axis_step_um = np.round((tile_axis_ROI) * (1 - tile_axis_overlap),
                                 2)  #unit: um
    tile_axis_step_mm = tile_axis_step_um / 1000  #unit: mm
    tile_axis_positions = np.rint(tile_axis_range_mm /
                                  tile_axis_step_mm).astype(
                                      int)  #unit: number of positions
    # if tile_axis_positions rounded to zero, make sure we acquire at least one position
    if tile_axis_positions == 0:
        tile_axis_positions = 1

    # height axis setup
    # this is more complicated, since we have an oblique light sheet
    # the height of the scan is the length of the ROI in the tilted direction * sin(tilt angle)
    height_axis_overlap = 0.2  #unit: percentage
    height_axis_range_um = np.abs(height_axis_end_um -
                                  height_axis_start_um)  #unit: um
    height_axis_range_mm = height_axis_range_um / 1000  #unit: mm
    height_axis_ROI = ROI[3] * pixel_size_um * np.sin(
        30 * (np.pi / 180.))  #unit: um
    height_axis_step_um = np.round(
        (height_axis_ROI) * (1 - height_axis_overlap), 2)  #unit: um
    height_axis_step_mm = height_axis_step_um / 1000  #unit: mm
    height_axis_positions = np.rint(height_axis_range_mm /
                                    height_axis_step_mm).astype(
                                        int)  #unit: number of positions
    # if height_axis_positions rounded to zero, make sure we acquire at least one position
    if height_axis_positions == 0:
        height_axis_positions = 1

    # get handle to xy and z stages
    xy_stage = core.get_xy_stage_device()
    z_stage = core.get_focus_device()

    # Setup PLC card to give start trigger
    plcName = 'PLogic:E:36'
    propPosition = 'PointerPosition'
    propCellConfig = 'EditCellConfig'
    #addrOutputBNC3 = 35
    addrOutputBNC1 = 33
    addrStageSync = 46  # TTL5 on Tiger backplane = stage sync signal

    # connect stage sync signal to BNC output
    core.set_property(plcName, propPosition, addrOutputBNC1)
    core.set_property(plcName, propCellConfig, addrStageSync)

    # turn on 'transmit repeated commands' for Tiger
    core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'No')

    # set tile axis speed for all moves
    command = 'SPEED Y=.1'
    core.set_property('TigerCommHub', 'SerialCommand', command)

    # check to make sure Tiger is not busy
    ready = 'B'
    while (ready != 'N'):
        command = 'STATUS'
        core.set_property('TigerCommHub', 'SerialCommand', command)
        ready = core.get_property('TigerCommHub', 'SerialResponse')
        time.sleep(.500)

    # set scan axis speed for large move to initial position
    command = 'SPEED X=.1'
    core.set_property('TigerCommHub', 'SerialCommand', command)

    # check to make sure Tiger is not busy
    ready = 'B'
    while (ready != 'N'):
        command = 'STATUS'
        core.set_property('TigerCommHub', 'SerialCommand', command)
        ready = core.get_property('TigerCommHub', 'SerialResponse')
        time.sleep(.500)

    # turn off 'transmit repeated commands' for Tiger
    core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'Yes')

    # move scan scan stage to initial position
    core.set_xy_position(scan_axis_start_um, tile_axis_start_um)
    core.wait_for_device(xy_stage)
    core.set_position(height_axis_start_um)
    core.wait_for_device(z_stage)

    # turn on 'transmit repeated commands' for Tiger
    core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'No')

    # set scan axis speed to correct speed for continuous stage scan
    # expects mm/s
    command = 'SPEED X=' + str(scan_axis_speed)
    core.set_property('TigerCommHub', 'SerialCommand', command)

    # check to make sure Tiger is not busy
    ready = 'B'
    while (ready != 'N'):
        command = 'STATUS'
        core.set_property('TigerCommHub', 'SerialCommand', command)
        ready = core.get_property('TigerCommHub', 'SerialResponse')
        time.sleep(.500)

    # set scan axis to true 1D scan with no backlash
    command = '1SCAN X? Y=0 Z=9 F=0'
    core.set_property('TigerCommHub', 'SerialCommand', command)

    # check to make sure Tiger is not busy
    ready = 'B'
    while (ready != 'N'):
        command = 'STATUS'
        core.set_property('TigerCommHub', 'SerialCommand', command)
        ready = core.get_property('TigerCommHub', 'SerialResponse')
        time.sleep(.500)

    # set range and return speed (10% of max) for scan axis
    # expects mm
    command = '1SCANR X=' + str(scan_axis_start_mm) + ' Y=' + str(
        scan_axis_end_mm) + ' R=10'
    core.set_property('TigerCommHub', 'SerialCommand', command)

    # check to make sure Tiger is not busy
    ready = 'B'
    while (ready != 'N'):
        command = 'STATUS'
        core.set_property('TigerCommHub', 'SerialCommand', command)
        ready = core.get_property('TigerCommHub', 'SerialResponse')
        time.sleep(.500)

    # turn off 'transmit repeated commands' for Tiger
    core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'Yes')

    # construct boolean array for lasers to use
    channel_states = [state_405, state_488, state_561, state_635, state_730]
    channel_powers = [power_405, power_488, power_561, power_635, power_730]

    # set lasers to user defined power
    core.set_property('Coherent-Scientific Remote',
                      'Laser 405-100C - PowerSetpoint (%)', channel_powers[0])
    core.set_property('Coherent-Scientific Remote',
                      'Laser 488-150C - PowerSetpoint (%)', channel_powers[1])
    core.set_property('Coherent-Scientific Remote',
                      'Laser OBIS LS 561-150 - PowerSetpoint (%)',
                      channel_powers[2])
    core.set_property('Coherent-Scientific Remote',
                      'Laser 637-140C - PowerSetpoint (%)', channel_powers[3])
    core.set_property('Coherent-Scientific Remote',
                      'Laser 730-30C - PowerSetpoint (%)', channel_powers[4])

    # calculate total tiles
    total_tiles = tile_axis_positions * height_axis_positions

    # output acquisition metadata
    print('Number of X positions: ' + str(scan_axis_positions))
    print('Number of Y tiles: ' + str(tile_axis_positions))
    print('Number of Z slabs: ' + str(height_axis_positions))
    print('Number of channels:' + str(np.sum(channel_states)))
    print('Number of BDV H5 tiles: ' + str(total_tiles))

    # define unit tranformation matrix
    unit_matrix = np.array((
        (1.0, 0.0, 0.0, 0.0),  # change the 4. value for x_translation (px)
        (0.0, 1.0, 0.0, 0.0),  # change the 4. value for y_translation (px)
        (0.0, 0.0, 1.0, 0.0)))  # change the 4. value for z_translation (px)

    # create BDV H5 using npy2bdv
    fname = save_directory / save_name
    bdv_writer = npy2bdv.BdvWriter(fname,
                                   nchannels=np.sum(channel_states),
                                   ntiles=total_tiles,
                                   subsamp=((1, 1, 1), ),
                                   blockdim=((1, 128, 256), ))

    # reset tile index for BDV H5 file
    tile_index = 0

    for y in range(tile_axis_positions):
        # calculate tile axis position
        tile_position_um = tile_axis_start_um + (tile_axis_step_um * y)

        # move XY stage to new tile axis position
        core.set_xy_position(scan_axis_start_um, tile_position_um)
        core.wait_for_device(xy_stage)

        for z in range(height_axis_positions):

            print('Tile index: ' + str(tile_index))

            # calculate height axis position
            height_position_um = height_axis_start_um + (height_axis_step_um *
                                                         z)

            # move Z stage to new height axis position
            core.set_position(height_position_um)
            core.wait_for_device(z_stage)

            # reset channel index for BDV H5 file
            channel_index = 0

            for c in range(len(channel_states)):

                # determine active channel
                if channel_states[c] == 1:
                    if (c == 0):
                        core.set_config('Coherent-State', '405nm')
                        core.wait_for_config('Coherent-State', '405nm')
                    elif (c == 1):
                        core.set_config('Coherent-State', '488nm')
                        core.wait_for_config('Coherent-State', '488nm')
                    elif (c == 2):
                        core.set_config('Coherent-State', '561nm')
                        core.wait_for_config('Coherent-State', '561nm')
                    elif (c == 3):
                        core.set_config('Coherent-State', '637nm')
                        core.wait_for_config('Coherent-State', '637nm')
                    elif (c == 4):
                        core.set_config('Coherent-State', '730nm')
                        core.wait_for_config('Coherent-State', '730nm')

                    print('Channel index: ' + str(channel_index))
                    print('Active channel: ' + str(c))

                    # set camera to trigger first mode for stage synchronization
                    core.set_property('Camera', 'TriggerMode', 'Trigger first')
                    time.sleep(1)

                    # get current X, Y, and Z stage positions for translation transformation
                    point = core.get_xy_stage_position()
                    x_now = point.get_x()
                    y_now = point.get_y()
                    z_now = core.get_position(z_stage)

                    # calculate affine matrix components for translation transformation
                    affine_matrix = unit_matrix
                    affine_matrix[
                        0,
                        3] = y_now / pixel_size_um  # x axis in BDV H5 (tile axis on scope).
                    affine_matrix[1, 3] = z_now / (
                        pixel_size_um * np.sin(30. * np.pi / 180.)
                    )  # y axis in BDV H5 (height axis on scope).
                    affine_matrix[2, 3] = x_now / (
                        pixel_size_um * np.cos(30. * np.pi / 180.)
                    )  # z axis in BDV H5 (scan axis on scope).

                    # turn off 'transmit repeated commands' for Tiger
                    core.set_property('TigerCommHub',
                                      'OnlySendSerialCommandOnChange', 'No')

                    # check to make sure Tiger is not busy
                    ready = 'B'
                    while (ready != 'N'):
                        command = 'STATUS'
                        core.set_property('TigerCommHub', 'SerialCommand',
                                          command)
                        ready = core.get_property('TigerCommHub',
                                                  'SerialResponse')
                        time.sleep(.500)

                    # turn off 'transmit repeated commands' for Tiger
                    core.set_property('TigerCommHub',
                                      'OnlySendSerialCommandOnChange', 'Yes')

                    # start acquistion
                    core.start_sequence_acquisition(int(scan_axis_positions),
                                                    float(0.0), True)

                    # tell stage to execute scan
                    command = '1SCAN'
                    core.set_property('TigerCommHub', 'SerialCommand', command)

                    # reset image counter
                    image_counter = 0

                    # place stack into BDV H5
                    bdv_writer.append_view(
                        stack=None,
                        virtual_stack_dim=(scan_axis_positions, ROI[3],
                                           ROI[2]),
                        time=0,
                        channel=channel_index,
                        tile=tile_index,
                        m_affine=affine_matrix,
                        name_affine='stage translation',
                        voxel_size_xyz=(.115, .115, .200),
                        voxel_units='um')

                    # grab images from buffer
                    while (image_counter < scan_axis_positions):

                        # if there are images in the buffer, grab and process
                        if (core.get_remaining_image_count() > 0):
                            # grab top image in buffer
                            tagged_image = core.pop_next_tagged_image()

                            # grab metadata to convert 1D array to 2D image
                            image_height = tagged_image.tags['Height']
                            image_width = tagged_image.tags['Width']

                            # convert to 2D image and place into virtual stack in BDV H5
                            bdv_writer.append_plane(plane=np.flipud(
                                tagged_image.pix.reshape(
                                    (image_height, image_width))),
                                                    plane_index=image_counter,
                                                    time=0,
                                                    channel=channel_index)

                            # increment image counter
                            image_counter = image_counter + 1

                        # no images in buffer, wait for another image to arrive.
                        else:
                            time.sleep(np.minimum(.01 * exposure_ms, 1) / 1000)

                    # clean up acquistion
                    core.stop_sequence_acquisition()

                    # turn off lasers
                    core.set_config('Coherent-State', 'off')
                    core.wait_for_config('Coherent-State', 'off')

                    # set camera to internal trigger
                    # this is necessary to avoid PVCAM driver issues that we keep having for long acquisitions.
                    core.set_property('Camera', 'TriggerMode',
                                      'Internal Trigger')
                    time.sleep(1)

                    # increment channel index for BDV H5 file
                    channel_index = channel_index + 1

                    # turn off 'transmit repeated commands' for Tiger
                    core.set_property('TigerCommHub',
                                      'OnlySendSerialCommandOnChange', 'No')

                    # check to make sure Tiger is not busy
                    ready = 'B'
                    while (ready != 'N'):
                        command = 'STATUS'
                        core.set_property('TigerCommHub', 'SerialCommand',
                                          command)
                        ready = core.get_property('TigerCommHub',
                                                  'SerialResponse')
                        time.sleep(.500)

                    # turn off 'transmit repeated commands' for Tiger
                    core.set_property('TigerCommHub',
                                      'OnlySendSerialCommandOnChange', 'Yes')

            # increment tile index for BDV H5
            tile_index = tile_index + 1

    # write BDV XML and close BDV H5
    bdv_writer.write_xml_file(ntimes=1)
    bdv_writer.close()
from shared.analysis import central_pixel_without_cells, bleach_location
from shared.find_blobs import select

# variables
from shared.find_organelles import find_organelle

nr = 40
nr_between_projector_checks = 2
cal_exposure = 200
cal_offset = 5
n_curve = 500

# build up pycromanager bridge
bridge = Bridge()
mmc = bridge.get_core()
mm = bridge.get_studio()
projector = bridge.construct_java_object(
    "org.micromanager.projector.ProjectorAPI")
projector_device = projector.get_projection_device()


def snap_and_get_bleach_location(exposure, cutoff):
    """
    Takes an image with the current settings.  Finds a location close to the center where there are
    no objects (as defined in function central_picel_without_cells).  If no such location is found, returns -1.
    Targets bleacher to this location, exposes and takes an image of that exposure.  Finds the center of the
    actual bleach spot.  When the square of the distance between the intended target and the actual bleach spot is
    greater than provided offset, will execute a full calibration.
    :param exposure: exposure time to use for bleaching
    :param cutoff: square of distance.  When offset is higher than this code should execute a calibration
Exemplo n.º 6
0
def main():

    #------------------------------------------------------------------------------------------------------------------------------------
    #----------------------------------------------Begin setup of scan parameters--------------------------------------------------------
    #------------------------------------------------------------------------------------------------------------------------------------

    # lasers to use
    # 0 -> inactive
    # 1 -> active
    state_405 = 1
    state_488 = 0
    state_561 = 0
    state_635 = 1
    state_730 = 0

    # laser powers (0 -> 100%)
    power_405 = 10
    power_488 = 0
    power_561 = 0
    power_635 = 5
    power_730 = 0

    # exposure time
    exposure_ms = 5.

    # scan axis limits. Use stage positions reported by MM
    scan_axis_start_um = 6000.  #unit: um
    scan_axis_end_um = 16000.  #unit: um

    # tile axis limits. Use stage positions reported by MM
    tile_axis_start_um = -1300  #unit: um
    tile_axis_end_um = -1350.  #unit: um

    # height axis limits. Use stage positions reported by MM
    height_axis_start_um = 320.  #unit: um
    height_axis_end_um = 360.  #unit:  um

    # FOV parameters
    # ONLY MODIFY IF NECESSARY
    ROI = [0, 1024, 1599, 255]  #unit: pixels

    # setup file name
    save_directory = Path('E:/20201211/')
    save_name = 'shaffer_lung'

    #------------------------------------------------------------------------------------------------------------------------------------
    #----------------------------------------------End setup of scan parameters----------------------------------------------------------
    #------------------------------------------------------------------------------------------------------------------------------------

    bridge = Bridge()
    core = bridge.get_core()

    # turn off lasers
    core.set_config('Coherent-State', 'off')
    core.wait_for_config('Coherent-State', 'off')

    # set camera into 16bit readout mode
    # give camera time to change modes if necessary
    core.set_property('Camera', 'ReadoutRate', '100MHz 16bit')
    time.sleep(1)

    # set camera into low noise readout mode
    # give camera time to change modes if necessary
    core.set_property('Camera', 'Gain', '2-CMS')
    time.sleep(1)

    # set camera to trigger first mode
    # give camera time to change modes if necessary
    core.set_property('Camera', 'Trigger Timeout (secs)', 300)
    time.sleep(1)

    # set camera to internal trigger
    # give camera time to change modes if necessary
    core.set_property('Camera', 'TriggerMode', 'Internal Trigger')
    time.sleep(1)

    # change core timeout for long stage moves
    time.sleep(1)

    # crop FOV
    #core.set_roi(*ROI)

    # set exposure
    core.set_exposure(exposure_ms)

    # get actual framerate from micromanager properties
    # TO DO: fix need for user to have manually run an exposure with correct crop to get this value
    actual_readout_ms = float(core.get_property(
        'Camera', 'ActualInterval-ms'))  #unit: ms

    # camera pixel size
    pixel_size_um = .115  # unit: um

    # scan axis setup
    scan_axis_step_um = 0.2  # unit: um
    scan_axis_step_mm = scan_axis_step_um / 1000.  #unit: mm
    scan_axis_start_mm = scan_axis_start_um / 1000.  #unit: mm
    scan_axis_end_mm = scan_axis_end_um / 1000.  #unit: mm
    scan_axis_range_um = np.abs(scan_axis_end_um -
                                scan_axis_start_um)  # unit: um
    scan_axis_range_mm = scan_axis_range_um / 1000  #unit: mm
    actual_exposure_s = actual_readout_ms / 1000.  #unit: s
    scan_axis_speed = np.round(scan_axis_step_mm / actual_exposure_s,
                               2)  #unit: mm/s
    scan_axis_positions = np.rint(scan_axis_range_mm /
                                  scan_axis_step_mm).astype(
                                      int)  #unit: number of positions

    # tile axis setup
    tile_axis_overlap = 0.2  #unit: percentage
    tile_axis_range_um = np.abs(tile_axis_end_um -
                                tile_axis_start_um)  #unit: um
    tile_axis_range_mm = tile_axis_range_um / 1000  #unit: mm
    tile_axis_ROI = ROI[2] * pixel_size_um  #unit: um
    tile_axis_step_um = np.round((tile_axis_ROI) * (1 - tile_axis_overlap),
                                 2)  #unit: um
    tile_axis_step_mm = tile_axis_step_um / 1000  #unit: mm
    tile_axis_positions = np.rint(tile_axis_range_mm /
                                  tile_axis_step_mm).astype(
                                      int)  #unit: number of positions
    # if tile_axis_positions rounded to zero, make sure we acquire at least one position
    if tile_axis_positions == 0:
        tile_axis_positions = 1

    # height axis setup
    height_axis_overlap = 0.2  #unit: percentage
    height_axis_range_um = np.abs(height_axis_end_um -
                                  height_axis_start_um)  #unit: um
    height_axis_range_mm = height_axis_range_um / 1000  #unit: mm
    #height_axis_ROI = ROI[3]*pixel_size_um*np.sin(30*(np.pi/180.)) #unit: um TO DO: Why is overlap so large when using oblique pixel height??
    height_axis_ROI = ROI[3] * pixel_size_um  #unit: um
    height_axis_step_um = np.round(
        (height_axis_ROI) * (1 - height_axis_overlap), 2)  #unit: um
    height_axis_step_mm = height_axis_step_um / 1000  #unit: mm
    height_axis_positions = np.rint(height_axis_range_mm /
                                    height_axis_step_mm).astype(
                                        int)  #unit: number of positions
    # if height_axis_positions rounded to zero, make sure we acquire at least one position
    if height_axis_positions == 0:
        height_axis_positions = 1

    # get handle to xy and z stages
    xy_stage = core.get_xy_stage_device()
    z_stage = core.get_focus_device()

    # Setup Tiger controller to pass signal when the scan stage cross the start position to the PLC
    plcName = 'PLogic:E:36'
    propPosition = 'PointerPosition'
    propCellConfig = 'EditCellConfig'
    #addrOutputBNC3 = 35 # BNC3 on the PLC front panel
    addrOutputBNC1 = 33  # BNC1 on the PLC front panel
    addrStageSync = 46  # TTL5 on Tiger backplane = stage sync signal

    # connect stage sync signal to BNC output
    core.set_property(plcName, propPosition, addrOutputBNC1)
    core.set_property(plcName, propCellConfig, addrStageSync)

    # turn on 'transmit repeated commands' for Tiger
    core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'No')

    # set tile axis speed for all moves
    command = 'SPEED Y=.1'
    core.set_property('TigerCommHub', 'SerialCommand', command)

    # check to make sure Tiger is not busy
    ready = 'B'
    while (ready != 'N'):
        command = 'STATUS'
        core.set_property('TigerCommHub', 'SerialCommand', command)
        ready = core.get_property('TigerCommHub', 'SerialResponse')
        time.sleep(.500)

    # set scan axis speed for large move to initial position
    command = 'SPEED X=.1'
    core.set_property('TigerCommHub', 'SerialCommand', command)

    # check to make sure Tiger is not busy
    ready = 'B'
    while (ready != 'N'):
        command = 'STATUS'
        core.set_property('TigerCommHub', 'SerialCommand', command)
        ready = core.get_property('TigerCommHub', 'SerialResponse')
        time.sleep(.500)

    # turn off 'transmit repeated commands' for Tiger
    core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'Yes')

    # move scan scan stage to initial position
    core.set_xy_position(scan_axis_start_um, tile_axis_start_um)
    core.wait_for_device(xy_stage)
    core.set_position(height_axis_start_um)
    core.wait_for_device(z_stage)

    # turn on 'transmit repeated commands' for Tiger
    core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'No')

    # set scan axis speed to correct speed for continuous stage scan
    # expects mm/s
    command = 'SPEED X=' + str(scan_axis_speed)
    core.set_property('TigerCommHub', 'SerialCommand', command)

    # check to make sure Tiger is not busy
    ready = 'B'
    while (ready != 'N'):
        command = 'STATUS'
        core.set_property('TigerCommHub', 'SerialCommand', command)
        ready = core.get_property('TigerCommHub', 'SerialResponse')
        time.sleep(.500)

    # set scan axis to true 1D scan with no backlash
    command = '1SCAN X? Y=0 Z=9 F=0'
    core.set_property('TigerCommHub', 'SerialCommand', command)

    # check to make sure Tiger is not busy
    ready = 'B'
    while (ready != 'N'):
        command = 'STATUS'
        core.set_property('TigerCommHub', 'SerialCommand', command)
        ready = core.get_property('TigerCommHub', 'SerialResponse')
        time.sleep(.500)

    # set range and return speed (5% of max) for scan axis
    # expects mm
    command = '1SCANR X=' + str(scan_axis_start_mm) + ' Y=' + str(
        scan_axis_end_mm) + ' R=10'
    core.set_property('TigerCommHub', 'SerialCommand', command)

    # check to make sure Tiger is not busy
    ready = 'B'
    while (ready != 'N'):
        command = 'STATUS'
        core.set_property('TigerCommHub', 'SerialCommand', command)
        ready = core.get_property('TigerCommHub', 'SerialResponse')
        time.sleep(.500)

    # turn off 'transmit repeated commands' for Tiger
    core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'Yes')

    # construct boolean array for lasers to use
    channel_states = [state_405, state_488, state_561, state_635, state_730]
    channel_powers = [power_405, power_488, power_561, power_635, power_730]

    # set lasers to user defined power
    core.set_property('Coherent-Scientific Remote',
                      'Laser 405-100C - PowerSetpoint (%)', channel_powers[0])
    core.set_property('Coherent-Scientific Remote',
                      'Laser 488-150C - PowerSetpoint (%)', channel_powers[1])
    core.set_property('Coherent-Scientific Remote',
                      'Laser OBIS LS 561-150 - PowerSetpoint (%)',
                      channel_powers[2])
    core.set_property('Coherent-Scientific Remote',
                      'Laser 637-140C - PowerSetpoint (%)', channel_powers[3])
    core.set_property('Coherent-Scientific Remote',
                      'Laser 730-30C - PowerSetpoint (%)', channel_powers[4])

    print('Number of X positions: ' + str(scan_axis_positions))
    print('Number of Y tiles: ' + str(tile_axis_positions))
    print('Number of Z slabs: ' + str(height_axis_positions))

    #time.sleep(10)

    for y in range(tile_axis_positions):
        # calculate tile axis position
        tile_position_um = tile_axis_start_um + (tile_axis_step_um * y)

        # move XY stage to new tile axis position
        core.set_xy_position(scan_axis_start_um, tile_position_um)
        core.wait_for_device(xy_stage)

        for z in range(height_axis_positions):
            # calculate height axis position
            height_position_um = height_axis_start_um + (height_axis_step_um *
                                                         z)

            # move Z stage to new height axis position
            core.set_position(height_position_um)
            core.wait_for_device(z_stage)

            # create events to execute scan across this z plane
            events = []

            for c in range(len(channel_states)):
                for x in range(
                        scan_axis_positions + 10
                ):  #TO DO: Fix need for extra frames in ASI setup, not here.
                    if channel_states[c] == 1:
                        if (c == 0):
                            evt = {
                                'axes': {
                                    'z': x
                                },
                                'channel': {
                                    'group': 'Coherent-State',
                                    'config': '405nm'
                                }
                            }
                        elif (c == 1):
                            evt = {
                                'axes': {
                                    'z': x
                                },
                                'channel': {
                                    'group': 'Coherent-State',
                                    'config': '488nm'
                                }
                            }
                        elif (c == 2):
                            evt = {
                                'axes': {
                                    'z': x
                                },
                                'channel': {
                                    'group': 'Coherent-State',
                                    'config': '561nm'
                                }
                            }
                        elif (c == 3):
                            evt = {
                                'axes': {
                                    'z': x
                                },
                                'channel': {
                                    'group': 'Coherent-State',
                                    'config': '637nm'
                                }
                            }
                        elif (c == 4):
                            evt = {
                                'axes': {
                                    'z': x
                                },
                                'channel': {
                                    'group': 'Coherent-State',
                                    'config': '730nm'
                                }
                            }

                        events.append(evt)

            # set camera to trigger first mode for stage synchronization
            # give camera time to change modes
            core.set_property('Camera', 'TriggerMode', 'Trigger first')
            time.sleep(1)

            # update save_name with current Z plane
            save_name_z = save_name + '_y' + str(y).zfill(4) + '_z' + str(
                z).zfill(4)

            # run acquisition at this Z plane
            with Acquisition(directory=save_directory,
                             name=save_name_z,
                             post_hardware_hook_fn=post_hook_fn,
                             post_camera_hook_fn=camera_hook_fn,
                             show_display=False,
                             max_multi_res_index=0) as acq:
                acq.acquire(events)

                # added this code in an attempt to clean up resources, given the ZMQ error we are getting when using two hooks
                acq.acquire(None)
                acq.await_completion()

            # try to clean up acquisition so that AcqEngJ releases directory. This way we can move it to the network storage
            # in the background.
            acq = None

            # turn off lasers
            core.set_config('Coherent-State', 'off')
            core.wait_for_config('Coherent-State', 'off')

            # set camera to internal trigger
            # this is necessary to avoid PVCAM driver issues that we keep having for long acquisitions.
            # give camera time to change modes
            core.set_property('Camera', 'TriggerMode', 'Internal Trigger')
            time.sleep(1)
Exemplo n.º 7
0
from pycromanager import Acquisition, multi_d_acquisition_events, Bridge, start_headless

mm_app_path = '/Applications/Micro-Manager-2.0.0-gamma1'
# mm_app_path = 'C:/Program Files/Micro-Manager-2.0gamma'

config_file = mm_app_path + "/MMConfig_demo.cfg"

#Optional: specify your own version of java to run with
java_loc = "/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java"
# java_loc = None
start_headless(mm_app_path, config_file, java_loc=java_loc)

b = Bridge()
b.get_core().snap_image()
print(b.get_core().get_image())

save_dir = "/Users/henrypinkard/tmp"
# save_dir = "C:/Users/Henry Pinkard/Desktop/datadump"

with Acquisition(directory=save_dir, name="tcz_acq", debug=True) as acq:
    # Generate the events for a single z-stack
    events = multi_d_acquisition_events(
        num_time_points=5,
        time_interval_s=0,
        channel_group="Channel",
        channels=["DAPI", "FITC"],
        z_start=0,
        z_end=6,
        z_step=0.4,
        order="tcz",
    )
Exemplo n.º 8
0
def main():

    bridge = Bridge()
    core = bridge.get_core()

    # FOV parameters
    ROI = [1024, 0, 256, 1024]  #unit: pixels

    # camera exposure
    exposure_ms = 5  #unit: ms

    # set to high-res camera
    core.set_config('Camera', 'HighRes')

    # crop FOV
    core.set_roi(*ROI)

    # set exposure
    core.set_exposure(exposure_ms)

    # setup file name
    save_directory = Path('C:/data/test/')
    save_name = 'test_stages'

    # get handle to xy and z stages
    xy_stage = core.get_xy_stage_device()
    z_stage = core.get_focus_device()

    # move the stages to verify core can talk to them
    # positions chosen at random
    core.set_xy_position(100., 100.)
    core.wait_for_device(xy_stage)
    core.set_position(50.)
    core.wait_for_device(z_stage)

    # create events to hold all of the scan axis images during constant speed stage scan
    channel_configs = ['DAPI', 'FITC', 'Rhodamine', 'Cy5']
    events = []
    for y in range(2):
        for z in range(2):
            for c in range(len(channel_configs)):
                for x in range(2):
                    evt = {
                        'axes': {
                            'x': x,
                            'y': y,
                            'z': z
                        },
                        'x': 100,
                        'y': y * 1000,
                        'z': z * 100,
                        'channel': {
                            'group': 'Channel',
                            'config': channel_configs[c]
                        }
                    }
                    events.append(evt)

    # run acquisition
    # TO DO: properly handle an error here if camera driver fails to return expected number of images.
    with Acquisition(directory=save_directory,
                     name=save_name,
                     post_hardware_hook_fn=setup_scan_fn,
                     post_camera_hook_fn=hook_fn,
                     show_display=False,
                     max_multi_res_index=0,
                     debug=False) as acq:
        acq.acquire(events)
        acq.acquire(None)
        acq.await_completion()
Exemplo n.º 9
0
def main():

    #------------------------------------------------------------------------------------------------------------------------------------
    #----------------------------------------------Begin setup of scan parameters--------------------------------------------------------
    #------------------------------------------------------------------------------------------------------------------------------------

    # set up lasers
    channel_labels = ["405", "488", "561", "635", "730"]
    channel_states = [False, False, True, False,
                      False]  # true -> active, false -> inactive
    channel_powers = [50, 10, 90, 100, 95]  # (0 -> 100%)
    do_ind = [0, 1, 2, 3,
              4]  # digital output line corresponding to each channel

    # parse which channels are active
    active_channel_indices = [
        ind for ind, st in zip(do_ind, channel_states) if st
    ]
    n_active_channels = len(active_channel_indices)

    print("%d active channels: " % n_active_channels, end="")
    for ind in active_channel_indices:
        print("%s " % channel_labels[ind], end="")
    print("")

    # exposure time
    exposure_ms = 50.0

    # excess scan positions
    excess_scan_positions = 10

    # galvo voltage at neutral
    galvo_neutral_volt = -0.15  # unit: volts

    # scan axis limits. Use stage positions reported by MM
    scan_axis_start_um = 8680.  #unit: um
    scan_axis_end_um = 8800.  #unit: um

    # tile axis limits. Use stage positions reported by MM
    tile_axis_start_um = -3841.28  #unit: um
    tile_axis_end_um = -3841.28  #unit: um

    # height axis limits. Use stage positions reported by MM
    height_axis_start_um = 13128.63  #unit: um
    height_axis_end_um = 13128.63  #unit:  um

    # number of timepoints to execute
    # TO DO: add in control for rate of experiment
    timepoints = 1

    # FOV parameters
    # ONLY MODIFY IF NECESSARY
    # ROI = [0, 1152, 2304, 512] #unit: pixels

    # setup file name
    save_directory = Path('D:/20210831')
    save_name = 'stage_scan'

    #------------------------------------------------------------------------------------------------------------------------------------
    #----------------------------------------------End setup of scan parameters----------------------------------------------------------
    #------------------------------------------------------------------------------------------------------------------------------------

    # connect to Micromanager instance
    bridge = Bridge()
    core = bridge.get_core()

    # turn off lasers
    core.set_config('Laser', 'Off')
    core.wait_for_config('Laser', 'Off')

    # set camera to fast readout mode
    core.set_config('Camera-Setup', 'ScanMode3')
    core.wait_for_config('Camera-Setup', 'ScanMode3')

    # set camera to START mode upon input trigger
    core.set_config('Camera-TriggerType', 'START')
    core.wait_for_config('Camera-TriggerType', 'START')

    # set camera to positive input trigger
    core.set_config('Camera-TriggerPolarity', 'POSITIVE')
    core.wait_for_config('Camera-TriggerPolarity', 'POSITIVE')

    # set camera to internal control
    core.set_config('Camera-TriggerSource', 'INTERNAL')
    core.wait_for_config('Camera-TriggerSource', 'INTERNAL')

    # set camera to output positive triggers on all lines for exposure
    core.set_property('OrcaFusionBT', 'OUTPUT TRIGGER KIND[0]', 'EXPOSURE')
    core.set_property('OrcaFusionBT', 'OUTPUT TRIGGER KIND[1]', 'EXPOSURE')
    core.set_property('OrcaFusionBT', 'OUTPUT TRIGGER KIND[2]', 'EXPOSURE')
    core.set_property('OrcaFusionBT', 'OUTPUT TRIGGER POLARITY[0]', 'POSITIVE')
    core.set_property('OrcaFusionBT', 'OUTPUT TRIGGER POLARITY[1]', 'POSITIVE')
    core.set_property('OrcaFusionBT', 'OUTPUT TRIGGER POLARITY[2]', 'POSITIVE')

    # change core timeout for long stage moves
    core.set_property('Core', 'TimeoutMs', 100000)
    time.sleep(1)

    # set exposure
    core.set_exposure(exposure_ms)

    # determine image size
    core.snap_image()
    y_pixels = core.get_image_height()
    x_pixels = core.get_image_width()

    # grab exposure
    true_exposure = core.get_exposure()

    # get actual framerate from micromanager properties
    actual_readout_ms = true_exposure + float(
        core.get_property('OrcaFusionBT', 'ReadoutTime'))  #unit: ms

    # camera pixel size
    pixel_size_um = .115  # unit: um

    # scan axis setup
    scan_axis_step_um = 0.4  # unit: um
    scan_axis_step_mm = scan_axis_step_um / 1000.  #unit: mm
    scan_axis_start_mm = scan_axis_start_um / 1000.  #unit: mm
    scan_axis_end_mm = scan_axis_end_um / 1000.  #unit: mm
    scan_axis_range_um = np.abs(scan_axis_end_um -
                                scan_axis_start_um)  # unit: um
    scan_axis_range_mm = scan_axis_range_um / 1000  #unit: mm
    actual_exposure_s = actual_readout_ms / 1000.  #unit: s
    scan_axis_speed = np.round(scan_axis_step_mm / actual_exposure_s,
                               4)  #unit: mm/s
    scan_axis_positions = np.rint(scan_axis_range_mm /
                                  scan_axis_step_mm).astype(
                                      int)  #unit: number of positions

    # tile axis setup
    tile_axis_overlap = 0.2  #unit: percentage
    tile_axis_range_um = np.abs(tile_axis_end_um -
                                tile_axis_start_um)  #unit: um
    tile_axis_range_mm = tile_axis_range_um / 1000  #unit: mm
    tile_axis_ROI = x_pixels * pixel_size_um  #unit: um
    tile_axis_step_um = np.round((tile_axis_ROI) * (1 - tile_axis_overlap),
                                 2)  #unit: um
    tile_axis_step_mm = tile_axis_step_um / 1000  #unit: mm
    tile_axis_positions = np.rint(
        tile_axis_range_mm /
        tile_axis_step_mm).astype(int) + 1  #unit: number of positions
    # if tile_axis_positions rounded to zero, make sure we acquire at least one position
    if tile_axis_positions == 0:
        tile_axis_positions = 1

    # height axis setup
    height_axis_overlap = 0.2  #unit: percentage
    height_axis_range_um = np.abs(height_axis_end_um -
                                  height_axis_start_um)  #unit: um
    height_axis_range_mm = height_axis_range_um / 1000  #unit: mm
    height_axis_ROI = y_pixels * pixel_size_um * np.sin(
        30. * np.pi / 180.)  #unit: um
    height_axis_step_um = np.round(
        (height_axis_ROI) * (1 - height_axis_overlap), 2)  #unit: um
    height_axis_step_mm = height_axis_step_um / 1000  #unit: mm
    height_axis_positions = np.rint(
        height_axis_range_mm /
        height_axis_step_mm).astype(int) + 1  #unit: number of positions
    # if height_axis_positions rounded to zero, make sure we acquire at least one position
    if height_axis_positions == 0:
        height_axis_positions = 1

    # get handle to xy and z stages
    xy_stage = core.get_xy_stage_device()
    z_stage = core.get_focus_device()

    # galvo voltage at neutral
    galvo_neutral_volt = -.15  # unit: volts

    # set the galvo to the neutral position if it is not already
    try:
        taskAO_first = daq.Task()
        taskAO_first.CreateAOVoltageChan("/Dev1/ao0", "", -4.0, 4.0,
                                         daq.DAQmx_Val_Volts, None)
        taskAO_first.WriteAnalogScalarF64(True, -1, galvo_neutral_volt, None)
        taskAO_first.StopTask()
        taskAO_first.ClearTask()
    except:
        print("DAQmx Error %s" % err)

    # Setup Tiger controller to pass signal when the scan stage cross the start position to the PLC
    plcName = 'PLogic:E:36'
    propPosition = 'PointerPosition'
    propCellConfig = 'EditCellConfig'
    #addrOutputBNC3 = 35 # BNC3 on the PLC front panel
    addrOutputBNC1 = 33  # BNC1 on the PLC front panel
    addrStageSync = 46  # TTL5 on Tiger backplane = stage sync signal

    # connect stage sync signal to BNC output
    core.set_property(plcName, propPosition, addrOutputBNC1)
    core.set_property(plcName, propCellConfig, addrStageSync)

    # turn on 'transmit repeated commands' for Tiger
    core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'No')

    # set tile axis speed for all moves
    command = 'SPEED Y=.1'
    core.set_property('TigerCommHub', 'SerialCommand', command)

    # check to make sure Tiger is not busy
    ready = 'B'
    while (ready != 'N'):
        command = 'STATUS'
        core.set_property('TigerCommHub', 'SerialCommand', command)
        ready = core.get_property('TigerCommHub', 'SerialResponse')
        time.sleep(.500)

    # set scan axis speed for large move to initial position
    command = 'SPEED X=.1'
    core.set_property('TigerCommHub', 'SerialCommand', command)

    # check to make sure Tiger is not busy
    ready = 'B'
    while (ready != 'N'):
        command = 'STATUS'
        core.set_property('TigerCommHub', 'SerialCommand', command)
        ready = core.get_property('TigerCommHub', 'SerialResponse')
        time.sleep(.500)

    # turn off 'transmit repeated commands' for Tiger
    core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'Yes')

    # move scan scan stage to initial position
    core.set_xy_position(scan_axis_start_um, tile_axis_start_um)
    core.wait_for_device(xy_stage)
    core.set_position(height_axis_start_um)
    core.wait_for_device(z_stage)

    # turn on 'transmit repeated commands' for Tiger
    core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'No')

    # set scan axis speed to correct speed for continuous stage scan
    # expects mm/s
    command = 'SPEED X=' + str(scan_axis_speed)
    core.set_property('TigerCommHub', 'SerialCommand', command)

    # check to make sure Tiger is not busy
    ready = 'B'
    while (ready != 'N'):
        command = 'STATUS'
        core.set_property('TigerCommHub', 'SerialCommand', command)
        ready = core.get_property('TigerCommHub', 'SerialResponse')
        time.sleep(.500)

    # set scan axis to true 1D scan with no backlash
    command = '1SCAN X? Y=0 Z=9 F=0'
    core.set_property('TigerCommHub', 'SerialCommand', command)

    # check to make sure Tiger is not busy
    ready = 'B'
    while (ready != 'N'):
        command = 'STATUS'
        core.set_property('TigerCommHub', 'SerialCommand', command)
        ready = core.get_property('TigerCommHub', 'SerialResponse')
        time.sleep(.500)

    # set range and return speed (5% of max) for scan axis
    # expects mm
    command = '1SCANR X=' + str(scan_axis_start_mm) + ' Y=' + str(
        scan_axis_end_mm) + ' R=10'
    core.set_property('TigerCommHub', 'SerialCommand', command)

    # check to make sure Tiger is not busy
    ready = 'B'
    while (ready != 'N'):
        command = 'STATUS'
        core.set_property('TigerCommHub', 'SerialCommand', command)
        ready = core.get_property('TigerCommHub', 'SerialResponse')
        time.sleep(.500)

    # turn off 'transmit repeated commands' for Tiger
    core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'Yes')

    # set all laser to external triggering
    core.set_config('Modulation-405', 'External-Digital')
    core.wait_for_config('Modulation-405', 'External-Digital')
    core.set_config('Modulation-488', 'External-Digital')
    core.wait_for_config('Modulation-488', 'External-Digital')
    core.set_config('Modulation-561', 'External-Digital')
    core.wait_for_config('Modulation-561', 'External-Digital')
    core.set_config('Modulation-637', 'External-Digital')
    core.wait_for_config('Modulation-637', 'External-Digital')
    core.set_config('Modulation-730', 'External-Digital')
    core.wait_for_config('Modulation-730', 'External-Digital')

    # turn all lasers on
    core.set_config('Laser', 'AllOn')
    core.wait_for_config('Laser', 'AllOn')

    # set lasers to user defined power
    core.set_property('Coherent-Scientific Remote',
                      'Laser 405-100C - PowerSetpoint (%)', channel_powers[0])
    core.set_property('Coherent-Scientific Remote',
                      'Laser 488-150C - PowerSetpoint (%)', channel_powers[1])
    core.set_property('Coherent-Scientific Remote',
                      'Laser OBIS LS 561-150 - PowerSetpoint (%)',
                      channel_powers[2])
    core.set_property('Coherent-Scientific Remote',
                      'Laser 637-140C - PowerSetpoint (%)', channel_powers[3])
    core.set_property('Coherent-Scientific Remote',
                      'Laser 730-30C - PowerSetpoint (%)', channel_powers[4])

    # setup DAQ
    samples_per_ch = 2
    DAQ_sample_rate_Hz = 10000
    num_DI_channels = 8

    # set the galvo to neutral
    taskAO_last = daq.Task()
    taskAO_last.CreateAOVoltageChan("/Dev1/ao0", "", -4.0, 4.0,
                                    daq.DAQmx_Val_Volts, None)
    taskAO_last.WriteAnalogScalarF64(True, -1, galvo_neutral_volt, None)
    taskAO_last.StopTask()
    taskAO_last.ClearTask()

    # output experiment info
    print('Number of X positions: ' + str(scan_axis_positions))
    print('Number of Y tiles: ' + str(tile_axis_positions))
    print('Number of Z slabs: ' + str(height_axis_positions))
    print('Number of channels: ' + str(n_active_channels))

    # flags for metadata and processing
    setup_processing = True
    setup_metadata = True

    # create events to execute scan
    events = []
    for x in range(scan_axis_positions + excess_scan_positions):
        evt = {'axes': {'z': x}}
        events.append(evt)

    for t_idx in range(timepoints):
        for y_idx in range(tile_axis_positions):
            # calculate tile axis position
            tile_position_um = tile_axis_start_um + (tile_axis_step_um * y_idx)

            # move XY stage to new tile axis position
            core.set_xy_position(scan_axis_start_um, tile_position_um)
            core.wait_for_device(xy_stage)

            for z_idx in range(height_axis_positions):
                # calculate height axis position
                height_position_um = height_axis_start_um + (
                    height_axis_step_um * z_idx)

                # move Z stage to new height axis position
                core.set_position(height_position_um)
                core.wait_for_device(z_stage)

                for ch_idx in active_channel_indices:

                    # create DAQ pattern for laser strobing controlled via rolling shutter
                    dataDO = np.zeros((samples_per_ch, num_DI_channels),
                                      dtype=np.uint8)
                    dataDO[0, ch_idx] = 1
                    dataDO[1, ch_idx] = 0
                    #print(dataDO)

                    # update save_name with current tile information
                    save_name_tyzc = save_name + '_t' + str(t_idx).zfill(
                        4) + '_y' + str(y_idx).zfill(4) + '_z' + str(
                            z_idx).zfill(4) + '_ch' + str(ch_idx).zfill(4)

                    # turn on 'transmit repeated commands' for Tiger
                    core.set_property('TigerCommHub',
                                      'OnlySendSerialCommandOnChange', 'No')

                    # check to make sure Tiger is not busy
                    ready = 'B'
                    while (ready != 'N'):
                        command = 'STATUS'
                        core.set_property('TigerCommHub', 'SerialCommand',
                                          command)
                        ready = core.get_property('TigerCommHub',
                                                  'SerialResponse')
                        time.sleep(.500)

                    # turn off 'transmit repeated commands' for Tiger
                    core.set_property('TigerCommHub',
                                      'OnlySendSerialCommandOnChange', 'Yes')

                    # save actual stage positions
                    xy_pos = core.get_xy_stage_position()
                    stage_x = xy_pos.x
                    stage_y = xy_pos.y
                    stage_z = core.get_position()
                    current_stage_data = [{
                        'stage_x': stage_x,
                        'stage_y': stage_y,
                        'stage_z': stage_z
                    }]
                    df_current_stage = pd.DataFrame(current_stage_data)

                    # setup DAQ for laser strobing
                    try:
                        # ----- DIGITAL input -------
                        taskDI = daq.Task()
                        taskDI.CreateDIChan("/Dev1/PFI0", "",
                                            daq.DAQmx_Val_ChanForAllLines)

                        ## Configure change detection timing (from wave generator)
                        taskDI.CfgInputBuffer(
                            0
                        )  # must be enforced for change-detection timing, i.e no buffer
                        taskDI.CfgChangeDetectionTiming(
                            "/Dev1/PFI0", "/Dev1/PFI0",
                            daq.DAQmx_Val_ContSamps, 0)

                        ## Set where the starting trigger
                        taskDI.CfgDigEdgeStartTrig("/Dev1/PFI0",
                                                   daq.DAQmx_Val_Rising)

                        ## Export DI signal to unused PFI pins, for clock and start
                        taskDI.ExportSignal(daq.DAQmx_Val_ChangeDetectionEvent,
                                            "/Dev1/PFI2")
                        taskDI.ExportSignal(daq.DAQmx_Val_StartTrigger,
                                            "/Dev1/PFI1")

                        # ----- DIGITAL output ------
                        taskDO = daq.Task()
                        taskDO.CreateDOChan("/Dev1/port0/line0:7", "",
                                            daq.DAQmx_Val_ChanForAllLines)

                        ## Configure timing (from DI task)
                        taskDO.CfgSampClkTiming("/Dev1/PFI2",
                                                DAQ_sample_rate_Hz,
                                                daq.DAQmx_Val_Rising,
                                                daq.DAQmx_Val_ContSamps,
                                                samples_per_ch)

                        ## Write the output waveform
                        samples_per_ch_ct_digital = ct.c_int32()
                        taskDO.WriteDigitalLines(
                            samples_per_ch, False, 10.0,
                            daq.DAQmx_Val_GroupByChannel, dataDO,
                            ct.byref(samples_per_ch_ct_digital), None)

                        ## ------ Start digital input and output tasks ----------
                        taskDO.StartTask()
                        taskDI.StartTask()

                    except daq.DAQError as err:
                        print("DAQmx Error %s" % err)

                    # set camera to external control
                    # DCAM sets the camera back to INTERNAL mode after each acquisition
                    core.set_config('Camera-TriggerSource', 'EXTERNAL')
                    core.wait_for_config('Camera-TriggerSource', 'EXTERNAL')

                    # verify that camera actually switched back to external trigger mode
                    trigger_state = core.get_property('OrcaFusionBT',
                                                      'TRIGGER SOURCE')

                    # if not in external control, keep trying until camera changes settings
                    while not (trigger_state == 'EXTERNAL'):
                        time.sleep(2.0)
                        core.set_config('Camera-TriggerSource', 'EXTERNAL')
                        core.wait_for_config('Camera-TriggerSource',
                                             'EXTERNAL')
                        trigger_state = core.get_property(
                            'OrcaFusionBT', 'TRIGGER SOURCE')

                    print('T: ' + str(t_idx) + ' Y: ' + str(y_idx) + ' Z: ' +
                          str(z_idx) + ' C: ' + str(ch_idx))
                    # run acquisition for this tyzc combination
                    with Acquisition(directory=save_directory,
                                     name=save_name_tyzc,
                                     post_camera_hook_fn=camera_hook_fn,
                                     show_display=False,
                                     max_multi_res_index=0,
                                     saving_queue_size=5000) as acq:

                        acq.acquire(events)

                    # clean up acquisition so that AcqEngJ releases directory.
                    # NOTE: This currently does not work.
                    acq = None

                    acq_deleted = False
                    while not (acq_deleted):
                        try:
                            del acq
                        except:
                            time.sleep(0.1)
                            acq_deleted = False
                        else:
                            gc.collect()
                            acq_deleted = True

                    # stop DAQ and make sure it is at zero
                    try:
                        ## Stop and clear both tasks
                        taskDI.StopTask()
                        taskDO.StopTask()
                        taskDI.ClearTask()
                        taskDO.ClearTask()
                    except daq.DAQError as err:
                        print("DAQmx Error %s" % err)

                    # save experimental info after first tile.
                    # we do it this way so that Pycromanager can manage the directories.
                    if (setup_metadata):
                        # save stage scan parameters
                        scan_param_data = [{
                            'root_name':
                            str(save_name),
                            'scan_type':
                            str('stage'),
                            'theta':
                            float(30.0),
                            'scan_step':
                            float(scan_axis_step_um * 1000.),
                            'pixel_size':
                            float(pixel_size_um * 1000.),
                            'num_t':
                            int(timepoints),
                            'num_y':
                            int(tile_axis_positions),
                            'num_z':
                            int(height_axis_positions),
                            'num_ch':
                            int(n_active_channels),
                            'scan_axis_positions':
                            int(scan_axis_positions),
                            'excess_scan_positions':
                            int(excess_scan_positions),
                            'y_pixels':
                            int(y_pixels),
                            'x_pixels':
                            int(x_pixels),
                            '405_active':
                            bool(channel_states[0]),
                            '488_active':
                            bool(channel_states[1]),
                            '561_active':
                            bool(channel_states[2]),
                            '635_active':
                            bool(channel_states[3]),
                            '730_active':
                            bool(channel_states[4])
                        }]

                        # df_stage_scan_params = pd.DataFrame(scan_param_data)
                        # save_name_stage_params = save_directory / 'scan_metadata.csv'
                        # df_stage_scan_params.to_csv(save_name_stage_params)
                        data_io.write_metadata(
                            scan_param_data[0],
                            save_directory / Path('scan_metadata.csv'))

                        setup_metadata = False

                    # save stage scan positions after each tile
                    save_name_stage_positions = Path('t' +
                                                     str(t_idx).zfill(4) +
                                                     '_y' +
                                                     str(y_idx).zfill(4) +
                                                     '_z' +
                                                     str(z_idx).zfill(4) +
                                                     '_ch' +
                                                     str(ch_idx).zfill(4) +
                                                     '_stage_positions.csv')
                    save_name_stage_positions = save_directory / save_name_stage_positions
                    # todo: use data_io instead
                    df_current_stage.to_csv(save_name_stage_positions)

                    # turn on 'transmit repeated commands' for Tiger
                    core.set_property('TigerCommHub',
                                      'OnlySendSerialCommandOnChange', 'No')

                    # check to make sure Tiger is not busy
                    ready = 'B'
                    while (ready != 'N'):
                        command = 'STATUS'
                        core.set_property('TigerCommHub', 'SerialCommand',
                                          command)
                        ready = core.get_property('TigerCommHub',
                                                  'SerialResponse')
                        time.sleep(.500)

                    # turn off 'transmit repeated commands' for Tiger
                    core.set_property('TigerCommHub',
                                      'OnlySendSerialCommandOnChange', 'Yes')
                    '''
                    # if first tile, make parent directory on NAS and start reconstruction script on the server
                    if setup_processing:
                        # make home directory on NAS
                        save_directory_path = Path(save_directory)
                        remote_directory = Path('y:/') / Path(save_directory_path.parts[1])
                        cmd='mkdir ' + str(remote_directory)
                        status_mkdir = subprocess.run(cmd, shell=True)

                        # copy full experiment metadata to NAS
                        src= Path(save_directory) / Path('scan_metadata.csv') 
                        dst= Path(remote_directory) / Path('scan_metadata.csv') 
                        Thread(target=shutil.copy, args=[str(src), str(dst)]).start()

                        setup_processing=False
                    
                    # copy current tyzc metadata to NAS
                    save_directory_path = Path(save_directory)
                    remote_directory = Path('y:/') / Path(save_directory_path.parts[1])
                    src= Path(save_directory) / Path(save_name_stage_positions.parts[2])
                    dst= Path(remote_directory) / Path(save_name_stage_positions.parts[2])
                    Thread(target=shutil.copy, args=[str(src), str(dst)]).start()

                    # copy current tyzc data to NAS
                    save_directory_path = Path(save_directory)
                    remote_directory = Path('y:/') / Path(save_directory_path.parts[1])
                    src= Path(save_directory) / Path(save_name_tyzc+ '_1') 
                    dst= Path(remote_directory) / Path(save_name_tyzc+ '_1') 
                    Thread(target=shutil.copytree, args=[str(src), str(dst)]).start()
                    '''

    # set lasers to zero power
    channel_powers = [0., 0., 0., 0., 0.]
    core.set_property('Coherent-Scientific Remote',
                      'Laser 405-100C - PowerSetpoint (%)', channel_powers[0])
    core.set_property('Coherent-Scientific Remote',
                      'Laser 488-150C - PowerSetpoint (%)', channel_powers[1])
    core.set_property('Coherent-Scientific Remote',
                      'Laser OBIS LS 561-150 - PowerSetpoint (%)',
                      channel_powers[2])
    core.set_property('Coherent-Scientific Remote',
                      'Laser 637-140C - PowerSetpoint (%)', channel_powers[3])
    core.set_property('Coherent-Scientific Remote',
                      'Laser 730-30C - PowerSetpoint (%)', channel_powers[4])

    # turn all lasers off
    core.set_config('Laser', 'Off')
    core.wait_for_config('Laser', 'Off')

    # set all lasers back to software control
    core.set_config('Modulation-405', 'CW (constant power)')
    core.wait_for_config('Modulation-405', 'CW (constant power)')
    core.set_config('Modulation-488', 'CW (constant power)')
    core.wait_for_config('Modulation-488', 'CW (constant power)')
    core.set_config('Modulation-561', 'CW (constant power)')
    core.wait_for_config('Modulation-561', 'CW (constant power)')
    core.set_config('Modulation-637', 'CW (constant power)')
    core.wait_for_config('Modulation-637', 'CW (constant power)')
    core.set_config('Modulation-730', 'CW (constant power)')
    core.wait_for_config('Modulation-730', 'CW (constant power)')

    # set camera to internal control
    core.set_config('Camera-TriggerSource', 'INTERNAL')
    core.wait_for_config('Camera-TriggerSource', 'INTERNAL')

    bridge.close()
Exemplo n.º 10
0
class MainWindow(NewWindow):
    def __init__(self,
                 app,
                 args=None,
                 parent=None,
                 spatial_subsampling=4,
                 time_subsampling=1):
        """
        Intrinsic Imaging GUI
        """
        self.app = app

        super(MainWindow, self).__init__(i=1, title='intrinsic imaging')

        # some initialisation
        self.running, self.stim, self.STIM = False, None, None
        self.datafolder, self.img, self.vasculature_img = '', None, None

        self.t0, self.period = 0, 1

        ### trying the camera
        try:
            # we initialize the camera
            self.bridge = Bridge()
            self.core = self.bridge.get_core()
            self.exposure = self.core.get_exposure()
            self.demo = False
            auto_shutter = self.core.get_property('Core', 'AutoShutter')
            self.core.set_property('Core', 'AutoShutter', 0)
        except BaseException as be:
            print(be)
            print('')
            print(' /!\ Problem with the Camera /!\ ')
            print('        --> no camera found ')
            print('')
            self.exposure = -1  # flag for no camera
            self.demo = True

        ########################
        ##### building GUI #####
        ########################

        self.minView = False
        self.showwindow()

        # layout (from NewWindow class)
        self.init_basic_widget_grid(wdgt_length=3, Ncol_wdgt=20, Nrow_wdgt=20)

        # -- A plot area (ViewBox + axes) for displaying the image ---
        self.view = self.graphics_layout.addViewBox(lockAspect=True,
                                                    invertY=True)
        self.view.setMenuEnabled(False)
        self.view.setAspectLocked()
        self.pimg = pg.ImageItem()

        # ---  setting subject information ---
        self.add_widget(QtWidgets.QLabel('subjects file:'))
        self.subjectFileBox = QtWidgets.QComboBox(self)
        self.subjectFileBox.addItems([
            f for f in os.listdir(subjects_path)[::-1] if f.endswith('.json')
        ])
        self.subjectFileBox.activated.connect(self.get_subject_list)
        self.add_widget(self.subjectFileBox)

        self.add_widget(QtWidgets.QLabel('subject:'))
        self.subjectBox = QtWidgets.QComboBox(self)
        self.get_subject_list()
        self.add_widget(self.subjectBox)

        self.add_widget(QtWidgets.QLabel(20 * ' - '))
        self.vascButton = QtWidgets.QPushButton(
            " - = save Vasculature Picture = - ", self)
        self.vascButton.clicked.connect(self.take_vasculature_picture)
        self.add_widget(self.vascButton)

        self.add_widget(QtWidgets.QLabel(20 * ' - '))

        # ---  data acquisition properties ---
        self.add_widget(QtWidgets.QLabel('data folder:'), spec='small-left')
        self.folderB = QtWidgets.QComboBox(self)
        self.folderB.addItems(FOLDERS.keys())
        self.add_widget(self.folderB, spec='large-right')

        self.add_widget(QtWidgets.QLabel('  - protocol:'), spec='small-left')
        self.protocolBox = QtWidgets.QComboBox(self)
        self.protocolBox.addItems(['ALL', 'up', 'down', 'left', 'right'])
        self.add_widget(self.protocolBox, spec='large-right')
        self.add_widget(
            QtWidgets.QLabel('  - exposure: %.0f ms (from Micro-Manager)' %
                             self.exposure))

        self.add_widget(QtWidgets.QLabel('  - Nrepeat :'), spec='large-left')
        self.repeatBox = QtWidgets.QLineEdit()
        self.repeatBox.setText('10')
        self.add_widget(self.repeatBox, spec='small-right')

        self.add_widget(QtWidgets.QLabel('  - stim. period (s):'),
                        spec='large-left')
        self.periodBox = QtWidgets.QLineEdit()
        self.periodBox.setText('10')
        self.add_widget(self.periodBox, spec='small-right')

        self.add_widget(QtWidgets.QLabel('  - bar size (degree):'),
                        spec='large-left')
        self.barBox = QtWidgets.QLineEdit()
        self.barBox.setText('6')
        self.add_widget(self.barBox, spec='small-right')

        self.add_widget(QtWidgets.QLabel('  - spatial sub-sampling (px):'),
                        spec='large-left')
        self.spatialBox = QtWidgets.QLineEdit()
        self.spatialBox.setText(str(spatial_subsampling))
        self.add_widget(self.spatialBox, spec='small-right')

        self.add_widget(QtWidgets.QLabel('  - acq. freq. (Hz):'),
                        spec='large-left')
        self.freqBox = QtWidgets.QLineEdit()
        self.freqBox.setText('10')
        self.add_widget(self.freqBox, spec='small-right')

        # self.add_widget(QtWidgets.QLabel('  - flick. freq. (Hz) /!\ > acq:'),
        #                 spec='large-left')
        # self.flickBox = QtWidgets.QLineEdit()
        # self.flickBox.setText('10')
        # self.add_widget(self.flickBox, spec='small-right')

        self.demoBox = QtWidgets.QCheckBox("demo mode")
        self.demoBox.setStyleSheet("color: gray;")
        self.add_widget(self.demoBox, spec='large-left')
        self.demoBox.setChecked(self.demo)

        self.camBox = QtWidgets.QCheckBox("cam.")
        self.camBox.setStyleSheet("color: gray;")
        self.add_widget(self.camBox, spec='small-right')
        self.camBox.setChecked(True)

        # ---  launching acquisition ---
        self.liveButton = QtWidgets.QPushButton("--   live view    -- ", self)
        self.liveButton.clicked.connect(self.live_view)
        self.add_widget(self.liveButton)

        # ---  launching acquisition ---
        self.acqButton = QtWidgets.QPushButton("-- RUN PROTOCOL -- ", self)
        self.acqButton.clicked.connect(self.launch_protocol)
        self.add_widget(self.acqButton, spec='large-left')
        self.stopButton = QtWidgets.QPushButton(" STOP ", self)
        self.stopButton.clicked.connect(self.stop_protocol)
        self.add_widget(self.stopButton, spec='small-right')

        # ---  launching analysis ---
        self.add_widget(QtWidgets.QLabel(20 * ' - '))
        self.analysisButton = QtWidgets.QPushButton(" - = Analysis GUI = - ",
                                                    self)
        self.analysisButton.clicked.connect(self.open_analysis)
        self.add_widget(self.analysisButton, spec='large-left')

        self.pimg.setImage(0 * self.get_frame())
        self.view.addItem(self.pimg)
        self.view.autoRange(padding=0.001)
        self.analysisWindow = None

    def take_vasculature_picture(self):

        filename = generate_filename_path(FOLDERS[self.folderB.currentText()],
                                          filename='vasculature-%s' %
                                          self.subjectBox.currentText(),
                                          extension='.tif')

        # save HQ image as tiff
        img = self.get_frame(force_HQ=True)
        np.save(filename.replace('.tif', '.npy'), img)
        img = np.array(255 * (img - img.min()) / (img.max() - img.min()),
                       dtype=np.uint8)
        im = PIL.Image.fromarray(img)
        im.save(filename)
        print('vasculature image, saved as:')
        print(filename)

        # then keep a version to store with imaging:
        self.vasculature_img = self.get_frame()
        self.pimg.setImage(img)  # show on displayn

    def open_analysis(self):

        self.analysisWindow = runAnalysis(self.app, parent=self)

    def get_subject_list(self):
        with open(
                os.path.join(subjects_path,
                             self.subjectFileBox.currentText())) as f:
            self.subjects = json.load(f)
        self.subjectBox.clear()
        self.subjectBox.addItems(self.subjects.keys())

    def init_visual_stim(self, demo=True):

        with open(
                os.path.join(
                    pathlib.Path(__file__).resolve().parents[1], 'intrinsic',
                    'vis_stim', 'up.json'), 'r') as fp:
            protocol = json.load(fp)

        if self.demoBox.isChecked():
            protocol['demo'] = True

        self.stim = visual_stim.build_stim(protocol)
        self.parent = dummy_parent()

    def get_patterns(self, protocol, angle, size, Npatch=30):

        patterns = []

        if protocol in ['left', 'right']:
            z = np.linspace(-self.stim.screen['resolution'][1],
                            self.stim.screen['resolution'][1], Npatch)
            for i in np.arange(len(z) - 1)[(1 if self.flip else 0)::2]:
                patterns.append(
                    visual.Rect(win=self.stim.win,
                                size=(self.stim.angle_to_pix(size),
                                      z[1] - z[0]),
                                pos=(self.stim.angle_to_pix(angle), z[i]),
                                units='pix',
                                fillColor=1))
        if protocol in ['up', 'down']:
            x = np.linspace(-self.stim.screen['resolution'][0],
                            self.stim.screen['resolution'][0], Npatch)
            for i in np.arange(len(x) - 1)[(1 if self.flip else 0)::2]:
                patterns.append(
                    visual.Rect(win=self.stim.win,
                                size=(x[1] - x[0],
                                      self.stim.angle_to_pix(size)),
                                pos=(x[i], self.stim.angle_to_pix(angle)),
                                units='pix',
                                fillColor=1))

        return patterns

    def run(self):

        self.flip = False

        self.stim = visual_stim(
            {
                "Screen": "Dell-2020",
                "presentation-prestim-screen": -1,
                "presentation-poststim-screen": -1
            },
            demo=self.demoBox.isChecked())

        self.Nrepeat = int(self.repeatBox.text())  #
        self.period = float(self.periodBox.text())  # degree / second
        self.bar_size = float(self.barBox.text())  # degree / second
        # self.dt_save, self.dt = 1./float(self.freqBox.text()), 1./float(self.flickBox.text())
        self.dt_save, self.dt = 1. / float(self.freqBox.text()), 1. / float(
            self.freqBox.text())

        xmin, xmax = 1.15 * np.min(self.stim.x), 1.15 * np.max(self.stim.x)
        zmin, zmax = 1.3 * np.min(self.stim.z), 1.3 * np.max(self.stim.z)

        self.angle_start, self.angle_max, self.protocol, self.label = 0, 0, '', ''
        self.Npoints = int(self.period / self.dt_save)

        if self.protocolBox.currentText() == 'ALL':
            self.STIM = {
                'angle_start': [zmin, xmax, zmax, xmin],
                'angle_stop': [zmax, xmin, zmin, xmax],
                'label': ['up', 'left', 'down', 'right'],
                'xmin': xmin,
                'xmax': xmax,
                'zmin': zmin,
                'zmax': zmax
            }
            self.label = 'up'  # starting point
        else:
            self.STIM = {
                'label': [self.protocolBox.currentText()],
                'xmin': xmin,
                'xmax': xmax,
                'zmin': zmin,
                'zmax': zmax
            }
            if self.protocolBox.currentText() == 'up':
                self.STIM['angle_start'] = [zmin]
                self.STIM['angle_stop'] = [zmax]
            if self.protocolBox.currentText() == 'down':
                self.STIM['angle_start'] = [zmax]
                self.STIM['angle_stop'] = [zmin]
            if self.protocolBox.currentText() == 'left':
                self.STIM['angle_start'] = [xmax]
                self.STIM['angle_stop'] = [xmin]
            if self.protocolBox.currentText() == 'right':
                self.STIM['angle_start'] = [xmin]
                self.STIM['angle_stop'] = [xmax]
            self.label = self.protocolBox.currentText()

        for il, label in enumerate(self.STIM['label']):
            self.STIM[label + '-times'] = np.arange(
                self.Npoints * self.Nrepeat) * self.dt_save
            self.STIM[label + '-angle'] = np.concatenate([
                np.linspace(self.STIM['angle_start'][il],
                            self.STIM['angle_stop'][il], self.Npoints)
                for n in range(self.Nrepeat)
            ])

        # initialize one episode:
        self.iEp, self.iTime, self.t0_episode = 0, 0, time.time()

        self.img, self.nSave = self.new_img(), 0

        self.save_metadata()

        print('acquisition running [...]')

        self.update_dt()  # while loop

    def new_img(self):
        return np.zeros(self.imgsize, dtype=np.float64)

    def save_img(self):

        if self.nSave > 0:
            self.img /= self.nSave

        if True:  # live display
            self.pimg.setImage(self.img)

        # NEED TO STORE DATA HERE
        self.FRAMES.append(self.img)

        # re-init time step of acquisition
        self.img, self.nSave = self.new_img(), 0

    def update_dt(self):

        self.tSave = time.time()

        while (time.time() - self.tSave) <= self.dt_save:

            self.t = time.time()
            # show image
            patterns = self.get_patterns(
                self.STIM['label'][self.iEp % len(self.STIM['label'])],
                self.STIM[self.STIM['label'][self.iEp %
                                             len(self.STIM['label'])] +
                          '-angle'][self.iTime], self.bar_size)
            for pattern in patterns:
                pattern.draw()
            try:
                self.stim.win.flip()
            except BaseException:
                pass

            if self.camBox.isChecked():
                # # fetch image
                self.img += self.get_frame()
                self.nSave += 1.0

            # time.sleep(max([self.dt-(time.time()-self.t), 0]))
            # self.flip = (False if self.flip else True) # flip the flag

        self.flip = (False if self.flip else True)  # flip the flag

        if self.camBox.isChecked():
            self.save_img()  # re-init image here

        self.iTime += 1

        # checking if not episode over
        if not (self.iTime < len(self.STIM[self.STIM['label'][
                self.iEp % len(self.STIM['label'])] + '-angle'])):
            if self.camBox.isChecked():
                self.write_data()  # writing data when over
            self.t0_episode, self.img, self.nSave = time.time(), self.new_img(
            ), 0
            self.FRAMES = []  # re init data
            self.iTime = 0
            self.iEp += 1

        # continuing ?
        if self.running:
            QtCore.QTimer.singleShot(1, self.update_dt)

    def write_data(self):

        filename = '%s-%i.nwb' % (self.STIM['label'][self.iEp % len(
            self.STIM['label'])], int(self.iEp / len(self.STIM['label'])) + 1)

        nwbfile = pynwb.NWBFile(
            'Intrinsic Imaging data following bar stimulation',
            'intrinsic',
            datetime.datetime.utcnow(),
            file_create_date=datetime.datetime.utcnow())

        # Create our time series
        angles = pynwb.TimeSeries(
            name='angle_timeseries',
            data=self.STIM[self.STIM['label'][self.iEp %
                                              len(self.STIM['label'])] +
                           '-angle'],
            unit='Rd',
            timestamps=self.STIM[self.STIM['label'][self.iEp %
                                                    len(self.STIM['label'])] +
                                 '-times'])
        nwbfile.add_acquisition(angles)

        images = pynwb.image.ImageSeries(
            name='image_timeseries',
            data=np.array(self.FRAMES, dtype=np.float64),
            unit='a.u.',
            timestamps=self.STIM[self.STIM['label'][self.iEp %
                                                    len(self.STIM['label'])] +
                                 '-times'])

        nwbfile.add_acquisition(images)

        # Write the data to file
        io = pynwb.NWBHDF5IO(os.path.join(self.datafolder, filename), 'w')
        print('writing:', filename)
        io.write(nwbfile)
        io.close()
        print(filename, ' saved !')

    def save_metadata(self):

        filename = generate_filename_path(FOLDERS[self.folderB.currentText()],
                                          filename='metadata',
                                          extension='.npy')
        metadata = {
            'subject': str(self.subjectBox.currentText()),
            'exposure': self.exposure,
            'bar-size': float(self.barBox.text()),
            'acq-freq': float(self.freqBox.text()),
            'period': float(self.periodBox.text()),
            'Nrepeat': int(self.repeatBox.text()),
            'imgsize': self.imgsize,
            'STIM': self.STIM
        }

        np.save(filename, metadata)
        if self.vasculature_img is not None:
            np.save(filename.replace('metadata', 'vasculature'),
                    self.vasculature_img)

        self.datafolder = os.path.dirname(filename)

    def launch_protocol(self):

        if not self.running:
            self.running = True

            # initialization of data
            self.FRAMES = []
            self.img = self.get_frame()
            self.imgsize = self.img.shape
            self.pimg.setImage(self.img)
            self.view.autoRange(padding=0.001)

            self.run()

        else:
            print(
                ' /!\  --> pb in launching acquisition (either already running or missing camera)'
            )

    def live_view(self):
        self.running, self.t0 = True, time.time()
        self.update_Image()

    def stop_protocol(self):
        if self.running:
            self.running = False
            if self.stim is not None:
                self.stim.close()
        else:
            print('acquisition not launched')

    def get_frame(self, force_HQ=False):

        if self.exposure > 0:
            self.core.snap_image()
            tagged_image = self.core.get_tagged_image()
            #pixels by default come out as a 1D array. We can reshape them into an image
            img = np.reshape(tagged_image.pix,
                             newshape=[
                                 tagged_image.tags['Height'],
                                 tagged_image.tags['Width']
                             ])
        elif (self.stim is not None) and (self.STIM is not None):
            it = int((time.time() - self.t0_episode) / self.dt_save) % int(
                self.period / self.dt_save)
            protocol = self.STIM['label'][self.iEp % len(self.STIM['label'])]
            if protocol == 'left':
                img = np.random.randn(*self.stim.x.shape)+\
                    np.exp(-(self.stim.x-(40*it/self.Npoints-20))**2/2./10**2)*\
                    np.exp(-self.stim.z**2/2./15**2)
            elif protocol == 'right':
                img = np.random.randn(*self.stim.x.shape)+\
                    np.exp(-(self.stim.x+(40*it/self.Npoints-20))**2/2./10**2)*\
                    np.exp(-self.stim.z**2/2./15**2)
            elif protocol == 'up':
                img = np.random.randn(*self.stim.x.shape)+\
                    np.exp(-(self.stim.z-(40*it/self.Npoints-20))**2/2./10**2)*\
                    np.exp(-self.stim.x**2/2./15**2)
            else:  # down
                img = np.random.randn(*self.stim.x.shape)+\
                    np.exp(-(self.stim.z+(40*it/self.Npoints-20))**2/2./10**2)*\
                    np.exp(-self.stim.x**2/2./15**2)

        else:
            img = np.random.randn(720, 1280)

        if (int(self.spatialBox.text()) > 1) and not force_HQ:
            return 1.0 * analysis.resample_img(img, int(
                self.spatialBox.text()))
        else:
            return 1.0 * img

    def update_Image(self):
        # plot it
        self.pimg.setImage(self.get_frame())
        new_t0 = time.time()
        print('dt=%.1f ms' % (1e3 * (new_t0 - self.t0)))
        self.t0 = new_t0
        if self.running:
            QtCore.QTimer.singleShot(1, self.update_Image)

    def hitting_space(self):
        if not self.running:
            self.launch_protocol()
        else:
            self.stop_protocol()

    def process(self):
        self.launch_analysis()

    def quit(self):
        if self.exposure > 0:
            self.bridge.close()
        sys.exit()
Exemplo n.º 11
0
def main():

    #------------------------------------------------------------------------------------------------------------------------------------
    #----------------------------------------------Begin setup of scan parameters--------------------------------------------------------
    #------------------------------------------------------------------------------------------------------------------------------------

    # lasers to use
    # 0 -> inactive
    # 1 -> active
    state_405 = 0
    state_488 = 0
    state_561 = 0
    state_635 = 1
    state_730 = 0

    # laser powers (0 -> 100%)
    power_405 = 2
    power_488 = 2
    power_561 = 2
    power_635 = 50
    power_730 = 0

    # exposure time
    exposure_ms = 5.

    # scan axis limits. Use stage positions reported by MM
    scan_axis_start_um = 1614.  #unit: um
    scan_axis_end_um = 1625.  #unit: um

    tile_axis_start_um = -265.
    height_axis_start_um = 9500.

    # FOV parameters
    # ONLY MODIFY IF NECESSARY
    ROI = [1024, 0, 256, 2048]  #unit: pixels

    # setup file name
    save_directory = Path('E:/20201023/')
    save_name = 'scan_test'

    #------------------------------------------------------------------------------------------------------------------------------------
    #----------------------------------------------End setup of scan parameters----------------------------------------------------------
    #------------------------------------------------------------------------------------------------------------------------------------

    bridge = Bridge()
    core = bridge.get_core()

    # set camera into 16bit readout mode
    # give camera time to change modes if necessary
    core.set_property('Camera', 'ReadoutRate', '100MHz 16bit')
    time.sleep(5)

    # set camera into low noise readout mode
    # give camera time to change modes if necessary
    core.set_property('Camera', 'Gain', '2-CMS')
    time.sleep(5)

    # set camera to trigger first mode
    # give camera time to change modes if necessary
    core.set_property('Camera', 'Trigger Timeout (secs)', 60)
    time.sleep(5)

    # set camera to internal trigger
    # give camera time to change modes if necessary
    core.set_property('Camera', 'TriggerMode', 'Internal Trigger')
    time.sleep(5)

    # set exposure
    core.set_exposure(exposure_ms)

    # get actual framerate, accounting for readout time
    actual_readout_ms = float(core.get_property(
        'Camera', 'ActualInterval-ms'))  #unit: ms

    # camera pixel size
    pixel_size_um = .115  # unit: um

    # scan axis setup
    scan_axis_step_um = 0.2  # unit: um
    scan_axis_step_mm = scan_axis_step_um / 1000.  #unit: mm
    scan_axis_start_mm = scan_axis_start_um / 1000.  #unit: mm
    scan_axis_end_mm = scan_axis_end_um / 1000.  #unit: mm
    scan_axis_range_um = np.abs(scan_axis_end_um -
                                scan_axis_start_um)  # unit: um
    scan_axis_range_mm = scan_axis_range_um / 1000  #unit: mm
    actual_exposure_s = actual_readout_ms / 1000.  #unit: s
    scan_axis_speed = np.round(scan_axis_step_mm / actual_exposure_s,
                               2)  #unit: mm/s
    scan_axis_positions = np.rint(scan_axis_range_mm /
                                  scan_axis_step_mm).astype(int)

    # get handle to xy and z stages
    xy_stage = core.get_xy_stage_device()
    z_stage = core.get_focus_device()

    # Setup PLC card to give start trigger
    plcName = 'PLogic:E:36'
    propPosition = 'PointerPosition'
    propCellConfig = 'EditCellConfig'
    addrOutputBNC3 = 35
    addrStageSync = 46  # TTL5 on Tiger backplane = stage sync signal

    # connect stage sync signal to BNC output
    core.set_property(plcName, propPosition, addrOutputBNC3)
    core.set_property(plcName, propCellConfig, addrStageSync)

    # turn on 'transmit repeated commands' for Tiger
    core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'No')

    # set tile axis speed for all moves
    command = 'SPEED Y=.5'
    core.set_property('TigerCommHub', 'SerialCommand', command)

    # check to make sure Tiger is not busy
    ready = 'B'
    while (ready != 'N'):
        command = 'STATUS'
        core.set_property('TigerCommHub', 'SerialCommand', command)
        ready = core.get_property('TigerCommHub', 'SerialResponse')
        time.sleep(.500)

    # set scan axis speed for large move to initial position
    command = 'SPEED X=.5'
    core.set_property('TigerCommHub', 'SerialCommand', command)

    # check to make sure Tiger is not busy
    ready = 'B'
    while (ready != 'N'):
        command = 'STATUS'
        core.set_property('TigerCommHub', 'SerialCommand', command)
        ready = core.get_property('TigerCommHub', 'SerialResponse')
        time.sleep(.500)

    # turn off 'transmit repeated commands' for Tiger
    core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'Yes')

    # move scan scan stage to initial position
    core.set_xy_position(scan_axis_start_um, tile_axis_start_um)
    core.wait_for_device(xy_stage)
    core.set_position(height_axis_start_um)
    core.wait_for_device(z_stage)

    # turn on 'transmit repeated commands' for Tiger
    core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'No')

    # set scan axis speed to correct speed for continuous stage scan
    # expects mm/s
    command = 'SPEED X=' + str(scan_axis_speed)
    core.set_property('TigerCommHub', 'SerialCommand', command)

    # check to make sure Tiger is not busy
    ready = 'B'
    while (ready != 'N'):
        command = 'STATUS'
        core.set_property('TigerCommHub', 'SerialCommand', command)
        ready = core.get_property('TigerCommHub', 'SerialResponse')
        time.sleep(.500)

    # set scan axis to true 1D scan with no backlash
    command = '1SCAN X? Y=0 Z=9 F=0'
    core.set_property('TigerCommHub', 'SerialCommand', command)

    # check to make sure Tiger is not busy
    ready = 'B'
    while (ready != 'N'):
        command = 'STATUS'
        core.set_property('TigerCommHub', 'SerialCommand', command)
        ready = core.get_property('TigerCommHub', 'SerialResponse')
        time.sleep(.500)

    # set range for scan axis
    # expects mm
    command = '1SCANR X=' + str(scan_axis_start_mm) + ' Y=' + str(
        scan_axis_end_mm) + ' R=50'
    core.set_property('TigerCommHub', 'SerialCommand', command)

    # check to make sure Tiger is not busy
    ready = 'B'
    while (ready != 'N'):
        command = 'STATUS'
        core.set_property('TigerCommHub', 'SerialCommand', command)
        ready = core.get_property('TigerCommHub', 'SerialResponse')
        time.sleep(.500)

    #command = '1SCANV X=0 Y=0 Z=2'
    #core.set_property('TigerCommHub','SerialCommand',command)

    # check to make sure Tiger is not busy
    ready = 'B'
    while (ready != 'N'):
        command = 'STATUS'
        core.set_property('TigerCommHub', 'SerialCommand', command)
        ready = core.get_property('TigerCommHub', 'SerialResponse')
        time.sleep(.500)

    # turn off 'transmit repeated commands' for Tiger
    core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'Yes')

    # construct boolean array for lasers to use
    channel_states = [state_405, state_488, state_561, state_635, state_730]
    channel_powers = [power_405, power_488, power_561, power_635, power_730]

    # set all lasers to off and user defined power
    core.set_property('Coherent-Scientific Remote',
                      'Laser 405-100C - PowerSetpoint (%)', channel_powers[0])
    core.set_property('Coherent-Scientific Remote',
                      'Laser 488-150C - PowerSetpoint (%)', channel_powers[1])
    core.set_property('Coherent-Scientific Remote',
                      'Laser OBIS LS 561-150 - PowerSetpoint (%)',
                      channel_powers[2])
    core.set_property('Coherent-Scientific Remote',
                      'Laser 637-140C - PowerSetpoint (%)', channel_powers[3])
    core.set_property('Coherent-Scientific Remote',
                      'Laser 730-30C - PowerSetpoint (%)', channel_powers[4])

    print(scan_axis_positions)
    # create events to execute scan
    events = []
    #for t in range(2):
    for x in range(scan_axis_positions):
        evt = {'axes': {'x': x}}

        events.append(evt)

    # set camera to internal trigger
    # give camera time to change modes if necessary
    core.set_property('Camera', 'TriggerMode', 'Trigger first')
    time.sleep(1)

    # run acquisition
    with Acquisition(directory=save_directory,
                     name=save_name,
                     post_hardware_hook_fn=post_hook_fn,
                     post_camera_hook_fn=camera_hook_fn,
                     show_display=True,
                     max_multi_res_index=0) as acq:
        acq.acquire(events)

    # set camera to internal trigger
    # give camera time to change modes if necessary
    core.set_property('Camera', 'TriggerMode', 'Internal Trigger')
    time.sleep(1)