Example #1
0
def main(argv=None):
    parser = argparse.ArgumentParser(description='microscope server control')
    parser.add_argument('--debug', action='store_true', help='show full stack traces on error')
    subparsers = parser.add_subparsers(help='sub-command help', dest='command')
    subparsers.required = True
    parser_start = subparsers.add_parser('start', help='start the microscope server, if not running')
    parser_start.add_argument('--local', action='store_false', dest='public', help='Allow only local connections to the server [default: allow network connections]')
    parser_start.add_argument('--verbose', action='store_true', help='Log all RPC calls and property state changes.')
    parser_stop = subparsers.add_parser('stop', help='stop the microscope server, if running')
    parser_stop.add_argument('-f', '--force', action='store_true', help='forcibly kill the server process')
    parser_restart = subparsers.add_parser('restart', help='restart the microscope server, if running')
    parser_restart.add_argument('-f', '--force', action='store_true', help='forcibly kill the server process')
    parser_status = subparsers.add_parser('status', help='report whether the microscope server is running')
    args = parser.parse_args(argv)

    try:
        server = scope_server.ScopeServer()
        if args.command == 'status':
            server.status()
        if args.command in {'stop', 'restart'}:
            server.stop(args.force)
        if args.command == 'start':
            with server.arg_file.open('w') as f:
                datafile.json_encode_legible_to_file(dict(public=args.public, verbose=args.verbose), f)
        if args.command in {'start', 'restart'}:
            server.start()
    except Exception as e:
        if args.debug:
            traceback.print_exc(file=sys.stderr)
        else:
            sys.stderr.write(str(e)+'\n')
        return 1
Example #2
0
def take_sequential_images(scope, out_dir, tl_intensity=255, exposure_time=2):
    '''
        Take sequential images as one specifies positions on a stage
    '''

    out_dir = pathlib.Path(out_dir)
    scope.camera.acquisition_sequencer.new_sequence()
    scope.camera.acquisition_sequencer.add_step(exposure_time,
                                                'TL',
                                                tl_intensity=tl_intensity)
    out_dir.mkdir(exist_ok=True)
    pos_num = 0
    print(
        'Press enter after each position has been found; press control-c to end'
    )

    while True:
        try:
            input()
        except KeyboardInterrupt:
            break
        bf_image = scope.camera.acquisition_sequencer.run()[0]
        freeimage.write(bf_image, out_dir / f'_{pos_num:03d}.png')
        pos_num += 1

    if pos_num > 0:
        imaging_parameters = {
            'lamp': 'TL',
            'exposure': exposure_time,
            'intensity': tl_intensity
        }
        with (out_dir / 'imaging_parameters.json').open('w') as param_file:
            datafile.json_encode_legible_to_file(imaging_parameters,
                                                 param_file)
def reset_positions_with_offset(experiment_dir, offset):
    ''' Modify position coordinates based on a fixed x-y offset
    
    Parameters:
        experiment_dir - str/pathlib.Path to experiment root
        offset - list giving the x-y offset
    '''

    experiment_dir = pathlib.Path(experiment_dir)
    print(f'Modifying positions for {experiment_dir.name}')
    metadata = load_data.read_metadata(experiment_dir)
    new_metadata = metadata.copy()

    if len(offset) == 2:
        offset.extend([0])

    try:
        time_label = time.strftime('%Y%m%d-%H%M-%S')

        for position in metadata['positions']:
            position_coords = metadata['positions'][position]
            new_metadata['positions'][position] = [
                position_coords[0] + offset[0], position_coords[1] + offset[1],
                position_coords[2] + offset[2]
            ]

        with (experiment_dir /
              f'experiment_metadata_beforechangingpositions_{time_label}.json'
              ).open('w') as mdata_file:
            datafile.json_encode_legible_to_file(metadata, mdata_file)

        load_data.write_metadata(new_metadata, experiment_dir)
    except KeyboardInterrupt:
        pass
