def main(): parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description='GUI for sorting filenames') parser.add_argument("stack", type=str, help="stack name") args = parser.parse_args() stack = args.stack sqlController = SqlController() sections = list(sqlController.get_valid_sections(stack)) # Queued transformations keeps track of each transformation the user wants to perform # on ALL the images. The transformations are applied to the large "raw" files after # the user clicks "done orienting" if len(sections) > 0: global app app = QApplication(sys.argv) global ex ex = init_GUI(stack) # Run GUI as usual ex.show() # Simulate a user's keypress because otherwise the autozoom is weird ex.keyPressEvent(91) sys.exit(app.exec_()) else: print('There are no sections to work with.')
def make_pages(animal, fetch, layer): templateLoader = jinja2.FileSystemLoader(searchpath="./templates") templateEnv = jinja2.Environment(loader=templateLoader) if 'sql' in fetch: sqlController = SqlController(animal) valid_sections = sqlController.get_sections(animal, 1) container = "container.html" else: fileLocationManager = FileLocationManager(animal) valid_sections = sorted(os.listdir(fileLocationManager.thumbnail_web)) container = "list_dir.html" if layer is not None: fileLocationManager = FileLocationManager(animal) INPUT = os.path.join(fileLocationManager.thumbnail_web, 'points', layer) valid_sections = sorted(os.listdir(INPUT)) container = "list_points.html" template = templateEnv.get_template(container) lfiles = len(valid_sections) outputText = template.render(animal=animal, valid_sections=valid_sections, lfiles=lfiles, layer=layer) else: template = templateEnv.get_template(container) lfiles = len(valid_sections) outputText = template.render( animal=animal, valid_sections=valid_sections, lfiles=lfiles ) # this is where to put args to the template renderer # to save the results filename = '{}.thumbnails.html'.format(animal) with open(filename, "w") as fh: fh.write(outputText)
def get_atlas_centers(): sqlController = SqlController('Atlas') lauren_person_id = 16 input_type_manual = 1 atlas_centers = sqlController.get_centers_dict( 'Atlas', input_type_id=input_type_manual, person_id=lauren_person_id) return atlas_centers
def __init__(self, stack, parent=None): super(GUISetupMain, self).__init__(parent) # Stack specific info, determined from dropdown menu selection self.stack = stack self.fileLocationManager = FileLocationManager(self.stack) self.sqlController = SqlController() self.sqlController.get_animal_info(self.stack) self.stain = self.sqlController.histology.counterstain self.curr_step = self.sqlController.get_current_step_from_progress_ini( self.stack) # Init UI self.init_ui() # Set buttons functionality self.b_1_4.clicked.connect(lambda: self.click_button(self.b_1_4)) self.b_1_6.clicked.connect(lambda: self.click_button(self.b_1_6)) self.b_exit.clicked.connect(lambda: self.click_button(self.b_exit)) # Update buttons self.update_buttons() # Center the GUI self.center()
def __init__(self, stack, parent=None): super(GUISortedFilenames, self).__init__(parent) self.stack = stack self.fileLocationManager = FileLocationManager(self.stack) self.sqlController = SqlController() self.sqlController.get_animal_info(self.stack) self.valid_sections = self.sqlController.get_valid_sections(stack) self.valid_section_keys = sorted(list(self.valid_sections)) self.curr_section_index = 0 self.curr_section = None self.init_ui() self.b_rotate_left.clicked.connect( lambda: self.click_button(self.b_rotate_left)) self.b_rotate_right.clicked.connect( lambda: self.click_button(self.b_rotate_right)) self.b_flip_vertical.clicked.connect( lambda: self.click_button(self.b_flip_vertical)) self.b_flip_horozontal.clicked.connect( lambda: self.click_button(self.b_flip_horozontal)) self.b_move_left.clicked.connect( lambda: self.click_button(self.b_move_left)) self.b_move_right.clicked.connect( lambda: self.click_button(self.b_move_right)) self.b_quality.currentIndexChanged.connect( lambda: self.click_button(self.b_quality)) self.b_remove.clicked.connect(lambda: self.click_button(self.b_remove)) self.b_help.clicked.connect(lambda: self.click_button(self.b_help)) self.b_done.clicked.connect(lambda: self.click_button(self.b_done)) self.set_curr_section(self.curr_section_index)
def __init__(self, stack, parent=None): super(init_GUI, self).__init__(parent) self.font_h1 = QFont("Arial", 32) self.font_p1 = QFont("Arial", 16) self.stack = stack self.fileLocationManager = FileLocationManager(self.stack) self.sqlController = SqlController() self.sqlController.get_animal_info(self.stack) self.valid_sections = self.sqlController.get_valid_sections(stack) self.valid_section_keys = sorted(list(self.valid_sections)) section_length = len(self.valid_section_keys) self.curr_section_index = section_length // 2 self.prev_section_index = self.curr_section_index self.next_section_index = self.curr_section_index self.curr_section = self.valid_sections[self.valid_section_keys[ self.curr_section_index]]['destination'] self.prev_section = self.getPrevValidSection(self.curr_section_index) self.next_section = self.getNextValidSection(self.curr_section_index) self.curr_T = None self.mode = 'view' # self.mode = 'align' self.transform_type = 'pairwise' # Can toggle to 'anchor' # Increasing this number will brighten the images self.curr_img_multiplier = 1 self.prev_img_multiplier = 1 self.initUI()
def padder(animal, bgcolor): fileLocationManager = FileLocationManager(animal) sqlController = SqlController() sqlController.get_animal_info(animal) INPUT = os.path.join(fileLocationManager.prep, 'thumbnail_masked') OUTPUT = '/net/birdstore/Active_Atlas_Data/data_root/brains_info/masks/{}/prealigned'.format(animal) files = sorted(os.listdir(INPUT)) width = sqlController.scan_run.width height = sqlController.scan_run.height max_width = int(width * SCALING_FACTOR) max_height = int(height * SCALING_FACTOR) for i, file in enumerate(tqdm(files)): infile = os.path.join(INPUT, file) try: img = io.imread(infile) except: print('Could not open', infile) continue fixed = place_image(img, file, max_width, max_height, bgcolor) outpath = os.path.join(OUTPUT, file) cv2.imwrite(outpath, fixed.astype('uint8')) print('Finished')
def update_tifs(animal, channel): """ Args: animal: the prep id of the animal channel: the channel of the stack to process njobs: number of jobs for parallel computing Returns: nothing """ fileLocationManager = FileLocationManager(animal) sqlController = SqlController(animal) tifs = sqlController.get_distinct_section_filenames(animal, channel) INPUT = os.path.join(fileLocationManager.prep, 'CH1', 'full') # Update TIFs' size try: os.listdir(INPUT) except OSError as e: print(e) sys.exit() for i, tif in enumerate(tqdm(tifs)): print(tif.file_name) input_path = os.path.join(INPUT, str(i).zfill(3) + '.tif') if os.path.exists(input_path): print(input_path) tif.file_size = os.path.getsize(input_path) sqlController.update_row(tif)
def make_web_thumbnails(animal): """ This was originally getting the thumbnails from the preps/thumbnail dir but they aren't usuable. The ones in the preps/CH1/thumbnail_aligned are much better But we need to test if there ane aligned files, if not use the cleaned ones. Thumbnails are always created from CH1 Args: animal: the prep id of the animal njobs: number of jobs for parallel computing Returns: nothing """ fileLocationManager = FileLocationManager(animal) sqlController = SqlController(animal) INPUT = '/home/eodonnell/DK39/cshl/jpg' OUTPUT = os.path.join(fileLocationManager.root, animal, 'cshl/jpg') tifs = sqlController.get_sections(animal, 1) for i, tif in enumerate(tqdm(tifs)): input_path = os.path.join(INPUT, os.path.splitext(tif.file_name)[0] + '.jpg') output_path = os.path.join(OUTPUT, str(i).zfill(3) + '.jpg') if not os.path.exists(input_path): continue if os.path.exists(output_path): continue os.makedirs(os.path.dirname(output_path), exist_ok=True) cmd = "convert {} {}".format(input_path, output_path) subprocess.run(cmd, shell=True)
def __init__(self, stack, parent=None): super(init_GUI, self).__init__(parent) self.font_h1 = QFont("Arial", 32) self.font_p1 = QFont("Arial", 16) self.queued_transformations = [] # create a dataManager object self.sqlController = SqlController() self.stack = stack self.fileLocationManager = FileLocationManager(self.stack) self.sqlController.get_animal_info(self.stack) self.valid_sections = self.sqlController.get_valid_sections(stack) self.valid_section_keys = sorted(list(self.valid_sections)) section_length = len(self.valid_section_keys) self.curr_section_index = section_length // 2 self.prev_section_index = self.curr_section_index self.next_section_index = self.curr_section_index self.curr_section = self.valid_sections[self.valid_section_keys[ self.curr_section_index]]['destination'] self.prev_section = self.getPrevValidSection(self.curr_section_index) self.next_section = self.getNextValidSection(self.curr_section_index) self.initUI()
def get_db_structure_infos(): sqlController = SqlController('MD589') db_structures = sqlController.get_structures_dict() structures = {} for structure, v in db_structures.items(): if '_' in structure: structure = structure[0:-2] structures[structure] = v return structures
def __init__(self, stack, parent = None): super(init_GUI, self).__init__(parent) self.font1 = QFont("Arial",16) self.font2 = QFont("Arial",12) # Stack specific info, determined from dropdown menu selection self.stack = stack self.curr_step = "" self.sqlController = SqlController() self.sqlController.get_animal_info(self.stack) self.initUI()
def __init__(self, parent=None): super(init_GUI, self).__init__(parent) self.font1 = QFont("Arial", 16) self.font2 = QFont("Arial", 12) self.stack = stack self.fileLocationManager = FileLocationManager(self.stack) self.sqlController = SqlController() self.sqlController.get_animal_info(self.stack) self.stain = self.sqlController.histology.counterstain self.curr_step = self.sqlController.get_current_step_from_progress_ini( self.stack) self.initUI()
def create_points(animal, layer, url_id, create): fileLocationManager = FileLocationManager(animal) sqlController = SqlController(animal) # Get src points data df = sqlController.get_point_dataframe(url_id) df = df[df['Layer'] == layer] df.sort_values(by=['Section', 'X', 'Y'], inplace=True) if create: records = df[['X', 'Y', 'Section']].to_records(index=False) coordinates = list(records) width = sqlController.scan_run.width height = sqlController.scan_run.height sections = sqlController.get_section_count(animal) layer = str(layer).replace(' ', '_') OUTPUT_DIR = os.path.join(fileLocationManager.neuroglancer_data, layer) if os.path.exists(OUTPUT_DIR): shutil.rmtree(OUTPUT_DIR) os.makedirs(OUTPUT_DIR, exist_ok=True) info = os.path.join(DATA_PATH, 'atlas_data', 'points', 'info') outfile = os.path.join(OUTPUT_DIR, 'info') with open(info, 'r+') as rf: data = json.load(rf) data['upper_bound'] = [width, height, sections] # <--- add `id` value. rf.seek(0) # <--- should reset file position to the beginning. with open(outfile, 'w') as wf: json.dump(data, wf, indent=4) spatial_dir = os.path.join(OUTPUT_DIR, 'spatial0') os.makedirs(spatial_dir) total_count = len( coordinates) # coordinates is a list of tuples (x,y,z) with open(os.path.join(spatial_dir, '0_0_0.gz'), 'wb') as unzippedfile: buf = struct.pack('<Q', total_count) pt_buf = b''.join( struct.pack('<3f', x, y, z) for (x, y, z) in coordinates) buf += pt_buf id_buf = struct.pack('<%sQ' % len(coordinates), *range(len(coordinates))) buf += id_buf bufout = gzip.compress(buf) unzippedfile.write(bufout) else: print(df['Layer'].unique()) print(df.head(25))
def get_atlas_centers(atlas_box_size=(1000, 1000, 300), atlas_box_scales=(10, 10, 20), atlas_raw_scale=10): atlas_box_scales = np.array(atlas_box_scales) atlas_box_size = np.array(atlas_box_size) atlas_box_center = atlas_box_size / 2 sqlController = SqlController('Atlas') atlas_centers = sqlController.get_centers_dict('Atlas', input_type_id=1, person_id=16) for structure, center in atlas_centers.items(): center = (atlas_box_center + np.array(center) * atlas_raw_scale / atlas_box_scales) * atlas_box_scales atlas_centers[structure] = center return atlas_centers
def test_dir(animal, dir, downsample=True, same_size=False): error = "" #thumbnail resolution ntb is 10400 and min size of DK52 is 16074 #thumbnail resolution thion is 14464 and min size for MD585 is 21954 # so 10000 is a good min size # min size on NTB is 8.8K starting_size = 4000 min_size = starting_size * SCALING_FACTOR * 1000 if downsample: min_size = starting_size sqlController = SqlController(animal) section_count = sqlController.get_section_count(animal) try: files = sorted(os.listdir(dir)) except: return f'{dir} does not exist' if section_count == 0: section_count = len(files) widths = set() heights = set() for f in files: filepath = os.path.join(dir, f) width, height = get_image_size(filepath) widths.add(int(width)) heights.add(int(height)) size = os.path.getsize(filepath) if size < min_size: error += f"{size} is less than min: {min_size} {filepath} \n" # picked 100 as an arbitrary number. the min file count is usually around 380 or so if len(files) > 100: min_width = min(widths) max_width = max(widths) min_height = min(heights) max_height = max(heights) else: min_width = 0 max_width = 0 min_height = 0 max_height = 0 if section_count != len(files): error += f"Number of files in {dir} is incorrect.\n" if min_width != max_width and min_width > 0 and same_size: error += f"Widths are not of equal size, min is {min_width} and max is {max_width}.\n" if min_height != max_height and min_height > 0 and same_size: error += f"Heights are not of equal size, min is {min_height} and max is {max_height}.\n" return error
def get_atlas_centers(atlas_box_size=(1000, 1000, 300), atlas_box_scales=(10, 10, 20), atlas_raw_scale=10): atlas_box_scales = np.array(atlas_box_scales) atlas_box_size = np.array(atlas_box_size) atlas_box_center = atlas_box_size / 2 sqlController = SqlController('Atlas') atlas_centers = sqlController.get_centers_dict('Atlas') for structure, origin in atlas_centers.items(): # transform into the atlas box coordinates that neuroglancer assumes center = atlas_box_center + np.array( origin) * atlas_raw_scale / atlas_box_scales atlas_centers[structure] = center return atlas_centers
def convert_cropbox_to_arr_xywh_1um(data, in_fmt, in_resol, stack): #print('data', data, 'in_fmt', in_fmt) sqlController = SqlController(stack) if isinstance(data, dict): data['rostral_limit'] = float(data['rostral_limit']) data['caudal_limit'] = float(data['caudal_limit']) data['dorsal_limit'] = float(data['dorsal_limit']) data['ventral_limit'] = float(data['ventral_limit']) arr_xywh = np.array([ data['rostral_limit'], data['dorsal_limit'], data['caudal_limit'] - data['rostral_limit'] + 1, data['ventral_limit'] - data['dorsal_limit'] + 1 ]) # Since this does not check for wrt, the user needs to make sure the cropbox is relative to the input prep (i.e. the wrt attribute is the same as input prep) elif isinstance(data, str): if in_fmt == 'str_xywh': d = re.sub('[!@#$cropwarp\]\[\']', '', data) l = d.split(',') a = [float(v) for v in l] arr_xywh = np.array(a) elif in_fmt == 'str_xxyy': #####UPGRADE from 2 to 3arr_xxyy = np.array(map(np.round, map(eval, data.split(',')))) arr_xxyy = np.array( list(map(np.round, list(map(eval, data.split(',')))))) arr_xywh = np.array([ arr_xxyy[0], arr_xxyy[2], arr_xxyy[1] - arr_xxyy[0] + 1, arr_xxyy[3] - arr_xxyy[2] + 1 ]) else: raise else: if in_fmt == 'arr_xywh': arr_xywh = data #arr_xywh = np.array(data) elif in_fmt == 'arr_xxyy': arr_xywh = np.array([ data[0], data[2], data[1] - data[0] + 1, data[3] - data[2] + 1 ]) else: print(in_fmt, data) raise string_to_um_in_resolution = sqlController.convert_resolution_string_to_um( stack, in_resol) arr_xywh_1um = arr_xywh * string_to_um_in_resolution print('arr_xywh_1um', arr_xywh_1um) return arr_xywh_1um
def convert_cropbox_from_arr_xywh_1um(data, out_fmt, out_resol, stack): sqlController = SqlController(stack) string_to_um_out_resolution = sqlController.convert_resolution_string_to_um( stack, out_resol) data = data / string_to_um_out_resolution if out_fmt == 'str_xywh': return ','.join(map(str, data)) elif out_fmt == 'dict': raise Exception("too lazy to implement") elif out_fmt == 'arr_xywh': return data elif out_fmt == 'arr_xxyy': return np.array( [data[0], data[0] + data[2] - 1, data[1], data[1] + data[3] - 1]) else: raise
def make_tif(animal, tif_id, file_id, testing=False): fileLocationManager = FileLocationManager(animal) sqlController = SqlController(animal) INPUT = fileLocationManager.czi OUTPUT = fileLocationManager.tif start = time.time() tif = sqlController.get_tif(tif_id) slide = sqlController.get_slide(tif.slide_id) czi_file = os.path.join(INPUT, slide.file_name) section = sqlController.get_section(file_id) tif_file = os.path.join(OUTPUT, section.file_name) if not os.path.exists(czi_file) and not testing: return 0 if os.path.exists(tif_file): return 1 if testing: command = ['touch', tif_file] else: command = ['/usr/local/share/bftools/bfconvert', '-bigtiff', '-separate', '-series', str(tif.scene_index), '-channel', str(tif.channel-1), '-nooverwrite', czi_file, tif_file] run(command) end = time.time() if os.path.exists(tif_file): tif.file_size = os.path.getsize(tif_file) tif.processing_duration = end - start sqlController.update_row(tif) return 1
def make_web_thumbnails(animal): """ This was originally getting the thumbnails from the preps/thumbnail dir but they aren't usuable. The ones in the preps/CH1/thumbnail_aligned are much better But we need to test if there ane aligned files, if not use the cleaned ones. Thumbnails are always created from CH1 Args: animal: the prep id of the animal njobs: number of jobs for parallel computing Returns: nothing """ channel_dir = 'CH1' fileLocationManager = FileLocationManager(animal) sqlController = SqlController(animal) INPUT = os.path.join(fileLocationManager.prep, channel_dir, 'thumbnail_aligned') len_files = len(os.listdir(INPUT)) if len_files < 10: INPUT = os.path.join(fileLocationManager.prep, channel_dir, 'thumbnail_cleaned') ##### Check if files in dir are valid error = test_dir(animal, INPUT, downsample=True, same_size=True) if len(error) > 0: print(error) sys.exit() OUTPUT = fileLocationManager.thumbnail_web os.makedirs(OUTPUT, exist_ok=True) tifs = sqlController.get_sections(animal, 1) for i, tif in enumerate(tqdm(tifs)): input_path = os.path.join(INPUT, str(i).zfill(3) + '.tif') output_path = os.path.join(OUTPUT, os.path.splitext(tif.file_name)[0] + '.png') if not os.path.exists(input_path): continue if os.path.exists(output_path): continue original = Image.open(input_path) original.save(output_path, format="png")
def get_atlas_centers( atlas_box_size=(1000, 1000, 300), atlas_box_scales=(10, 10, 20), atlas_raw_scale=10 ): atlas_box_scales = np.array(atlas_box_scales) atlas_box_size = np.array(atlas_box_size) atlas_box_center = atlas_box_size / 2 sqlController = SqlController('Atlas') # person is lauren, input_type is manual atlas_centers = sqlController.get_centers_dict('Atlas', input_type_id=1, person_id=16) for structure, center in atlas_centers.items(): # transform into the atlas box coordinates that neuroglancer assumes center = atlas_box_center + np.array(center) * atlas_raw_scale / atlas_box_scales atlas_centers[structure] = center return atlas_centers
def __init__(self, parent=None): super(init_GUI, self).__init__(parent) self.font1 = QFont("Arial", 16) self.font2 = QFont("Arial", 12) # Stack specific info, determined from dropdown menu selection self.stack = "" self.stain = "" self.detector_id = "" self.img_version_1 = "" self.img_version_2 = "" self.curr_step = "" self.initial_bottom_text = "Push `Finished` to exit the GUI" self.sqlController = SqlController() self.stack_metadata = self.sqlController.generate_stack_metadata() self.initUI()
def main(): parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description='GUI for sorting filenames') parser.add_argument("stack", type=str, help="stack name") args = parser.parse_args() stack = args.stack sqlController = SqlController() sections = list(sqlController.get_valid_sections(stack)) if len(sections) > 0: global app app = QApplication(sys.argv) global ex ex = init_GUI(stack) # Run GUI as usual ex.show() sys.exit(app.exec_()) else: print('There are no sections to work with.')
def make_low_resolution(animal, channel): """ Args: takes the full resolution tifs and downsamples them. animal: the prep id of the animal channel: the channel of the stack to process Returns: list of commands """ sqlController = SqlController(animal) if 'thion' in sqlController.histology.counterstain: sqlController.set_task(animal, CREATE_CHANNEL_2_THUMBNAILS) sqlController.set_task(animal, CREATE_CHANNEL_3_THUMBNAILS) fileLocationManager = FileLocationManager(animal) commands = [] INPUT = os.path.join(fileLocationManager.prep, f'CH{channel}', 'full') ##### Check if files in dir are valid error = test_dir(animal, INPUT, downsample=False, same_size=False) if len(error) > 0: print(error) sys.exit() OUTPUT = os.path.join(fileLocationManager.prep, f'CH{channel}', 'thumbnail') os.makedirs(OUTPUT, exist_ok=True) tifs = sorted(os.listdir(INPUT)) for tif in tifs: input_path = os.path.join(INPUT, tif) output_path = os.path.join(OUTPUT, tif) if os.path.exists(output_path): continue cmd = [ 'convert', input_path, '-resize', '3.125%', '-compress', 'lzw', output_path ] commands.append(cmd) with Pool(4) as p: p.map(workernoshell, commands)
def test_tif(animal, channel): sqlController = SqlController(animal) checks = ['tif'] fileLocationManager = FileLocationManager(animal) # tifs for name, dir in zip(checks, [fileLocationManager.tif]): db_files = sqlController.get_distinct_section_filenames( animal, channel) valid_file_length = db_files.count() dir_exists, lfiles, badsize = directory_filled(dir, channel) if not dir_exists: print("{} does not exist.".format(dir)) missings = find_missing(dir, db_files) if len(missings) > 0: print("Missing files:") count = 1 for missing in missings: print(count, missing) count += 1
def create_thumbnails(stack): ## Downsample and normalize images in the "_raw" folder raw_folder = os.path.join(ROOT_DIR, stack, 'tif') sections = SqlController.get_valid_sections(stack) for img_name in os.listdir(raw_folder): input_fp = os.path.join(raw_folder, img_name) output_fp = os.path.join(ROOT_DIR, stack, 'preps', 'thumbnail', img_name) # Create thumbnails execute_command("convert \"" + input_fp + "\" -resize 3.125% -auto-level -normalize \ -compress lzw \"" + output_fp + "\"")
def fix_tifs(animal, channel): sqlController = SqlController(animal) fileLocationManager = FileLocationManager(animal) dir = fileLocationManager.tif db_files = sqlController.get_sections(animal, channel) source_files = [] source_keys = [] for tif in db_files: source_files.append(tif.file_name) source_keys.append(tif.id) files = os.listdir(dir) files = [file for file in files if 'C{}.tif'.format(channel) in file] missing_files = list(set(source_files) - set(files)) for i, missing in enumerate(missing_files): #pass file_id = source_keys[source_files.index(missing)] section = sqlController.get_section(file_id) print(i, missing, file_id, section.id, section.file_name) make_tif(animal, section.tif_id, file_id, testing=False)
def create_atlas(level): if level == 'high': MESH_PATH = os.path.join(DATA_PATH, 'atlas_data', atlas_name, 'mesh', '0.9') else: MESH_PATH = os.path.join(DATA_PATH, 'atlas_data', atlas_name, 'mesh', '0.1') sqlController = SqlController('MD589') structures = sqlController.get_structures_list() acts = [] for structure in tqdm(structures): filepath = os.path.join(MESH_PATH, f'{structure}.stl') if os.path.exists(filepath): act = load(filepath) color = sqlController.get_structure_color_rgb(structure) act.color(color) acts.append(act) show(acts)
def __init__(self, stack, parent=None): super(GUICropBrainStem, self).__init__(parent) self.stack = stack self.fileLocationManager = FileLocationManager(self.stack) self.sqlController = SqlController() self.sqlController.get_animal_info(self.stack) self.valid_sections = self.sqlController.get_valid_sections(stack) self.valid_section_keys = sorted(list(self.valid_sections)) self.curr_section_index = 0 self.curr_section = None self.active_selection = '' self.img_width = 2001 self.img_height = 1001 self.rostral = -1 self.caudal = -1 self.ventral = -1 self.dorsal = -1 self.first_slice = -1 self.last_slice = -1 self.init_ui() self.b_rostral.clicked.connect( lambda: self.click_button(self.b_rostral)) self.b_caudal.clicked.connect(lambda: self.click_button(self.b_caudal)) self.b_dorsal.clicked.connect(lambda: self.click_button(self.b_dorsal)) self.b_ventral.clicked.connect( lambda: self.click_button(self.b_ventral)) self.b_first_slice.clicked.connect( lambda: self.click_button(self.b_first_slice)) self.b_last_slice.clicked.connect( lambda: self.click_button(self.b_last_slice)) self.b_done.clicked.connect(lambda: self.click_button(self.b_done)) self.viewer.click.connect(self.click_photo)