def run(self): """ Script run on thread start. Performs area scan on a separate thread. :return: Nothing. """ print("Measurement Parameters:") print("Type: %s | Field: %s | Side: %s" % (self.meas_type, self.meas_field, self.meas_side)) print("Measurement: ", self.meas) # Preparation x_points = int(np.ceil(np.around(self.x_distance / self.grid_step_dist, decimals=3))) + 1 y_points = int(np.ceil(np.around(self.y_distance / self.grid_step_dist, decimals=3))) + 1 # Check ports and instantiate relevant objects (motors, NARDA driver) try: m = MotorDriver() except serial.SerialException: print("Error: Connection to C4 controller was not found") wx.CallAfter(self.parent.enablegui) self.exc = sys.exc_info() i = 10 while i: print(i) time.sleep(1) i -= 1 print("Thread '%s' threw an exception: %s" % (self.getName(), self.exc[0])) return narda = NardaNavigator() # Set measurement settings narda.selectTab('mode') narda.selectInputField(self.meas_field) narda.selectTab('span') narda.inputTextEntry('start', str(self.span_start)) narda.inputTextEntry('stop', str(self.span_stop)) narda.selectRBW(self.meas_rbw) narda.selectTab('data') narda.enableMaxHold() # Calculate number of motor steps necessary to move one grid space self.num_steps = self.grid_step_dist / m.step_unit # Run scan self.values, self.grid, self.curr_row,\ self.curr_col, self.max_fname = run_scan(x_points, y_points, m, narda, self.num_steps, self.dwell_time, self.save_dir, self.comment, self.meas_type, self.meas_field, self.meas_side, self.meas, self.start_pos) print("General area scan complete.") self.callback(self) wx.CallAfter(self.parent.run_post_scan) m.destroy()
def run(self): """ Script run on thread start. Corrects a previous value from the general area scan results on a separate thread. :return: Nothing. """ print("Measurement Parameters:") print("Type: %s | Field: %s | Side: %s" % (self.meas_type, self.meas_field, self.meas_side)) print("Measurement: ", self.meas) # Check ports and instantiate relevant objects (motors, NARDA driver) try: m = MotorDriver() except serial.SerialException: print("Error: Connection to C4 controller was not found.") return -1 narda = NardaNavigator() # Set measurement settings narda.selectTab('mode') narda.selectInputField(self.meas_field) narda.selectTab('span') narda.inputTextEntry('start', str(self.span_start)) narda.inputTextEntry('stop', str(self.span_stop)) narda.selectRBW(self.meas_rbw) narda.selectTab('data') # Find the target location target_row, target_col = np.where(self.grid == int(self.target)) row_steps = target_row - self.curr_row col_steps = target_col - self.curr_col # Move to target location print("R steps: %d - C steps %d" % (row_steps, col_steps)) if row_steps > 0: m.forward_motor_two(int(self.num_steps * row_steps)) else: m.reverse_motor_two(int(-1 * self.num_steps * row_steps)) if col_steps > 0: m.forward_motor_one(int(self.num_steps * col_steps)) else: m.reverse_motor_one(int(-1 * self.num_steps * col_steps)) self.curr_row = target_row self.curr_col = target_col print(self.values) print("row:", self.curr_row, "col:", self.curr_col) fname = build_filename(self.meas_type, self.meas_field, self.meas_side, self.target) # Take measurement value = narda.takeMeasurement(self.dwell_time, self.meas, fname, self.save_dir, self.comment) self.values[self.curr_row, self.curr_col] = value print(self.values) # Check if max and take screenshot of plot/UI accordingly if value > self.values.max(): print("New max val: %f" % value) # Switch to Snipping Tool in front of the NARDA program narda.saveBitmap(fname, self.save_dir) narda.bringToFront() # Once bitmap is saved, return focus to NARDA os.rename(self.save_dir + '/' + self.max_fname + '.PNG', self.save_dir + '/' + fname + '.PNG') print("Correction of previous value complete.") self.callback(self) wx.CallAfter(self.parent.run_post_scan) m.destroy()
def __init__(self, parent, title, grid_step): """ :param parent: Parent frame invoking the LocationSelectGUI. :param title: Title for the GUI window. :param grid_step: The grid step size. """ wx.Frame.__init__(self, parent, title=title, size=(400, 400)) # Variables try: self.motor = MotorDriver() except serial.SerialException: print("Error: Connection to C4 controller was not found") self.Close() return # self.narda = NardaNavigator() self.currx = 0.0 self.curry = 0.0 self.distx = grid_step self.disty = grid_step self.errx = 0.0 self.erry = 0.0 self.stepx = int(self.distx / self.motor.step_unit) self.stepy = int(self.disty / self.motor.step_unit) self.fracx = self.distx / self.motor.step_unit - self.stepx self.fracy = self.disty / self.motor.step_unit - self.stepy # UI Elements up_id = 301 down_id = 302 left_id = 303 right_id = 304 self.up_btn = wx.Button(self, up_id, "Up") self.down_btn = wx.Button(self, down_id, "Down") self.left_btn = wx.Button(self, left_id, "Left") self.right_btn = wx.Button(self, right_id, "Right") self.coord_box = wx.StaticText(self, label="Coordinates:\n[%.3f, %.3f]" % (self.currx, self.curry)) self.x_text = wx.StaticText(self, label="X Step Distance (in cm)") self.x_tctrl = wx.TextCtrl(self, style=wx.TE_PROCESS_ENTER) self.x_tctrl.SetValue(str(self.distx)) self.y_text = wx.StaticText(self, label="Y Step Distance (in cm)") self.y_tctrl = wx.TextCtrl(self, style=wx.TE_PROCESS_ENTER) self.y_tctrl.SetValue(str(self.disty)) # Bindings/Shortcuts self.Bind(wx.EVT_KEY_UP, self.OnKey) # Binding on "up" event to only register once self.Bind(wx.EVT_TEXT_ENTER, self.update_settings) self.Bind(wx.EVT_CHILD_FOCUS, self.update_settings) self.Bind(wx.EVT_BUTTON, self.move_up, self.up_btn) self.Bind(wx.EVT_BUTTON, self.move_down, self.down_btn) self.Bind(wx.EVT_BUTTON, self.move_left, self.left_btn) self.Bind(wx.EVT_BUTTON, self.move_right, self.right_btn) self.Bind(wx.EVT_CLOSE, self.OnClose) # Sizers/Layout, Static Lines, & Static Boxes self.mainh_sizer = wx.BoxSizer(wx.HORIZONTAL) self.btn_stbox = wx.StaticBoxSizer(wx.VERTICAL, self, "Control Buttons") self.btn_sizer = wx.GridSizer(rows=3, cols=3, hgap=0, vgap=0) self.settings_stbox = wx.StaticBoxSizer(wx.VERTICAL, self, "Settings") self.btn_sizer.AddStretchSpacer(prop=1) self.btn_sizer.Add(self.up_btn, proportion=1, flag=wx.EXPAND) self.btn_sizer.AddStretchSpacer(prop=1) self.btn_sizer.Add(self.left_btn, proportion=1, flag=wx.EXPAND) self.btn_sizer.AddStretchSpacer(prop=1) self.btn_sizer.Add(self.right_btn, proportion=1, flag=wx.EXPAND) self.btn_sizer.AddStretchSpacer(prop=1) self.btn_sizer.Add(self.down_btn, proportion=1, flag=wx.EXPAND) self.btn_sizer.AddStretchSpacer(prop=1) self.btn_stbox.Add(self.btn_sizer, proportion=5, flag=wx.EXPAND) self.btn_stbox.Add(self.coord_box, proportion=1, flag=wx.EXPAND) self.settings_stbox.Add(self.x_text, proportion=0, flag=wx.EXPAND) self.settings_stbox.Add(self.x_tctrl, proportion=0, flag=wx.EXPAND) self.settings_stbox.Add(self.y_text, proportion=0, flag=wx.EXPAND) self.settings_stbox.Add(self.y_tctrl, proportion=0, flag=wx.EXPAND) self.mainh_sizer.Add(self.btn_stbox, proportion=5, flag=wx.EXPAND | wx.ALL, border=5) self.mainh_sizer.Add(self.settings_stbox, proportion=2, flag=wx.EXPAND | wx.ALL, border=5) self.SetSizer(self.mainh_sizer) self.SetAutoLayout(True) self.mainh_sizer.Fit(self) self.Show(True)
def run(self): """ Script run on thread start. Performs zoom scan on a separate thread. :return: Nothing. """ print("Measurement Parameters:") print("Type: %s | Field: %s | Side: %s" % (self.meas_type, self.meas_field, self.meas_side)) print("Measurement: ", self.meas) # Preparation x_points = 5 y_points = 5 # Check ports and instantiate relevant objects (motors, NARDA driver) try: m = MotorDriver() except serial.SerialException: print("Error: Connection to C4 controller was not found") return -1 narda = NardaNavigator() # Set measurement settings narda.selectTab('mode') narda.selectInputField(self.meas_field) narda.selectTab('span') narda.inputTextEntry('start', str(self.span_start)) narda.inputTextEntry('stop', str(self.span_stop)) narda.selectRBW(self.meas_rbw) narda.selectTab('data') # Calculate number of motor steps necessary to move one grid space znum_steps = self.num_steps / 4.0 # Zoom scan steps are scaled down # Move to coordinate with maximum value max_val = self.values.max() max_row, max_col = np.where(self.values == float(max_val)) print("Max value: %f" % max_val) print(max_row, max_col) print("Max value coordinates: Row - %d / Col - %d" % (max_row, max_col)) row_steps = max_row - self.curr_row col_steps = max_col - self.curr_col self.curr_row = max_row self.curr_col = max_col if row_steps > 0: m.forward_motor_two(int(self.num_steps * row_steps)) else: m.reverse_motor_two(int(-1 * self.num_steps * row_steps)) if col_steps > 0: m.forward_motor_one(int(self.num_steps * col_steps)) else: m.reverse_motor_one(int(-1 * self.num_steps * col_steps)) # Run scan self.zoom_values, _, _, _, _ = run_scan(x_points, y_points, m, narda, znum_steps, self.dwell_time, self.save_dir, self.comment, self.meas_type, self.meas_field, 'z', self.meas) # Move back to original position m.reverse_motor_one(int(2 * znum_steps)) m.reverse_motor_two(int(2 * znum_steps)) print("Zoom scan complete.") self.callback(self) wx.CallAfter(self.parent.run_post_scan) m.destroy()
class ManualMoveGUI(wx.Frame): """ GUI interfaced with the MotorDriver class that allows manual control over the motors. """ def __init__(self, parent, title, grid_step): """ :param parent: Parent frame invoking the LocationSelectGUI. :param title: Title for the GUI window. :param grid_step: The grid step size. """ wx.Frame.__init__(self, parent, title=title, size=(400, 400)) # Variables try: self.motor = MotorDriver() except serial.SerialException: print("Error: Connection to C4 controller was not found") self.Close() return # self.narda = NardaNavigator() self.currx = 0.0 self.curry = 0.0 self.distx = grid_step self.disty = grid_step self.errx = 0.0 self.erry = 0.0 self.stepx = int(self.distx / self.motor.step_unit) self.stepy = int(self.disty / self.motor.step_unit) self.fracx = self.distx / self.motor.step_unit - self.stepx self.fracy = self.disty / self.motor.step_unit - self.stepy # UI Elements up_id = 301 down_id = 302 left_id = 303 right_id = 304 self.up_btn = wx.Button(self, up_id, "Up") self.down_btn = wx.Button(self, down_id, "Down") self.left_btn = wx.Button(self, left_id, "Left") self.right_btn = wx.Button(self, right_id, "Right") self.coord_box = wx.StaticText(self, label="Coordinates:\n[%.3f, %.3f]" % (self.currx, self.curry)) self.x_text = wx.StaticText(self, label="X Step Distance (in cm)") self.x_tctrl = wx.TextCtrl(self, style=wx.TE_PROCESS_ENTER) self.x_tctrl.SetValue(str(self.distx)) self.y_text = wx.StaticText(self, label="Y Step Distance (in cm)") self.y_tctrl = wx.TextCtrl(self, style=wx.TE_PROCESS_ENTER) self.y_tctrl.SetValue(str(self.disty)) # Bindings/Shortcuts self.Bind(wx.EVT_KEY_UP, self.OnKey) # Binding on "up" event to only register once self.Bind(wx.EVT_TEXT_ENTER, self.update_settings) self.Bind(wx.EVT_CHILD_FOCUS, self.update_settings) self.Bind(wx.EVT_BUTTON, self.move_up, self.up_btn) self.Bind(wx.EVT_BUTTON, self.move_down, self.down_btn) self.Bind(wx.EVT_BUTTON, self.move_left, self.left_btn) self.Bind(wx.EVT_BUTTON, self.move_right, self.right_btn) self.Bind(wx.EVT_CLOSE, self.OnClose) # Sizers/Layout, Static Lines, & Static Boxes self.mainh_sizer = wx.BoxSizer(wx.HORIZONTAL) self.btn_stbox = wx.StaticBoxSizer(wx.VERTICAL, self, "Control Buttons") self.btn_sizer = wx.GridSizer(rows=3, cols=3, hgap=0, vgap=0) self.settings_stbox = wx.StaticBoxSizer(wx.VERTICAL, self, "Settings") self.btn_sizer.AddStretchSpacer(prop=1) self.btn_sizer.Add(self.up_btn, proportion=1, flag=wx.EXPAND) self.btn_sizer.AddStretchSpacer(prop=1) self.btn_sizer.Add(self.left_btn, proportion=1, flag=wx.EXPAND) self.btn_sizer.AddStretchSpacer(prop=1) self.btn_sizer.Add(self.right_btn, proportion=1, flag=wx.EXPAND) self.btn_sizer.AddStretchSpacer(prop=1) self.btn_sizer.Add(self.down_btn, proportion=1, flag=wx.EXPAND) self.btn_sizer.AddStretchSpacer(prop=1) self.btn_stbox.Add(self.btn_sizer, proportion=5, flag=wx.EXPAND) self.btn_stbox.Add(self.coord_box, proportion=1, flag=wx.EXPAND) self.settings_stbox.Add(self.x_text, proportion=0, flag=wx.EXPAND) self.settings_stbox.Add(self.x_tctrl, proportion=0, flag=wx.EXPAND) self.settings_stbox.Add(self.y_text, proportion=0, flag=wx.EXPAND) self.settings_stbox.Add(self.y_tctrl, proportion=0, flag=wx.EXPAND) self.mainh_sizer.Add(self.btn_stbox, proportion=5, flag=wx.EXPAND | wx.ALL, border=5) self.mainh_sizer.Add(self.settings_stbox, proportion=2, flag=wx.EXPAND | wx.ALL, border=5) self.SetSizer(self.mainh_sizer) self.SetAutoLayout(True) self.mainh_sizer.Fit(self) self.Show(True) def move_up(self, e): """ Moves the NS probe forward (i.e. negative X direction of the phone). :param e: Event handler. :return: Nothing. """ self.curry -= self.disty self.erry -= self.fracy self.motor.reverse_motor_two(self.stepy + int(self.erry)) self.erry -= int(self.erry) self.coord_box.SetLabel("Coordinates:\n[%.3f, %.3f]" % (self.currx, self.curry)) def move_down(self, e): """ Moves the NS probe backward (i.e. positive X direction of the phone). :param e: Event handler. :return: Nothing. """ self.curry += self.disty self.erry += self.fracy self.motor.forward_motor_two(self.stepy + int(self.erry)) self.erry -= int(self.erry) self.coord_box.SetLabel("Coordinates:\n[%.3f, %.3f]" % (self.currx, self.curry)) def move_left(self, e): """ Moves the NS probe leftward (i.e. negative Y direction of the phone). :param e: Event handler. :return: Nothing. """ self.currx -= self.distx self.errx -= self.fracx self.motor.reverse_motor_one(self.stepx + int(self.errx)) self.errx -= int(self.errx) self.coord_box.SetLabel("Coordinates:\n[%.3f, %.3f]" % (self.currx, self.curry)) def move_right(self, e): """ Moves the NS probe rightward (i.e. positive Y direction of the phone). :param e: Event handler. :return: Nothing. """ self.currx += self.distx self.errx += self.fracx self.motor.forward_motor_one(self.stepx + int(self.errx)) self.errx -= int(self.errx) self.coord_box.SetLabel("Coordinates:\n[%.3f, %.3f]" % (self.currx, self.curry)) def OnKey(self, e): """ Handles wx.EVT_KEY_UP events (releasing a pressed key) to allow keyboard controlled movement. Registers arrow keys for movement. :param e: Event handler. :return: Nothing. """ if e.GetKeyCode() == wx.WXK_UP: self.move_up(None) elif e.GetKeyCode() == wx.WXK_DOWN: self.move_down(None) elif e.GetKeyCode() == wx.WXK_LEFT: self.move_left(None) elif e.GetKeyCode() == wx.WXK_RIGHT: self.move_right(None) else: e.Skip() def update_settings(self, e): """ Handles automatic X and Y grid step distance edits. Called when [Enter] is pressed or when the user clicks on any element/widget of the GUI. :param e: Event handler. :return: Nothing. """ try: xval = float(self.x_tctrl.GetValue()) yval = float(self.y_tctrl.GetValue()) if self.distx == xval and self.disty == yval: return self.distx = xval self.disty = yval except ValueError: print("Invalid distance values.\nPlease input numeric values.") self.x_tctrl = float(self.distx) self.y_tctrl = float(self.disty) return self.stepx = int(self.distx / self.motor.step_unit) self.stepy = int(self.disty / self.motor.step_unit) self.fracx = self.distx / self.motor.step_unit - self.stepx self.fracy = self.disty / self.motor.step_unit - self.stepy print("New step distances: X =", self.distx, "Y =", self.disty) def OnClose(self, e): """ Exit script for the GUI, called when the window is closed. Notifies the user about exiting the manual movement module, destorys the motor object, and destroys the GUI object. :param e: Event handler. :return: Nothing. """ print("Exiting Manual Movement module.") self.motor.destroy() self.Destroy()