Example #4
0
def main(argv=None):
    parser = argparse.ArgumentParser(description='microscope server control')
    parser.add_argument('--debug',
                        action='store_true',
                        help='show full stack traces on error')
    subparsers = parser.add_subparsers(help='sub-command help', dest='command')
    subparsers.required = True
    parser_start = subparsers.add_parser(
        'start', help='start the microscope server, if not running')
    parser_start.add_argument(
        '--local',
        action='store_false',
        dest='public',
        help=
        'Allow only local connections to the server [default: allow network connections]'
    )
    parser_start.add_argument(
        '--verbose',
        action='store_true',
        help='Log all RPC calls and property state changes.')
    parser_stop = subparsers.add_parser(
        'stop', help='stop the microscope server, if running')
    parser_stop.add_argument('-f',
                             '--force',
                             action='store_true',
                             help='forcibly kill the server process')
    parser_restart = subparsers.add_parser(
        'restart', help='restart the microscope server, if running')
    parser_restart.add_argument('-f',
                                '--force',
                                action='store_true',
                                help='forcibly kill the server process')
    parser_status = subparsers.add_parser(
        'status', help='report whether the microscope server is running')
    args = parser.parse_args(argv)

    try:
        server = scope_server.ScopeServer()
        if args.command == 'status':
            server.status()
        if args.command in {'stop', 'restart'}:
            server.stop(args.force)
        if args.command == 'start':
            with server.arg_file.open('w') as f:
                datafile.json_encode_legible_to_file(
                    dict(public=args.public, verbose=args.verbose), f)
        if args.command in {'start', 'restart'}:
            server.start()
    except Exception as e:
        if args.debug:
            traceback.print_exc(file=sys.stderr)
        else:
            sys.stderr.write(str(e) + '\n')
        return 1
Example #5
0
def create_metadata_file(data_dir, positions, z_max, reference_positions,
        nominal_temperature, objective, optocoupler, filter_cube,
        fluorescence_flatfield_lamp, save_focus_stacks=None, **other_metadata):
    """ Create the experiment_metadata.json file for timecourse acquisitions.

    Parameters:
        data_dir: directory to write metadata file into
        positions: list of (x,y,z) positions, OR dict mapping different category
            names to lists of (x,y,z) positions.
        z_max: maximum z-value allowed during autofocus
        reference_positions: list of (x,y,z) positions to be used to generate
            brightfield and optionally fluorescence flat-field images.
        nominal_temperature: intended temperature for experiment
        objective, optocoupler: objective and optocoupler to be used.
        filter_cube: name of the filter cube to use
        fluorescence_flatfield_lamp: if fluorescent flatfield images are
            desired, provide the name of an appropriate spectra x lamp that is
            compatible with the specified filter cube. Use None to disable
            fluorescence flatfielding.
        save_focus_stacks: if None, don't save any focus stacks. If a list of position
            names, save focus stacks for those positions. If a number, save
            focus stacks for that number of positions.
        **other_metadata: key-values that will be saved directly in metadata json.
    """
    data_dir = pathlib.Path(data_dir)
    data_dir.mkdir(parents=True, exist_ok=True)
    try:
        items = positions.items()
    except AttributeError:
        items = [('', positions)]
    named_positions = {}
    for name_prefix, positions in items:
        names = _name_positions(len(positions), name_prefix)
        named_positions.update(zip(names, positions))
    bf_meter_position_name = _choose_bf_metering_pos(named_positions)
    metadata = dict(z_max=z_max, reference_positions=reference_positions,
        positions=named_positions, bf_meter_position_name=bf_meter_position_name,
        objective=int(objective), optocoupler=float(optocoupler),
        nominal_temperature=float(nominal_temperature), filter_cube=str(filter_cube),
        fluorescence_flatfield_lamp=fluorescence_flatfield_lamp, **other_metadata)
    if save_focus_stacks:
        try:
            # check if it's iterable
            for pos in save_focus_stacks:
                assert pos in named_positions
        except TypeError:
            num_to_save = int(save_focus_stacks)
            save_indices = numpy.random.permutation(len(named_positions))[:num_to_save]
            names = list(named_positions.keys())
            save_focus_stacks = [names[i] for i in save_indices]
        metadata['save_focus_stacks'] = save_focus_stacks
    with (data_dir / 'experiment_metadata.json').open('w') as f:
        datafile.json_encode_legible_to_file(metadata, f)
