def wipe_region(z, gap=0.08, speed=None): if DUMMY_CONNECTIONS: return move_to(V2((-1, 0)) + LOCAL_O * (-1 if INVERT_COORDINATES else 1)) z_rotary.move_abs(mm2rotdata(z), await_reply=True) if CONNECT_KEITHLEY: kh.set_output_on() for i in range(int(REGION_SIZE.y / (2 * gap)) + 1): if i > 0: move_to( V2((-1, gap * 2 * i)) + LOCAL_O * (-1 if INVERT_COORDINATES else 1), speed) move_to( V2((REGION_SIZE.x + 1, gap * 2 * i)) + LOCAL_O * (-1 if INVERT_COORDINATES else 1), speed) move_to( V2((REGION_SIZE.x + 1, gap * (2 * i + 1))) + LOCAL_O * (-1 if INVERT_COORDINATES else 1), speed) move_to( V2((-1, gap * (2 * i + 1))) + LOCAL_O * (-1 if INVERT_COORDINATES else 1), speed) if CONNECT_KEITHLEY: kh.set_output_off()
def wipe_region(z, speed=None): move_to(V2((-1, 0)) + LOCAL_O * (-1 if INVERT else 1)) z_rotary.move_abs(mm2rotdata(z), await_reply=True) if CONNECT_KEITHLEY: keith.set_output_on() for i in range(int(REGION_SIZE.y / (2 * WIPE_GAP)) + 1): if i > 0: move_to( V2((-1, WIPE_GAP * 2 * i)) + LOCAL_O * (-1 if INVERT else 1), speed) move_to( V2((REGION_SIZE.x + 1, WIPE_GAP * 2 * i)) + LOCAL_O * (-1 if INVERT else 1), speed) move_to( V2((REGION_SIZE.x + 1, WIPE_GAP * (2 * i + 1))) + LOCAL_O * (-1 if INVERT else 1), speed) move_to( V2((-1, WIPE_GAP * (2 * i + 1))) + LOCAL_O * (-1 if INVERT else 1), speed) if CONNECT_KEITHLEY: keith.set_output_off()
def write_part_circle(center, radius, start_deg, end_deg, speed, log_command=False): if log_command: print("PCIRCLE: \tc%s, r%d, (%dº–%dº), %d mm/s" % (center, radius, start, end, speed)) invert_factor = 1 if INVERT else -1 f = ground_speed / (1000 * radius) # (mstep/s) / (1000 * mstep) = 1 / ms T = 1000 * 2 * math.pi * radius / speed # (ms) start_pos = center + V2((radius, start_deg), polar=True) move_to(start_pos) start_time = time.perf_counter() for t in range(start_deg * T / 360 + DELTA_T, end_deg * T / 360, DELTA_T): delta = radius * (V2(f * t) - V2(f * (t - 1))) velocity = 1000 * delta / (DELTA_T * 9.375 ) # don't really like this... data_speed = linspeed2lindata(velocity.magnitude) x_linear.move_vel(invert_factor * linspeed2lindata(velocity.x)) y_linear.move_vel(invert_factor * linspeed2lindata(velocity.y)) while time.perf_counter() - start_time < t: time.sleep(0.001) x_linear.stop() y_linear.stop()
def outline_region(z, speed=None): if DUMMY_CONNECTIONS: return move_to(V2((-0.1, -0.1)) + LOCAL_O * (-1 if INVERT_COORDINATES else 1)) z_rotary.move_abs(mm2rotdata(z), await_reply=True) if CONNECT_KEITHLEY: kh.set_output_on() move_to( V2((-0.1, REGION_SIZE.y + 0.1)) + LOCAL_O * (-1 if INVERT_COORDINATES else 1), speed) move_to( REGION_SIZE + V2( (0.1, 0.1)) + LOCAL_O * (-1 if INVERT_COORDINATES else 1), speed) move_to( V2((REGION_SIZE.x + 0.1, -0.1)) + LOCAL_O * (-1 if INVERT_COORDINATES else 1), speed) move_to( V2((-0.1, -0.1)) + LOCAL_O * (-1 if INVERT_COORDINATES else 1), speed) if CONNECT_KEITHLEY: kh.set_output_off()
def write_parallel_lines_horizontal_region_wide(z, speeds, gap, inter_speed_gap_factor=0.2): if DUMMY_CONNECTIONS: return for i in range(len(speeds)): start = V2((-1, i * (2 + inter_speed_gap_factor) * gap)) end = V2((REGION_SIZE.x + 1, i * (2 + inter_speed_gap_factor) * gap)) speed = speeds[i] print(speed) if i == 0: move_to(start) z_rotary.move_abs(mm2rotdata(z), await_reply=True) write_line(start, end, speed) write_line(end + V2((0, gap)), start + V2((0, gap)), speed) if not MOVE_MAPPING: print(LOCAL_O + V2((0, (len(speeds) * (2 + inter_speed_gap_factor) + 1) * gap)))
def write_parallel_lines_horizontal_continuous(z, start, end, gap, speed): if DUMMY_CONNECTIONS: return shift = V2((0, gap)) move_to(start) z_rotary.move_abs(mm2rotdata(z), await_reply=True) if CONNECT_KEITHLEY: kh.set_output_on() num_lines = int(abs((end - start).y) / float(gap)) for i in range(0, num_lines, 2): if i > 0: move_to(start + shift * i, speed) move_to(V2((end.x, start.y)) + shift * i, speed) move_to(V2((end.x, start.y)) + shift * (i + 1), speed) move_to(start + shift * (i + 1), speed) if CONNECT_KEITHLEY: kh.set_output_off() # PRINT OUT WHERE TO SET LOCAL_O NEXT if not MOVE_MAPPING: print(LOCAL_O + V2((0, (num_lines + 1) * gap))) print("OR") print(LOCAL_O + V2((abs((end - start).x) + gap, 0)))
def define_operating_constants(): """ ZABER CONTROL """ global GLOBAL_O, TR, LOCAL_O, REGION_SIZE, \ STAGES_PORT, MM_PER_MSTEP, DATA_PER_MM, DATA_PER_MM_SPEED, DATA_PER_DEG, DATA_PER_DEG_SPEED, DEG_PER_MM, \ DELTA_T, DEFAULT_HOME_SPEED, DEFAULT_ROT_SPEED, LIN_STAGE_ACCELERATION, ROT_STAGE_ACCELERATION, \ ROTARY_MIN_ANGLE, ROTARY_MAX_ANGLE, B_EMPIR, INVERT_COORDINATES GLOBAL_O = V2((0, 0)) # ORIGIN = LASER FOCUSED ON BOTTOM LEFT CORNER TR = V2((0, 0)) # ...TOP RIGHT CORNER LOCAL_O = V2((0, 0)) REGION_SIZE = GLOBAL_O - TR STAGES_PORT = "COM3" # serial port to Zaber stages DATA_PER_MM = 1000 / 0.047625 # conversion from mm to data DATA_PER_MM_SPEED = 2240 # conversion from mm/s to data (speed) DATA_PER_DEG = 12800 / 3 # conversion from degrees to data DATA_PER_DEG_SPEED = 6990 # conversion from deg/s to data (speed) DEG_PER_MM = 9.2597 # (deg/mm) empirical conversion, mm to degrees DELTA_T = 24 # (ms) SET LOWER WHEN WRITING FASTER DEFAULT_HOME_SPEED = 5 # (mm/s) DEFAULT_ROT_SPEED = 15 # (deg/s) LIN_STAGE_ACCELERATION = 2000 # (data/s^2) ? # BE CAREFUL ABOUT INCREASING THIS VALUE! Cf. EXTREMELY IMPORTANT # NOTES #3 in README.rm. ROT_STAGE_ACCELERATION = 40 # (data/s^2) ? ROTARY_MIN_ANGLE = 0.0 # (deg) min position of rotary stage = upper bound on laser height ROTARY_MAX_ANGLE = 113.5 # (deg) max postition of rotary stage = min. allowable laser height B_EMPIR = 1414.9692 # (deg) position of rotary stage at 0 mm # True if writing to a sample to be viewed in microscope (since microscope inverts image) INVERT_COORDINATES = True
def write_parallel_lines_horizontal_continuous(z, start, end, gap, speed, log_command=False): shift = V2((0, gap)) move_to(start) z_rotary.move_abs(mm2rotdata(z), await_reply=True) if CONNECT_KEITHLEY: keith.set_output_on() num_lines = int(abs((end - start).y) / float(gap)) for i in range(0, num_lines, 2): if i > 0: move_to(start + shift * i, speed) move_to(V2((end.x, start.y)) + shift * i, speed) move_to(V2((end.x, start.y)) + shift * (i + 1), speed) move_to(start + shift * (i + 1), speed) if CONNECT_KEITHLEY: keith.set_output_off() # PRINT OUT WHERE TO SET LOCAL_O NEXT print(LOCAL_O + V2((0, (num_lines + 1) * gap))) print("OR") print(LOCAL_O + V2((abs((end - start).x) + gap, 0))) # SHOULD DO THE SAME THING IN THEORY... HAVEN'T QUITE TESTED... """
def __init__(self, sample_name): self.path_prefix = "/Users/harperwallace/Dropbox/Reczek Lab/COMMANDS/gui/path_" self.sample_name = sample_name self.TR = V2((0, 0)) self.GLOBAL_O = V2((0, 0)) self.REGION_SIZE = V2((0, 0)) self.local_o = V2((0, 0)) self.curr_pos = V3( (0, 0, 0)) # should probably adjust so initial z is home height self.reformatted_file_text = ""
def __init__(self, sample_name, connect_keithley, default_speed): self.connect_keithley = connect_keithley self.default_speed = default_speed self.sample_name = sample_name self.TR = V2((0, 0)) self.GLOBAL_O = V2((0, 0)) self.REGION_SIZE = V2((0, 0)) self.local_o = V2((0, 0)) self.curr_pos = V3( (0, 0, 0)) # should probably adjust so initial z is home height self.reformatted_file_text = "" self.continue_to_run = False
def current_position(): if CONNECT_ROTARY: return V3((lindata2mm(x_linear.get_position()), lindata2mm(y_linear.get_position()), rotdata2mm(z_rotary.get_position()))) return V2((lindata2mm(x_linear.get_position()), lindata2mm(y_linear.get_position())))
def setup_stages(): global serial_conn, x_linear, y_linear, z_rotary if DUMMY_CONNECTIONS: return serial_conn = BinarySerial(STAGES_PORT, timeout=None) if CONNECT_ROTARY: z_rotary = BinaryDevice(serial_conn, 1) z_rotary.set_home_speed(degspeed2rotdata(DEFAULT_ROT_SPEED)) z_rotary.set_target_speed(degspeed2rotdata(DEFAULT_ROT_SPEED)) z_rotary.set_acceleration(ROT_STAGE_ACCELERATION) z_rotary.set_min_position(deg2rotdata(ROTARY_MIN_ANGLE)) z_rotary.set_max_position(deg2rotdata(ROTARY_MAX_ANGLE)) x_linear = BinaryDevice(serial_conn, 2) y_linear = BinaryDevice(serial_conn, 3) x_linear.set_home_speed(linspeed2lindata(DEFAULT_HOME_SPEED)) y_linear.set_home_speed(linspeed2lindata(DEFAULT_HOME_SPEED)) x_linear.set_target_speed(linspeed2lindata(DEFAULT_HOME_SPEED)) y_linear.set_target_speed(linspeed2lindata(DEFAULT_HOME_SPEED)) x_linear.set_acceleration(LIN_STAGE_ACCELERATION) y_linear.set_acceleration(LIN_STAGE_ACCELERATION) x_linear.disable_manual_move_tracking() y_linear.disable_manual_move_tracking() move_to(V2((0.1, 0.1)), is_local=False) home_all()
def write_part_circle(center, radius, start_deg, end_deg, speed, log_command=False): if log_command: print("PCIRCLE: \tc%s, r%d, (%dº–%dº), %d mm/s" % (center, radius, start, end, speed)) invert_factor = 1 if INVERT else -1 f = speed / (1000 * radius ) # circle frequency; (mm/s) / (1000 * mm) = 1 / ms T = 1000 * 2 * math.pi * radius / speed # time it takes to do a whole circle (ms) start_pos = center + V2( start_deg) * radius # no need for invert_factor--handled in move_to move_to(start_pos) x_linear.disable_auto_reply() y_linear.disable_auto_reply() start_time = time.perf_counter() for t in range( int(start_deg * T / 360) + DELTA_T, int(end_deg * T / 360), DELTA_T): delta = (V2(180 / math.pi * f * t) - V2(180 / math.pi * f * (t - DELTA_T))) * radius velocity = delta.unit * speed # await_reply set to None here because move_vel can't be interrupted by disable_auto_reply # (will get busy error response = [_, 255, 255]); None value just skips setting auto_reply status x_linear.move_vel(invert_factor * linspeed2lindata(velocity.x), await_reply=None) y_linear.move_vel(invert_factor * linspeed2lindata(velocity.y), await_reply=None) while time.perf_counter() - start_time < 0.001 * t: time.sleep(0.001) x_linear.stop() y_linear.stop()
def write_part_circle(center, radius, start_deg, end_deg, speed): if DUMMY_CONNECTIONS: return invert_factor = 1 if INVERT_COORDINATES else -1 # f = circle frequency; (mm/s) / (1000 * mm) = 1 / ms f = speed / (1000 * radius) # T = period = time it takes to do a whole circle (ms) T = 1000 * 2 * math.pi * radius / speed # no need for invert_factor--handled in move_to start_pos = center + V2(start_deg) * radius move_to(start_pos) x_linear.disable_auto_reply() y_linear.disable_auto_reply() start_time = time.perf_counter() for t in range( int(start_deg * T / 360) + DELTA_T, int(end_deg * T / 360), DELTA_T): delta = (V2(180 / math.pi * f * t) - V2(180 / math.pi * f * (t - DELTA_T))) * radius velocity = delta.unit * speed # await_reply set to None here because move_vel can't be # interrupted by disable_auto_reply (will get busy error # response = [_, 255, 255]); None value just skips setting # auto_reply status x_linear.move_vel(invert_factor * linspeed2lindata(velocity.x), await_reply=None) y_linear.move_vel(invert_factor * linspeed2lindata(velocity.y), await_reply=None) while time.perf_counter() - start_time < 0.001 * t: time.sleep(0.001) x_linear.stop() y_linear.stop()
def write_parallel_lines_horizontal_const_height(z, x_width, speeds, gap, inter_speed_gap_factor=0.2): for i in range(len(speeds)): start = V2((0, i * (2 + inter_speed_gap_factor) * gap)) end = V2((x_width, i * (2 + inter_speed_gap_factor) * gap)) speed = speeds[i] print(speed) if i == 0: move_to(start) z_rotary.move_abs(mm2rotdata(z), await_reply=True) write_line(start, end, speed) write_line(end + V2((0, gap)), start + V2((0, gap)), speed) print(LOCAL_O + V2((0, (len(speeds) * (2 + inter_speed_gap_factor) + 1) * gap))) print("OR") print(LOCAL_O + V2((x_width + gap, 0)))
def __init__(self, path_prefix, sample_name, connect_keithley, default_speed): self.path_prefix = path_prefix self.sample_name = sample_name # If True, assumes that the beam shutter will close for moves # between (and hence won't render those moves, but will # consider and the paths between moves anyway, as gray, # dashed lines) self.connect_keithley = connect_keithley self.default_speed = default_speed self.TR = V2((0, 0)) self.GLOBAL_O = V2((0, 0)) self.REGION_SIZE = V2((0, 0)) self.local_o = V2((0, 0)) self.curr_pos = V2((0, 0)) self.new_file_text = "" self.new_cmds_array = [] self.continue_to_run = False
def write_parallel_angled_lines(start, length, angle, gap, speed, num_lines, log_command=False): write_parallel_lines(start, start + V2((length, angle), polar=True), gap, speed, num_lines, log_command=log_command)
def write_parallel_lines_vertical_region_tall(z, speeds, gap, inter_speed_gap_factor=0.2): z_rotary.move_abs(mm2rotdata(z), await_reply=True) for i in range(len(speeds)): start = V2((i * (2 + inter_speed_gap_factor) * gap, -1)) end = V2((i * (2 + inter_speed_gap_factor) * gap, REGION_SIZE.y + 1)) speed = speeds[i] print(speed) if i == 0: move_to(start) z_rotary.move_abs(mm2rotdata(z), await_reply=True) write_line(start, end, speed) write_line(end + V2((gap, 0)), start + V2((gap, 0)), speed) print(LOCAL_O + V2(((len(speeds) * (2 + inter_speed_gap_factor) + 1) * gap, 0)))
def write_mapped_commands(mh): global GLOBAL_O, TR, REGION_SIZE, LOCAL_O LOCAL_O = V2((0, 0)) GLOBAL_O = mh.GLOBAL_O TR = mh.TR REGION_SIZE = GLOBAL_O - TR for cmd_args in mh.new_cmds_array: if cmd_args[0] == "write_parallel_lines_vertical_continuous": write_parallel_lines_vertical_continuous(*cmd_args[1:]) elif cmd_args[0] == "write_parallel_lines_horizontal_continuous": write_parallel_lines_horizontal_continuous(*cmd_args[1:]) elif cmd_args[0] == "write_parallel_lines_vertical_region_tall": write_parallel_lines_vertical_region_tall(*cmd_args[1:]) elif cmd_args[0] == "write_parallel_lines_horizontal_region_wide": write_parallel_lines_horizontal_region_wide(*cmd_args[1:]) elif cmd_args[0] == "write_parallel_lines_horizontal_const_height": write_parallel_lines_horizontal_const_height(*cmd_args[1:]) elif cmd_args[0] == "write_parallel_lines_gap": write_parallel_lines_gap(*cmd_args[1:]) elif cmd_args[0] == "write_parallel_lines_delta_s": write_parallel_lines_delta_s(*cmd_args[1:]) elif cmd_args[0] == "write_line": write_line(*cmd_args[1:]) elif cmd_args[0] == "write_circle": write_circle(*cmd_args[1:]) elif cmd_args[0] == "write_part_circle": write_part_circle(*cmd_args[1:]) elif cmd_args[0] == "outline_region": outline_region(*cmd_args[1:]) elif cmd_args[0] == "wipe_region": wipe_region(*cmd_args[1:]) elif cmd_args[0] == "move_to": move_to(*cmd_args[1:])
def draw_map(self): fix, ax = plt.subplots(nrows=1, ncols=1, figsize=(5.5, 6)) plt.subplots_adjust(bottom=0.2) axbcancel = plt.axes([0.7, 0.05, 0.1, 0.075]) bcancel = Button(axbcancel, 'Cancel') bcancel.on_clicked(self.cancel) axbrun = plt.axes([0.81, 0.05, 0.1, 0.075]) brun = Button(axbrun, 'Run') brun.on_clicked(self.run) try: total_time = 0 curr_command = 0 in_new_cmds = False log_file = open(self.path_prefix + self.sample_name + ".txt", "r") #, encoding = "UTF8") for line in log_file.readlines(): if len(line.rstrip()) > 0 and line[0] != "#": step_time = 0 stripped_line = line.split("#")[0].rstrip() # setting GLOBAL_O, TR, or LOCAL_O if stripped_line.find("=") != -1 and stripped_line.find( "=") < stripped_line.find("("): val = stripped_line.split("=", 1)[0].rstrip() args = list( map( float, re.sub( "[^0-9.,]", "", stripped_line.split("=", 1)[1].replace( "V2", "").replace("V3", "")).split(","))) if val == "GLOBAL_O": self.GLOBAL_O = V2((args[0], args[1])) elif val == "TR": self.TR = V2((args[0], args[1])) self.REGION_SIZE = self.GLOBAL_O - self.TR ax.add_patch( Rectangle((0, 0), self.REGION_SIZE.x, self.REGION_SIZE.y, fill=None, alpha=1)) plt.xlim(-0.05 * self.REGION_SIZE.x, 1.05 * self.REGION_SIZE.x) plt.ylim(-0.05 * self.REGION_SIZE.y, 1.05 * self.REGION_SIZE.y) ax.xaxis.set_ticks( np.arange(0, self.REGION_SIZE.x, 2)) ax.yaxis.set_ticks( np.arange(0, self.REGION_SIZE.y, 2)) ax.set_aspect('equal', adjustable='box') elif val == "LOCAL_O": self.local_o = V2((args[0], args[1])) self.new_file_text += line # calling command else: curr_command += 1 cmd = stripped_line.split("(", 1)[0] # separates out arguments, omitting lists (e.g., "speeds" array in write_parallel_lines_vertical_region_tall) args_str = stripped_line.split("(", 1)[1].replace( "V2", "").replace("V3", "") array_arg = re.search("\[.*?\]", args_str) if array_arg: speeds = list( map( float, re.sub("\[|\]", "", array_arg.group(0)).split(","))) args_str = re.sub("\[.*?\]", "{}".format(len(speeds)), args_str) args = list( map(float, re.sub("[^0-9.,-]", "", args_str).split(","))) # write_parallel_lines_vertical_continuous(z, start, end, gap, speed) if cmd == "write_parallel_lines_vertical_continuous": start = self.local_o + V2((args[1], args[2])) end = self.local_o + V2((args[3], args[4])) gap = args[5] shift = V2((gap, 0)) speed = args[6] ax.annotate(curr_command, xy=(start.x, start.y)) num_lines = int( abs((end - start).x) / float(shift.x)) for i in range(0, num_lines, 2): step_time += self.render_write_line( ax, start + shift * i, V2((start.x, end.y)) + shift * i, speed, in_new_cmds) step_time += self.render_write_line( ax, V2((start.x, end.y)) + shift * (i + 1), start + shift * (i + 1), speed, in_new_cmds) if in_new_cmds: self.new_cmds_array.append( (cmd, args[0], start, end, gap, speed)) # write_parallel_lines_horizontal_continuous(z, start, end, gap, speed) elif cmd == "write_parallel_lines_horizontal_continuous": start = self.local_o + V2((args[1], args[2])) end = self.local_o + V2((args[3], args[4])) gap = args[5] speed = args[6] shift = V2((0, gap)) ax.annotate(curr_command, xy=(start.x, start.y)) num_lines = int( abs((end - start).y) / float(shift.y)) for i in range(0, num_lines, 2): step_time += self.render_write_line( ax, start + shift * i, V2((end.x, start.y)) + shift * i, speed, in_new_cmds) step_time += self.render_write_line( ax, V2((end.x, start.y)) + shift * (i + 1), start + shift * (i + 1), speed, in_new_cmds) if in_new_cmds: self.new_cmds_array.append( (cmd, args[0], start, end, gap, speed)) # write_parallel_lines_vertical_region_tall(z, speeds, gap, inter_speed_gap_factor = 0.2) elif cmd == "write_parallel_lines_vertical_region_tall": start = self.local_o + V2((0, -1)) end = self.local_o + V2( (0, self.REGION_SIZE.y + 1)) gap = args[2] inter_speed_gap_factor = 0.2 if len( args) < 4 else args[3] shift = V2(((2 + inter_speed_gap_factor) * gap, 0)) ax.annotate(curr_command, xy=(start.x, start.y)) for i in range(len(speeds)): speed = speeds[i] step_time += self.render_write_line( ax, start + shift * i, end + shift * i, speed, in_new_cmds) step_time += self.render_write_line( ax, end + shift * i + V2((gap, 0)), start + shift * i + V2( (gap, 0)), speed, in_new_cmds) if in_new_cmds: self.new_cmds_array.append( (cmd, args[0], speeds, gap, inter_speed_gap_factor)) # write_parallel_lines_horizontal_region_wide(z, speeds, gap, inter_speed_gap_factor = 0.2) elif cmd == "write_parallel_lines_horizontal_region_wide": start = self.local_o + V2((-1, 0)) end = self.local_o + V2( (self.REGION_SIZE.x + 1, 0)) gap = args[2] inter_speed_gap_factor = 0.2 if len( args) < 4 else args[3] shift = V2((0, (2 + inter_speed_gap_factor) * gap)) ax.annotate(curr_command, xy=(start.x, start.y)) for i in range(len(speeds)): speed = speeds[i] step_time += self.render_write_line( ax, start + shift * i, end + shift * i, speed, in_new_cmds) step_time += self.render_write_line( ax, end + shift * i + V2((0, gap)), start + shift * i + V2( (0, gap)), speed, in_new_cmds) if in_new_cmds: self.new_cmds_array.append( (cmd, args[0], speeds, gap, inter_speed_gap_factor)) # write_parallel_lines_horizontal_const_height(z, x_width, speeds, gap, inter_speed_gap_factor = 0.2) elif cmd == "write_parallel_lines_horizontal_const_height": x_width = args[1] start = self.local_o end = self.local_o + V2((x_width, 0)) gap = args[3] inter_speed_gap_factor = 0.2 if len( args) < 5 else args[4] shift = V2((0, (2 + inter_speed_gap_factor) * gap)) ax.annotate(curr_command, xy=(start.x, start.y)) for i in range(len(speeds)): speed = speeds[i] step_time += self.render_write_line( ax, start + shift * i, end + shift * i, speed, in_new_cmds) step_time += self.render_write_line( ax, end + shift * i + V2((0, gap)), start + shift * i + V2( (0, gap)), speed, in_new_cmds) if in_new_cmds: self.new_cmds_array.append( (cmd, args[0], x_width, speeds, gap, inter_speed_gap_factor)) # write_parallel_lines_gap(z, start, end, gap, speed, num_lines) elif cmd == "write_parallel_lines_gap": start = self.local_o + V2((args[1], args[2])) end = self.local_o + V2((args[3], args[4])) gap = args[5] speed = args[6] num_lines = int(args[7]) ax.annotate(curr_command, xy=(start.x, start.y)) direction = end - start shift = direction.unit.perpendicular_clk * gap for i in range(num_lines): step_time += self.render_write_line( ax, start + shift * i, end + shift * i, speed, in_new_cmds) if in_new_cmds: self.new_cmds_array.append( (cmd, args[0], start, end, gap, speed, num_lines)) # write_parallel_lines_delta_s(z, start, end, gap_dist, speed, delta_speed, num_lines_per_speed, num_speeds) elif cmd == "write_parallel_lines_delta_s": start = self.local_o + V2((args[1], args[2])) end = self.local_o + V2((args[3], args[4])) gap_dist = args[5] speed = args[6] delta_speed = args[7] num_lines_per_speed = int(args[8]) num_speeds = int(args[9]) ax.annotate(curr_command, xy=(start.x, start.y)) direction = end - start shift = direction.unit.perpendicular_clk * gap_dist inter_speed_spacer = shift * ( num_lines_per_speed + (0.7 if num_lines_per_speed > 1 else 0)) for i in range(num_speeds): for j in range(num_lines_per_speed): step_time += self.render_write_line( ax, start + inter_speed_spacer * i + shift * j, end + inter_speed_spacer * i + shift * j, speed + i * delta_speed, in_new_cmds) if in_new_cmds: self.new_cmds_array.append( (cmd, args[0], start, end, gap_dist, speed, delta_speed, num_lines_per_speed, num_speeds)) # write_line(start, end, speed) elif cmd == "write_line": start = self.local_o + V2((args[0], args[1])) end = self.local_o + V2((args[2], args[3])) speed = args[4] ax.annotate(curr_command, xy=(start.x, start.y)) step_time += self.render_write_line( ax, start, end, speed, in_new_cmds) if in_new_cmds: self.new_cmds_array.append( (cmd, start, end, speed)) # write_circle(center, radius, speed) elif cmd == "write_circle": center = self.local_o + V2((args[0], args[1])) radius = args[2] speed = args[3] color = '#DF8800' if in_new_cmds else '#149E27' start = V2((center.x + radius, center.y)) ax.annotate( curr_command, xy=(start.x, start.y )) #args[-1][2:], xy=(start.x, start.y)) ax.add_patch( Circle((center.x, center.y), radius=radius, fill=None, alpha=1, color=color, linewidth=1.5)) if in_new_cmds: step_time += self.render_move_to_start( ax, start) + 2 * np.pi * radius / speed self.new_cmds_array.append( (cmd, center, radius, speed)) self.curr_pos.setXY(start) # write_part_circle(center, radius, start_deg, end_deg, speed) elif cmd == "write_part_circle": center = self.local_o + V2((args[0], args[1])) radius = args[2] start_deg = args[3] end_deg = args[4] speed = args[5] color = '#DF8800' if in_new_cmds else '#149E27' start = center + V2(start_deg) * radius ax.annotate( curr_command, xy=(start.x, start.y )) #args[-1][2:], xy=(start.x, start.y)) ax.add_patch( Arc((center.x, center.y), 2 * radius, 2 * radius, 0, start_deg, end_deg, fill=None, alpha=1, color=color, linewidth=1.5)) if in_new_cmds: step_time += self.render_move_to_start( ax, start) + 2 * np.pi * ( end_deg - start_deg) * radius / (360 * speed) self.new_cmds_array.append( (cmd, center, radius, start_deg, end_deg, speed)) self.curr_pos.setXY(center + V2(end_deg) * radius) # outline_region(z, speed = None) # DON'T CORRECT FOR LOCAL_O elif cmd == "outline_region": speed = self.default_speed if len( args) < 2 else args[1] ax.annotate(curr_command, xy=(-0.1, -0.1)) step_time += self.render_write_line( ax, V2((-0.1, -0.1)), V2((-0.1, self.REGION_SIZE.y + 0.1)), speed, in_new_cmds) step_time += self.render_write_line( ax, V2((-0.1, self.REGION_SIZE.y + 0.1)), self.REGION_SIZE + V2( (0.1, 0.1)), speed, in_new_cmds) step_time += self.render_write_line( ax, self.REGION_SIZE + V2((0.1, 0.1)), V2((self.REGION_SIZE.x + 0.1, -0.1)), speed, in_new_cmds) step_time += self.render_write_line( ax, V2((self.REGION_SIZE.x + 0.1, -0.1)), V2((-0.1, -0.1)), speed, in_new_cmds) if in_new_cmds: self.new_cmds_array.append( (cmd, args[0], speed)) # wipe_region(z, gap = 0.08, speed = None) # DON'T CORRECT FOR LOCAL_O elif cmd == "wipe_region": gap = args[1] speed = self.default_speed if len( args) < 3 else args[2] for i in range( int(self.REGION_SIZE.y / (2 * gap)) + 1): step_time += self.render_write_line( ax, V2((-1, gap * 2 * i)), V2((self.REGION_SIZE.x + 1, gap * 2 * i)), speed, in_new_cmds) step_time += self.render_write_line( ax, V2((self.REGION_SIZE.x + 1, gap * (2 * i + 1))), V2((-1, gap * (2 * i + 1))), speed, in_new_cmds) if in_new_cmds: self.new_cmds_array.append( (cmd, args[0], gap, speed)) # move_to(point, ground_speed = None, laser_on = False) elif cmd == "move_to": if in_new_cmds: point = self.local_o + V2((args[0], args[1])) speed = self.default_speed if len( args) < 3 else args[2] ax.annotate(curr_command, xy=(self.curr_pos.x, self.curr_pos.y)) step_time += self.render_move_to_start( ax, point, speed) self.new_cmds_array.append((cmd, point, speed)) if in_new_cmds: total_time += step_time self.new_file_text += line.rstrip( ) + "\t\t# [{}]\n".format(curr_command) else: self.new_file_text += line # reset local origin for new commands # NOTE: don't change the ## NEW header in the template sample file elif line[0:6] == "## NEW": in_new_cmds = True self.new_file_text = self.new_file_text.rstrip( ) + "\n\n# " + datetime.now(timezone( "US/Eastern")).strftime("%Y-%m-%d %H:%M:%S") + "\n" self.new_file_text += "LOCAL_O = V2((0, 0))\n" self.local_o = V2((0, 0)) self.curr_pos = self.TR * (-1) #curr_power = 0 elif line[0:6] == "## REF": in_new_cmds = False self.new_file_text += "\n\n\n\n## NEW COMMANDS\n\n\n\n\n\n" + line # include newlines and comments elif line[0] == "#" or not in_new_cmds: self.new_file_text += line log_file.close() plt.text(-110.0, 3.0, "{} s = {} min".format( int(10 * total_time) / 10.0, int(100 * total_time / 60.0) / 100.0), fontsize=12) plt.show() except FileNotFoundError: print("{}{} not found.".format(self.path_prefix, self.sample_name))
# REFERENCE: https://www.zaber.com/support/docs/api/core-python/0.9/binary.html#binary-module import sys, time import keithley_init as kc from coordinates import V2, V3 from zaber.serial import BinarySerial, BinaryDevice, BinaryCommand, CommandType GLOBAL_O = V2((0, 0)) TR = V2((0, 0)) LOCAL_O = V2((0, 0)) """ # CENTER SQUARE GLOBAL_O = V2((35.940, 29.300)) # ORIGIN = BOTTOM LEFT TR = V2((23.887, 16.591)) # TOP RIGHT REGION_SIZE = GLOBAL_O - TR # minor adjustments of writing region to prevent overlap without redefining global origin LOCAL_O = V2((-1.0, 0.6)) """ CONNECT_KEITHLEY = False LASER_CURRENT = 0.6 def main(): define_operating_constants() if CONNECT_KEITHLEY: setup_keithley()
def move_to(point, ground_speed=None, laser_on=False): if CONNECT_KEITHLEY: if not laser_on: keith.set_output_off() else: keith.set_output_on() ground_speed = DEFAULT_HOME_SPEED if ground_speed is None else ground_speed global_point = local2globalmm( point) # point data as a position (i.e., given invert, FsOR) global_point_data = mm2lindata(global_point) dist = global_point - current_position() lin_dist = V2(dist) # get the linear components of the distance lin_dist_data = mm2lindata(lin_dist) #z_dist_data = 0 if (type(point) is V2 or not CONNECT_ROTARY) else (mm2rotdata(point.z) - z_rotary.get_position()) veloc = abs(lin_dist.unit) * ground_speed x_time = time_to_move(lin_dist.x, veloc.x, LIN_STAGE_ACCELERATION) y_time = time_to_move(lin_dist.y, veloc.y, LIN_STAGE_ACCELERATION) #z_time = 0 if (type(point) is V2 or not CONNECT_ROTARY) else time_to_move(rotdata2deg(z_dist_data), DEFAULT_ROT_SPEED, ROT_STAGE_ACCELERATION) # !!! not tested but seems right times = [x_time, y_time] #, z_time] last_to_move = times.index(max(times)) if abs(lin_dist_data.x) > 0: x_linear.set_target_speed(linspeed2lindata(veloc.x), await_reply=True) if abs(lin_dist_data.y) > 0: y_linear.set_target_speed(linspeed2lindata(veloc.y), await_reply=True) # this is super ugly but it has to go like this procedurally, such that the command "await_reply"-ing (i.e., the slowest move) is the last one called if last_to_move == 0: if abs(lin_dist_data.y) > 0: y_linear.move_abs( global_point_data.y ) # don't await reply if x-axis will be slowest (necessary for simultaneous moves) #if abs(z_dist_data) > 0: # z_rotary.move_abs(mm2rotdata(point.z)) # don't await reply if x-axis will be slowest if abs(lin_dist_data.x) > 0: x_linear.move_abs(global_point_data.x, await_reply=True) elif last_to_move == 1: if abs(lin_dist_data.x) > 0: x_linear.move_abs(global_point_data.x ) # don't await reply if y-axis will be slowest #if abs(z_dist_data) > 0: # z_rotary.move_abs(mm2rotdata(point.z)) # don't await reply if y-axis will be slowest if abs(lin_dist_data.y) > 0: y_linear.move_abs(global_point_data.y, await_reply=True) """ elif last_to_move == 2: if abs(lin_dist_data.x) > 0: x_linear.move_abs(global_point_data.x) # don't await reply if rotary will be slowest if abs(lin_dist_data.y) > 0: y_linear.move_abs(global_point_data.y) # don't await reply if rotary will be slowest if abs(z_dist_data) > 0: z_rotary.move_abs(mm2rotdata(point.z), await_reply = True) """ if CONNECT_KEITHLEY and laser_on: keith.set_output_off()
def draw_map(self): fix, ax = plt.subplots(nrows=1, ncols=1, figsize=(5.5, 6)) plt.subplots_adjust(bottom=0.2) axbcancel = plt.axes([0.7, 0.05, 0.1, 0.075]) bcancel = Button(axbcancel, 'Cancel') bcancel.on_clicked(self.cancel) axbrun = plt.axes([0.81, 0.05, 0.1, 0.075]) brun = Button(axbrun, 'Run') brun.on_clicked(self.run) try: total_time = 0 curr_command = 1 curr_power = 0 new_commands_section = False reformatted_new_cmds = "" log_file = open(PATH_PREFIX + self.sample_name + ".txt", "r") for line in log_file.readlines(): if (line[0] != "#") and (line[0] != "-"): stripped_line = line.split("#")[0].rstrip() args = stripped_line.split("\t") step_time = 0 reformatted_str = "" color = '#DF8800' if new_commands_section else '#149E27' # i.e., orange if new; else green if args[0] == "L": start = self.local_o + V2(args[1]) end = self.local_o + V2(args[2]) speed = float(args[3]) ax.annotate(curr_command, xy=( start.x, start.y)) #args[-1][2:], xy=(start.x, start.y)) step_time = self.render_write_line( ax, start, end, speed, color) curr_command += 1 elif args[0] == "PLH": start = self.local_o + V2(args[1]) end = self.local_o + V2(args[2]) gap = float(args[3]) speed = float(args[4]) ax.annotate(curr_command, xy=( start.x, start.y)) #args[-1][2:], xy=(start.x, start.y)) for i in range(int((end - start).y / (2 * gap)) + 1): step_time += self.render_write_line( ax, start + V2((0, 2 * i * gap)), V2((end.x, start.y)) + V2((0, 2 * i * gap)), speed, color) step_time += self.render_write_line( ax, V2((end.x, start.y)) + V2( (0, (2 * i + 1) * gap)), start + V2( (0, (2 * i + 1) * gap)), speed, color) curr_command += 1 elif args[0] == "PLV": start = self.local_o + V2(args[1]) end = self.local_o + V2(args[2]) gap = float(args[3]) speed = float(args[4]) ax.annotate(curr_command, xy=( start.x, start.y)) #args[-1][2:], xy=(start.x, start.y)) for i in range(int((end - start).x / (2 * gap)) + 1): step_time += self.render_write_line( ax, V2((start.x + 2 * i * gap, start.y)), V2((start.x + 2 * i * gap, end.y)), speed, color) step_time += self.render_write_line( ax, V2((start.x + (2 * i + 1) * gap, end.y)), V2((start.x + (2 * i + 1) * gap, start.y)), speed, color) curr_command += 1 elif args[0] == "C": center = self.local_o + V2(args[1]) radius = float(args[2]) speed = float(args[3]) start = V2((center.x + radius, center.y)) ax.annotate(curr_command, xy=( start.x, start.y)) #args[-1][2:], xy=(start.x, start.y)) ax.add_patch( Circle((center.x, center.y), radius=radius, fill=None, alpha=1, color=color, linewidth=1.5)) step_time = self.render_move_to_start( ax, start) + 2 * np.pi * radius / speed self.curr_pos.setXY(start) curr_command += 1 # wipe functions ignore local_o elif args[0] == "WH": gap = float(args[1]) speed = float(args[2]) ax.annotate( curr_command, xy=(0, 0)) #args[-1][2:], xy=(start.x, start.y)) for i in range(int(REGION_SIZE.y / (2 * gap)) + 1): step_time += self.render_write_line( ax, V2((-0.5, 2 * i * gap)), V2((self.REGION_SIZE.x + 0.5, 2 * i * gap)), speed, color) step_time += self.render_write_line( ax, V2((self.REGION_SIZE.x + 0.5, (2 * i + 1) * gap)), V2((-0.5, (2 * i + 1) * gap)), speed, color) curr_command += 1 elif args[0] == "WV": gap = float(args[1]) speed = float(args[2]) ax.annotate( curr_command, xy=(0, 0)) #args[-1][2:], xy=(start.x, start.y)) for i in range(int((end - start).x / (2 * gap)) + 1): step_time += self.render_write_line( ax, V2((2 * i * gap, -0.5)), V2((2 * i * gap, self.REGION_SIZE.y + 0.5)), speed, color) step_time += self.render_write_line( ax, V2(((2 * i + 1) * gap, self.REGION_SIZE.y + 0.5)), V2(((2 * i + 1) * gap, -0.5)), speed, color) curr_command += 1 # reformat new commands with comment to the side to keep track of power/height settings if new_commands_section and stripped_line != "": if args[0] not in ["P", "Z", "LOC"]: total_time += step_time curr_power_str = " ----" if curr_power == 0 else " " * ( 2 - int(math.log10(curr_power))) + str(curr_power) reformatted_cmd = stripped_line + "\t" * int( 9 - len(stripped_line.expandtabs()) / 8 ) + "## {}. {}(z = {}, P = {} mW, t = {} s {}= {} min)\n".format( curr_command - 1, " " * (1 - int(math.log10(curr_command - 1))) + args[0] + " " * (4 - len(args[0])), self.curr_pos.z, curr_power_str, int(step_time), " " * (1 - int(step_time / 10)), int(step_time / 60 + 0.5)) reformatted_new_cmds += reformatted_cmd elif args[0] != "LOC": reformatted_new_cmds += line self.reformatted_file_text += line else: reformatted_new_cmds += line else: self.reformatted_file_text += line if args[0] == "TR": self.TR = V2( args[1]) # string parsing added in coordinates elif args[0] == "O": self.GLOBAL_O = V2(args[1]) self.REGION_SIZE = self.GLOBAL_O - self.TR ax.add_patch( Rectangle((0, 0), self.REGION_SIZE.x, self.REGION_SIZE.y, fill=None, alpha=1)) plt.xlim(left=-0.05 * self.REGION_SIZE.x, right=1.05 * self.REGION_SIZE.x) plt.ylim(bottom=-0.05 * self.REGION_SIZE.y, top=1.05 * self.REGION_SIZE.y) ax.xaxis.set_ticks(np.arange(0, self.REGION_SIZE.x, 2)) ax.yaxis.set_ticks(np.arange(0, self.REGION_SIZE.y, 2)) ax.set_aspect('equal', adjustable='box') elif args[0] == "Z": self.curr_pos.z = float(args[1]) curr_command += 1 elif args[0] == "P": curr_power = float(args[1]) elif args[0] == "LOC": self.local_o = V2(args[1]) elif args[0] == "%%%": new_commands_section = not new_commands_section if new_commands_section: reformatted_new_cmds += "LOC\t[0, 0]\n" self.local_o = V2((0, 0)) self.curr_pos = V3(self.TR * (-1), 0) curr_power = 0 else: self.reformatted_file_text += line print(self.reformatted_file_text.split("%%%")) before, middle, after = self.reformatted_file_text.split("%%%") self.reformatted_file_text = before + "%%%\n\n# " + datetime.now( timezone("US/Eastern")).strftime( "%Y-%m-%d %H:%M:%S" ) + "\n" + middle + reformatted_new_cmds + after log_file.close() plt.text(-110.0, 3.0, "{} s = {} min".format( int(10 * total_time) / 10.0, int(100 * total_time / 60.0) / 100.0), fontsize=12) plt.show() except FileNotFoundError: print("{}{} not found.".format(PATH_PREFIX, self.sample_name))
""" IF (IN CONSOLE) PRESSING STOP DOES NOT DISPLAY THE CURRENT POSITION, I THINK IT'S PROBABLY BECAUSE DISABLE_AUTO_REPLY IS ON. RESET DEVICE MODE SUCH THAT BIT 0 = 0. """ import sys, time, math, winsound import keyboard import keithley_handler as kc from drawing_handler import MoveMapper from coordinates import V2, V3 from zaber.serial import BinarySerial, BinaryDevice, BinaryCommand, CommandType #""" SAMPLE_NAME = "HW 2020-01-23 A" GLOBAL_O = V2((35.6, 39.0260)) # ORIGIN = BOTTOM LEFT TR = V2((21.6566, 25.0)) # TOP RIGHT LOCAL_O = V2( (6.2, 0.5) ) # minor adjustments of writing region to prevent overlap without redefining global origin #""" """ HW 2020-01-23 B "" GLOBAL_O = V2((35.9, 35.3)) # ORIGIN = BOTTOM LEFT TR = V2((22.0, 21.0)) # TOP RIGHT LOCAL_O = V2((1.0, 8.6)) # minor adjustments of writing region to prevent overlap without redefining global origin #""" """ SAMPLE_NAME = "HW_1_19_1" GLOBAL_O = V2((35.9859, 37.8388)) # ORIGIN = BOTTOM LEFT
def current_position(): if DUMMY_CONNECTIONS: return V2((0, 0)) return V2((lindata2mm(x_linear.get_position()), lindata2mm(y_linear.get_position())))
def draw_map(self): plt.figure() ax = plt.gca() try: total_time = 0 curr_command = 1 curr_power = 0 new_commands_section = False reformatted_new_cmds = "" log_file = open(self.path_prefix + self.sample_name + ".txt", "r") for line in log_file.readlines(): if (line[0] != "#") and (line[0] != "-"): args = line.rstrip().split("\t") step_time = 0 reformatted_str = "" color = '#DF8800' if new_commands_section else '#149E27' # i.e., orange if new; else green if args[0] == "L": start = self.local_o + V2(args[1]) end = self.local_o + V2(args[2]) speed = float(args[3]) ax.annotate(curr_command, xy=( start.x, start.y)) #args[-1][2:], xy=(start.x, start.y)) step_time = self.render_write_line( ax, start, end, speed, color) curr_command += 1 elif args[0] == "PLH": start = self.local_o + V2(args[1]) end = self.local_o + V2(args[2]) gap = float(args[3]) speed = float(args[4]) ax.annotate(curr_command, xy=( start.x, start.y)) #args[-1][2:], xy=(start.x, start.y)) for i in range(int((end - start).y / (2 * gap)) + 1): step_time += self.render_write_line( ax, start + V2((0, 2 * i * gap)), V2((end.x, start.y)) + V2((0, 2 * i * gap)), speed, color) step_time += self.render_write_line( ax, V2((end.x, start.y)) + V2( (0, (2 * i + 1) * gap)), start + V2( (0, (2 * i + 1) * gap)), speed, color) curr_command += 1 elif args[0] == "PLV": start = self.local_o + V2(args[1]) end = self.local_o + V2(args[2]) gap = float(args[3]) speed = float(args[4]) ax.annotate(curr_command, xy=( start.x, start.y)) #args[-1][2:], xy=(start.x, start.y)) for i in range(int((end - start).x / (2 * gap)) + 1): step_time += self.render_write_line( ax, V2((start.x + 2 * i * gap, start.y)), V2((start.x + 2 * i * gap, end.y)), speed, color) step_time += self.render_write_line( ax, V2((start.x + (2 * i + 1) * gap, end.y)), V2((start.x + (2 * i + 1) * gap, start.y)), speed, color) curr_command += 1 elif args[0] == "C": center = self.local_o + V2(args[1]) radius = float(args[2]) speed = float(args[3]) start = V2((center.x + radius, center.y)) ax.annotate(curr_command, xy=( start.x, start.y)) #args[-1][2:], xy=(start.x, start.y)) ax.add_patch( Circle((center.x, center.y), radius=radius, fill=None, alpha=1, color=color, linewidth=1.5)) step_time = self.render_move_to_start( ax, start) + 2 * np.pi * radius / speed self.curr_pos.setXY(start) curr_command += 1 # wipe functions ignore local_o elif args[0] == "WH": gap = float(args[1]) speed = float(args[2]) ax.annotate( curr_command, xy=(0, 0)) #args[-1][2:], xy=(start.x, start.y)) for i in range(int(REGION_SIZE.y / (2 * gap)) + 1): step_time += self.render_write_line( ax, V2((-0.5, 2 * i * gap)), V2((self.REGION_SIZE.x + 0.5, 2 * i * gap)), speed, color) step_time += self.render_write_line( ax, V2((self.REGION_SIZE.x + 0.5, (2 * i + 1) * gap)), V2((-0.5, (2 * i + 1) * gap)), speed, color) curr_command += 1 elif args[0] == "WV": gap = float(args[1]) speed = float(args[2]) ax.annotate( curr_command, xy=(0, 0)) #args[-1][2:], xy=(start.x, start.y)) for i in range(int((end - start).x / (2 * gap)) + 1): step_time += self.render_write_line( ax, V2((2 * i * gap, -0.5)), V2((2 * i * gap, self.REGION_SIZE.y + 0.5)), speed, color) step_time += self.render_write_line( ax, V2(((2 * i + 1) * gap, self.REGION_SIZE.y + 0.5)), V2(((2 * i + 1) * gap, -0.5)), speed, color) curr_command += 1 # reformat new commands with comment to the side to keep track of power/height settings if new_commands_section and line.rstrip( ) != "" and args[0] not in ["P", "Z"]: total_time += step_time reformatted_cmd = line.rstrip() + "\t" * int( 9 - len(line.rstrip().expandtabs()) / 8 ) + "## {}. {}(z = {}, P = {} mW, t = {} s {}= {} min)\n".format( curr_command - 1 if args[0] != "LOC" else "-", " " * (1 - int(math.log10(curr_command - 1))) + args[0] + " " * (4 - len(args[0])), self.curr_pos.z, " " * (2 - int(math.log10(curr_power))) + str(curr_power), int(step_time), " " * (1 - int(step_time / 10)), int(step_time / 60 + 0.5)) reformatted_new_cmds += reformatted_cmd elif args[0] not in ["P", "Z"]: #else self.reformatted_file_text += line """ elif args[0] in ["P", "Z"]: reformatted_new_cmds += line """ if args[0] == "TR": self.TR = V2( args[1]) # string parsing added in coordinates elif args[0] == "O": self.GLOBAL_O = V2(args[1]) self.REGION_SIZE = self.GLOBAL_O - self.TR ax.add_patch( Rectangle((0, 0), self.REGION_SIZE.x, self.REGION_SIZE.y, fill=None, alpha=1)) plt.xlim(left=-0.05 * self.REGION_SIZE.x, right=1.05 * self.REGION_SIZE.x) plt.ylim(bottom=-0.05 * self.REGION_SIZE.y, top=1.05 * self.REGION_SIZE.y) ax.xaxis.set_ticks(np.arange(0, self.REGION_SIZE.x, 2)) ax.yaxis.set_ticks(np.arange(0, self.REGION_SIZE.y, 2)) ax.set_aspect('equal', adjustable='box') elif args[0] == "Z": self.curr_pos.z = float(args[1]) curr_command += 1 elif args[0] == "P": curr_power = float(args[1]) elif args[0] == "LOC": self.local_o = V2(args[1]) elif args[0] == "%%%": new_commands_section = True self.local_o = V2((0, 0)) #self.curr_pos = V3(self.TR*(-1), 0) else: self.reformatted_file_text += line print(total_time) before, after = self.reformatted_file_text.split("%%%") self.reformatted_file_text = before + "# " + datetime.now( timezone("US/Eastern")).strftime( "%Y-%m-%d %H:%M:%S" ) + "\n" + reformatted_new_cmds + "\n%%%" + after print(self.reformatted_file_text) log_file.close() plt.show() except FileNotFoundError: log_file = open( "/Users/harperwallace/Dropbox/_MISC/Python/%s.dat" % SAMPLE_NAME, "w+") log_file.close()
def main(): try: define_operating_constants() # Doesn't do anything if !CONNECT_KEITHLEY or fake connections setup_keithley() # Be sure to call setup_stages() before moving/setting objective height # Note that there's some give in the rotation of the pin through # the microscope coarse control setup_stages() if POSITION_GETTER_MODE: # Press 'p' to print current position to console keyboard.add_hotkey('p', print_position) # Press 'esc' once you're finished with position-getting keyboard.wait('esc') elif MOVE_MAPPING: mh = MappingHandler( SAMPLES_PATH, SAMPLE_NAME, (CONNECT_KEITHLEY if not DUMMY_CONNECTIONS else False), DEFAULT_HOME_SPEED) mh.draw_map() if mh.continue_to_run: write_mapped_commands(mh) mh.update_sample_history() else: # MANUAL COMMAND-CALLING # EXTREMELY IMPORTANT NOTES: # 1. DON'T LET THE OBJECTIVE LENS HIT THE SAMPLE HOLDER SCREWS. # 2. DON'T MELT THE BEAM SHUTTER BY LEAVING THE LASER ON IT TOO LONG. # (details in README.md) # Extract GLOBAL_O and TR from the sample's corresponding .txt file. # Note that if GLOBAL_O appears in a line below TR for some # reason, then GLOBAL_O won't be read (i.e., don't change the # order of GLOBAL_O and TR from the template file). try: log_file = open(SAMPLES_PATH + SAMPLE_NAME + ".txt", "r") for line in log_file.readlines(): if len(line.rstrip()) > 0 and line[0] != "#": stripped_line = line.split("#")[0].rstrip() if stripped_line.find( "=") != -1 and stripped_line.find( "=") < stripped_line.find("("): val = stripped_line.split("=", 1)[0].rstrip() args = list( map( float, re.sub( "[^0-9.,]", "", stripped_line.split("=", 1)[1].replace( "V2", "").replace("V3", "")).split(","))) if val == "GLOBAL_O": GLOBAL_O = V2((args[0], args[1])) elif val == "TR": TR = V2((args[0], args[1])) REGION_SIZE = GLOBAL_O - TR break except FileNotFoundError: print("SAMPLE FILE NOT FOUND. USING GENERIC ORIGINS.") # Move writing region without redefining global origins LOCAL_O = V2((0, 0)) ## BEGIN MANUAL COMMANDS: ## END MANUAL COMMANDS """ REFERENCE: write_parallel_lines_gap(z, start, end, gap, speed, num_lines): write_parallel_lines_vertical_continuous(z, start, end, gap, speed): write_parallel_lines_horizontal_continuous(z, start, end, gap, speed): write_parallel_lines_vertical_region_tall(z, speeds, gap, inter_speed_gap_factor = 0.2): write_parallel_lines_horizontal_region_wide(z, speeds, gap, inter_speed_gap_factor = 0.2): write_parallel_lines_horizontal_const_height(z, x_width, speeds, gap, inter_speed_gap_factor = 0.2): write_parallel_lines_delta_s(z, start, end, gap, speed, delta_speed, num_lines_per_speed, num_speeds): write_line(start, end, speed): write_circle(center, radius, speed): write_part_circle(center, radius, start_deg, end_deg, speed): outline_region(z, speed = None): wipe_region(z, gap = 0.08, speed = None): move_to(point, ground_speed = None, laser_on = False): home_all(): """ if not MAC_TESTING: # Make a little beep noise so I know it's all finished winsound.Beep(1000, 500) # SHIFT-CTRL-C TO INTERRUPT, THEN CLEAN UP except KeyboardInterrupt: print("--terminated--") except: print("--unexpected error--") raise finally: clean_up()