Example #6
0
def create_metadata_file(data_dir, positions, z_max, reference_positions,
        nominal_temperature, objective, optocoupler, filter_cube,
        fluorescence_flatfield_lamp, save_focus_stacks=None, **other_metadata):
    """ Create the experiment_metadata.json file for timecourse acquisitions.

    Parameters:
        data_dir: directory to write metadata file into
        positions: list of (x,y,z) positions, OR dict mapping different category
            names to lists of (x,y,z) positions.
        z_max: maximum z-value allowed during autofocus
        reference_positions: list of (x,y,z) positions to be used to generate
            brightfield and optionally fluorescence flat-field images.
        nominal_temperature: intended temperature for experiment
        objective, optocoupler: objective and optocoupler to be used.
        filter_cube: name of the filter cube to use
        fluorescence_flatfield_lamp: if fluorescent flatfield images are
            desired, provide the name of an appropriate spectra x lamp that is
            compatible with the specified filter cube. Use None to disable
            fluorescence flatfielding.
        save_focus_stacks: if None, don't save any focus stacks. If a list of position
            names, save focus stacks for those positions. If a number, save
            focus stacks for that number of positions.
        **other_metadata: key-values that will be saved directly in metadata json.
    """
    data_dir = pathlib.Path(data_dir)
    data_dir.mkdir(parents=True, exist_ok=True)
    try:
        items = positions.items()
    except AttributeError:
        items = [('', positions)]
    named_positions = {}
    for name_prefix, positions in items:
        names = _name_positions(len(positions), name_prefix)
        named_positions.update(zip(names, positions))
    bf_meter_position_name = _choose_bf_metering_pos(named_positions)
    metadata = dict(z_max=z_max, reference_positions=reference_positions,
        positions=named_positions, bf_meter_position_name=bf_meter_position_name,
        objective=int(objective), optocoupler=float(optocoupler),
        nominal_temperature=float(nominal_temperature), filter_cube=str(filter_cube),
        fluorescence_flatfield_lamp=fluorescence_flatfield_lamp, **other_metadata)
    if save_focus_stacks:
        try:
            # check if it's iterable
            for pos in save_focus_stacks:
                assert pos in named_positions
        except TypeError:
            num_to_save = int(save_focus_stacks)
            save_indices = numpy.random.permutation(len(named_positions))[:num_to_save]
            names = list(named_positions.keys())
            save_focus_stacks = [names[i] for i in save_indices]
        metadata['save_focus_stacks'] = save_focus_stacks
    with (data_dir / 'experiment_metadata.json').open('w') as f:
        datafile.json_encode_legible_to_file(metadata, f)
Example #7
0
def take_automated_plate_images(scope, out_dir):
    out_dir = pathlib.Path(out_dir)
    scope.camera.acquisition_sequencer.new_sequence()
    scope.camera.acquisition_sequencer.add_step(2, 'TL', tl_intensity=255)
    out_dir.mkdir(exist_ok=True)
    field_spacing = 2160 * 0.0065 * 1 / 2.5  # FILL ME IN WITH APPROPRIATE FIELD SIZE BASED ON 2.5X OBJECTIVE

    try:
        input('Specify center of plate')
        center_position = scope.stage.position
        input('Specify outer extent of plate')
        outer_position = scope.stage.position

        roi_radius = ((center_position[0] - outer_position[0])**2 +
                      (center_position[1] - outer_position[1])**2)**0.5

        # Define function to interpolate z - assume the plate surface is a parabola with radial symmetry about its center w.r.t. both x & y
        scale_param = (outer_position[2] - center_position[2]) / (roi_radius**
                                                                  2)
        interpolate_z = lambda x, y: scale_param * (
            (x - center_position[0])**2 +
            (y - center_position[1])**2) + center_position[2]

        grid_x = np.arange(center_position[0] - roi_radius / np.sqrt(2),
                           center_position[0] + roi_radius / np.sqrt(2),
                           field_spacing)
        grid_y = np.arange(center_position[1] - roi_radius / np.sqrt(2),
                           center_position[1] + roi_radius / np.sqrt(2),
                           field_spacing)
        xcoor, ycoor = np.meshgrid(grid_x, grid_y)
        xcoor = np.array(
            [pts if num % 2 else pts[::-1] for num, pts in enumerate(xcoor)]
        )  # invert the x-coordinates appropriately so that we make take min time to traverse the slide
        #raise Exception()

        pos_num = 0
        for x, y in zip(xcoor.flatten(), ycoor.flatten()):
            scope.stage.position = [x, y, interpolate_z(x, y)]

            bf_image = scope.camera.acquisition_sequencer.run()[0]
            freeimage.write(bf_image, out_dir / f'_{pos_num:03d}.png')
            pos_num += 1

        imaging_parameters = {'lamp': 'TL', 'exposure': 2, 'intensity': 255}
        with (out_dir / 'imaging_parameters.json').open('w') as param_file:
            datafile.json_encode_legible_to_file(imaging_parameters,
                                                 param_file)
        scope.stage.position = center_position
    except KeyboardInterrupt:
        return
def reset_positions_manual(scope,
                           experiment_dir,
                           *annotation_filters,
                           revert_z=False):
    '''Reset positions manually for an experiment (i.e. with a separate ris_widget window open)
    
    Parameters:
        scope - ScopeClient object as defined by scope.scope_client
        experiment_dir - str/pathlib.Path to experiment
        annotation_filters - Optional variable filters to use to isolate specific positions of interest

    Call with annotation filters like so:
    reset_position.reset_positions(scope, experiment_dir, elegant_filters.filter_excluded, elegant_filters.filter_live_animals)
    '''

    experiment_dir = pathlib.Path(experiment_dir)
    print(f'Traversing {experiment_dir.name}')
    metadata = load_data.read_metadata(experiment_dir)
    if annotation_filters:
        experiment_annotations = load_data.read_annotations(experiment_dir)
        for filter in annotation_filters:
            experiment_annotations = load_data.filter_annotations(
                experiment_annotations, filter)
        positions = experiment_annotations.keys()
    else:
        positions = metadata['positions'].keys()

    new_positions = poll_positions(scope,
                                   metadata,
                                   positions,
                                   revert_z=revert_z)

    if new_positions:
        try:
            input(f'\nPress any key to save positions; ctrl-c to abort')
            time_label = time.strftime('%Y%m%d-%H%M-%S')

            with (experiment_dir /
                  f'experiment_metadata_beforechangingpositions_{time_label}.json'
                  ).open('w') as mdata_file:
                datafile.json_encode_legible_to_file(metadata, mdata_file)

            metadata['positions'].update(new_positions)
            load_data.write_metadata(metadata, experiment_dir)
        except KeyboardInterrupt:
            pass
    else:
        print('No positions found to reset')
Example #9
0
def well_plate_acquisition(scope,
                           out_dir,
                           tl_intensity,
                           grid_size=[4, 6],
                           well_spacing_cc=12.92):
    '''
        grid_size, well_spacing_cc for nominal Falcon 48-well plate (latter in mm)

    '''

    out_dir = pathlib.Path(out_dir)
    scope.camera.acquisition_sequencer.new_sequence()
    scope.camera.acquisition_sequencer.add_step(2,
                                                'TL',
                                                tl_intensity=tl_intensity)
    out_dir.mkdir()

    try:
        print('Specify xy-position for top-left well; press ctrl-c to abort.')
        input()
        topleft_position = scope.stage.position

        pos_num = 0
        for row_num in range(grid_size[0]):
            for column_num in range(grid_size[1]):
                scope.stage.position = [
                    topleft_position[0] + column_num * well_spacing_cc,
                    topleft_position[1] + row_num * well_spacing_cc,
                    topleft_position[2],
                ]
                print('Adjust to desired z-position; press ctrl-c to abort.')
                input()

                bf_image = scope.camera.acquisition_sequencer.run()[0]
                freeimage.write(bf_image, out_dir / f'_{pos_num:03d}.png')
                pos_num += 1
        imaging_parameters = {
            'lamp': 'TL',
            'exposure': 2,
            'intensity': tl_intensity
        }
        with (out_dir / 'imaging_parameters.json').open('w') as param_file:
            datafile.json_encode_legible_to_file(imaging_parameters,
                                                 param_file)
    except KeyboardInterrupt:
        return
Example #10
0
def make_align_img(scope, expt_dir):
    expt_dir = pathlib.Path(expt_dir)
    try:
        scope_pos, my_image = take_img(scope, expt_dir)
    except KeyboardInterrupt:
        return

    time_label = time.strftime('%Y%m%d-%H%M-%S')

    with (expt_dir / 'experiment_metadata.json').open('r') as mdata_file:
        metadata = json.load(mdata_file)
    with (expt_dir / f'experiment_metadata_noalign_{time_label}.json'
          ).open('w') as mdata_file:
        datafile.json_encode_legible_to_file(metadata, mdata_file)

    metadata['align_position'] = scope_pos
    with (expt_dir / 'experiment_metadata.json').open('w') as mdata_file:
        datafile.json_encode_legible_to_file(metadata, mdata_file)
    (expt_dir / 'calibrations').mkdir(exist_ok=True)
    freeimage.write(my_image, expt_dir / 'calibrations' / 'align_image.png')
Example #11
0
 def _write(self, jobs):
     """Write Job tuples as json to self.backing_file."""
     job_list = [[str(exec_file)] + rest
                 for exec_file, *rest in jobs.values()]
     with self.jobs_lock, self.backing_file.open('w') as bf:
         datafile.json_encode_legible_to_file(job_list, bf)
Example #12
0
 def _write(self, jobs):
     """Write Job tuples as json to self.backing_file."""
     job_list = [[str(exec_file)] + rest for exec_file, *rest in jobs.values()]
     with self.jobs_lock, self.backing_file.open('w') as bf:
         datafile.json_encode_legible_to_file(job_list, bf)
Example #13
0
def perform_alignment(scope, expt_dir, rw):
    px_conversion = 1.304 / 1000  #mm/px
    expt_dir = pathlib.Path(expt_dir)

    before_img = freeimage.read(
        str(expt_dir / 'calibrations' / 'align_image.png'))
    with (expt_dir / 'experiment_metadata.json').open('r') as mdata_file:
        metadata = json.load(mdata_file)
    before_scope_pos = np.array(metadata['align_position'])
    if scope is not None:
        scope.stage.position = before_scope_pos  # Set z to same position
        after_scope_pos, after_img = take_img(scope, expt_dir)
    else:  # old debugging not on scope
        after_scope_pos = np.array([163.6972, 3.085, 23.739])
        #~ after_img = freeimage.read('/mnt/scopearray/Sinha_Drew/testing/align_pics/after_img.png')
        #after_img = freeimage.read('/media/Data/Documents/Dropbox/align_pics/after_img.png')
        #after_img = freeimage.read('/home/zplab/Desktop/align_pics/after_img.png')

    if len(rw.flipbook.pages) > 0: rw.flipbook.pages.clear()
    rw.flipbook.pages.append(ImageList([Image(before_img), Image(after_img)]))
    #rw.layers[0].tint=[255,232,185,0.5]
    #rw.layers[1].tint = [270,70,255,0.5]
    # my_ptpicker = PointListPicker(rw.main_view,rw.main_scene.layer_stack_item)
    # my_ptpicker = SimplePointPicker(rw.main_view,rw.main_scene.layer_stack_item)
    my_ptpicker = point_set.PointSet(rw)

    #ip_input('Click on first landmark in old and new images; press Enter when done.')
    input(
        'Click on first landmark in old and new images; press Enter when done.'
    )
    before_first_pos, after_first_pos = [
        np.array(point) for point in my_ptpicker.points
    ]  # IN PIXELS
    print('Acquired first landmark')
    # my_ptpicker.points = []
    for point in my_ptpicker.points:
        point.remove()

    ip_input(
        'Click on second landmark in old and new images; press Enter when done.'
    )
    before_next_pos, after_next_pos = [
        np.array(point) for point in my_ptpicker.points
    ]
    print('Acquired second landmark')
    # my_ptpicker.points = []
    for point in my_ptpicker.points:
        point.remove()

    xy_offset = after_scope_pos[:2] + after_first_pos * px_conversion - (
        before_scope_pos[:2] + before_first_pos * px_conversion)
    xy_offset = xy_offset * [
        -1, 1
    ]  #Correct for directionality of stage on ISCOPE    CHECK THIS ON SCOPE!!!!!!!!!!!
    print(xy_offset)

    before_next_adj = before_next_pos - before_first_pos
    after_next_adj = after_next_pos - after_first_pos

    before_incline = np.arctan(before_next_adj[1] / before_next_adj[0])
    after_incline = np.arctan(after_next_adj[1] / after_next_adj[0])

    incline_offset = after_incline - before_incline
    print('Before incline:{:.2f}\nAfter incline:{:.2f}\nOffset:{:.2f}'.format(
        before_incline, after_incline, incline_offset))  # GOOD UP TO HERE.

    #raise Exception("xy:{} (px), incline:{} (deg)".format(xy_offset,incline_offset*360/2*np.pi))

    old_metadata = metadata.copy()
    metadata['align_position'].append(after_scope_pos)  # Save the old!
    for well in metadata['positions']:
        # Do rotation first
        rotated_point = np.dot(
            np.array([[np.cos(incline_offset), -np.sin(incline_offset)],
                      [np.sin(incline_offset),
                       np.cos(incline_offset)]]),
            np.array(metadata['positions'][well][:2] -
                     np.array(before_scope_pos[:2] +
                              before_first_pos * px_conversion))
        ) + np.array(before_scope_pos[:2] + before_first_pos * px_conversion)
        metadata['positions'][well][:2] = list(rotated_point + xy_offset)

    wells = [
        well_dir.parts[-1] for well_dir in expt_dir.iterdir()
        if str(well_dir.parts[-1]).isnumeric()
    ]
    metadata['realignment_time'] = metadata.get('realignment_time', []).append(
        time.strftime("%Y-%m-%dt%H%M"))

    # Compare before and after positions (offset only)
    scope.stage.position = list(
        np.append(before_scope_pos[:2] + xy_offset, before_scope_pos[2]))
    trash, final_landmark_img = take_img(scope, expt_dir, poll=False)
    rw.flipbook.pages.append(
        ImageList([Image(before_img),
                   Image(final_landmark_img)]))
    ip_input(
        'Press anything if landmarks looks aligned (xy-offset); ctrl-c to abort'
    )

    # Compare first and last wells
    rw.flipbook.pages.clear()
    before_first_img = freeimage.read([
        bf_file for bf_file in (expt_dir / wells[0]).iterdir()
        if 'bf.png' in bf_file.parts[-1]
    ][0])
    scope.stage.position = list(
        np.append(
            np.array(old_metadata['positions'][wells[0]][:2]) + xy_offset,
            old_metadata['positions'][
                wells[0]][2]))  # Do one with the offset for debugging
    trash, after_first_offset_img = take_img(scope, expt_dir, poll=False)
    rw.flipbook.pages.append(
        ImageList([Image(before_first_img),
                   Image(after_first_offset_img)
                   ]))  #,name='Before After Well'+str(wells[0]))
    scope.stage.position = metadata['positions'][wells[0]]
    trash, after_first_img = take_img(scope, expt_dir, poll=False)
    rw.flipbook.pages.append(
        ImageList([Image(before_first_img),
                   Image(after_first_img)
                   ]))  #,name='Before After Well'+str(wells[0]))
    ip_input('Press anything if first well looks aligned; ctrl-c to abort')

    before_last_img = freeimage.read([
        bf_file for bf_file in (expt_dir / wells[-1]).iterdir()
        if 'bf.png' in bf_file.parts[-1]
    ][0])
    scope.stage.position = metadata['positions'][wells[-1]]
    trash, after_last_img = take_img(scope, expt_dir, poll=False)
    rw.flipbook.pages.clear()
    rw.flipbook.pages.append(
        ImageList([Image(before_last_img),
                   Image(after_last_img)
                   ]))  # ,name='Before After Well'+str(wells[-1]))
    ip_input('Press anything if last well looks aligned; ctrl-c to abort')

    with (expt_dir /
          'experiment_metadata_oldprealignment.json').open('w') as mdata_file:
        datafile.json_encode_legible_to_file(old_metadata, mdata_file)
    with (expt_dir / 'experiment_metadata.json').open('w') as mdata_file:
        datafile.json_encode_legible_to_file(metadata, mdata_file)
    freeimage.write(before_img,
                    str(expt_dir / 'calibrations' / 'old_align_image.png'))
    freeimage.write(after_img,
                    str(expt_dir / 'calibrations' / 'align_image.png'))