class AvionicsLogger(KRCCModule): def __init__(self, root): super().__init__() self.root = root self.exception = None self.list_string = StringVar() self.listbox = Listbox(root, listvariable=self.list_string, font='TkFixedFont', width=30) self.write_cache = '' self.logfile = None self.enable_logging = BooleanVar() self.enable_logging_checkbox = Checkbutton( root, var=self.enable_logging, text='Enable logging', command=self.enable_logging_changed) self.logfile_label = Label(root, text='Logfile name:') self.logfile_name = StringVar() self.logfile_name_entry = Entry(root, textvar=self.logfile_name) self.load() def write(self, string): if self.enable_logging.get() and self.logfile is None: if self.logfile_name.get() == '': self.logfile_name.set('logs/{}.log'.format(time.time())) self.logfile = io.open(self.logfile_name.get(), 'a') self.logfile.write(self.write_cache) self.write_cache = '' self.logfile.write(string) def cache(self, string): self.write_cache += string def enable_logging_changed(self): if not self.enable_logging.get(): self.logfile_name_entry.configure(state=NORMAL) if self.logfile is not None: self.logfile.close() self.logfile = None self.logfile_name.set('') else: self.logfile_name_entry.configure(state=DISABLED) def establish_connection_and_run(self): error = None dots = 0 connection = None while not self.terminate: try: if connection is None: connection = krpc.connect(name=self.name) self.run_with_connection(connection) error = None dots = 0 except Exception as e: if error != e.args[0]: error = e.args[0] print('\n') print(traceback.format_exc()) sys.stdout.write('Retrying') if dots > 80: dots = 0 sys.stdout.write('\n') sys.stdout.write('.') dots += 1 sys.stdout.flush() time.sleep(1) if connection is not None: connection.close() def run_with_connection(self, connection): logging.debug('KRPC connection established') vessel = connection.space_center.active_vessel ref = vessel.orbit.body.reference_frame flight = connection.add_stream(vessel.flight, ref) floats = [ 'mean_altitude', 'atmosphere_density', 'ballistic_coefficient', 'drag_coefficient', ] vectors = [ 'velocity', ] colon_pos_float = max([len(v) for v in floats]) colon_pos_vec = max([len(v) + 3 for v in vectors]) self.listbox.configure(width=max(colon_pos_float, colon_pos_vec) + 11) # Write the log file header. self.cache('time\t' + '\t'.join(floats) + '\t') s = '{}\t' + '\t'.join('{{}}[{}]'.format(x) for x in [0, 1, 2]) self.cache('\t'.join( s.format(*(v for _ in [0, 1, 2, 3])) for v in vectors)) self.cache('\n') log_sample_interval = 0.01 next_log_sample = time.time() while not self.terminate: values = [time.time()] strings = [] for name in floats: value = flight().__getattribute__(name) values.append(value) padding = colon_pos_float - len(name) + 9 format_string = '{{}}: {{:>{}.3f}}'.format(padding) strings.append(format_string.format(name, value)) for name in vectors: value = flight().__getattribute__(name) magnitude = value[0] padding = colon_pos_float - len(name) + 9 format_string = '{{}}: {{:>{}.3f}}'.format(padding) strings.append(format_string.format(name, magnitude)) values.append(magnitude) padding = colon_pos_vec - len(name) + 2 format_string = '{{}}[{{}}]: {{:>{}.3f}}'.format(padding) for i in [0, 1, 2]: values.append(value[i]) strings.append(format_string.format(name, i, value[i])) if self.enable_logging.get() and time.time() > next_log_sample: self.write('\t'.join(['{}'.format(v) for v in values]) + '\n') next_log_sample = time.time() + log_sample_interval self.list_string.set(tuple(strings)) def run(self): try: self.establish_connection_and_run() self.logfile_name_entry.destroy() self.logfile_label.destroy() self.enable_logging_checkbox.destroy() self.listbox.destroy() except RuntimeError: # Should only happen when KeyboardInterrupt is thrown in the MainThread. pass if self.logfile is not None: self.logfile.close() @property def name(self): return 'Avionics Logger' def load(self): self.listbox.pack(side=LEFT, fill=BOTH) self.logfile_label.pack(side=LEFT, anchor=NW) self.logfile_name_entry.pack(side=LEFT, anchor=NE, fill=X, expand=True) self.enable_logging_checkbox.pack(side=LEFT, anchor=NW)
class A_DWI: def __init__(self, container, frame, label='', text='', row=0, column=0): self.container = container self.is_b0 = BooleanVar(container.parent) self.is_dw = BooleanVar(container.parent) self.column = column self.direction = StringVar(container.parent) self.label_from = Label(frame, text='from') self.text_from = Entry(frame) self.text_from.insert(0, text) self.button_file_from = Button(frame, text='...', command=lambda:filenameDialog_text(self.text_from)) self.button_rm = Button(frame, text='remove', command=self.click_remove) self.radio_ap = Radiobutton(frame, text='AP', variable=self.direction, value='AP', command=self.set_direction) self.radio_pa = Radiobutton(frame, text='PA', variable=self.direction, value='PA', command=self.set_direction) self.label_to = Label(frame, text='to') self.text_to = Entry(frame) #self.text_to.insert(0, text) self.button_file_to = Button(frame, text='Gen', command=self.set_filename_to) self.check_b0 = Checkbutton(frame, text='B0', variable=self.is_b0) self.check_dw = Checkbutton(frame, text='DWI', variable=self.is_dw) self.button_up = Button(frame, text='up', width=3, command=self.click_up) self.button_dn = Button(frame, text='down', width=3, command=self.click_dn) self.row = -1 self.change_row(row) if text != '': self.set_appa() self.set_filename_to() def prefix(self): return self.container.parent.prefix() def set_direction(self): pass def get_dwi_filenames(self): ''' :return: [('from', 'to'), ('from', 'to')] ''' filename_from = self.text_from.get() filename_to = self.text_to.get() if self.is_dw.get(): rtn = [ [filename_from, filename_to] ] filename_b_from = filename_wo_ext(filename_from) filename_b_to = filename_wo_ext(filename_to) rtn.append( [filename_b_from+'.bval', filename_b_to+'.bval'] ) rtn.append( [filename_b_from+'.bvec', filename_b_to+'.bvec'] ) return rtn return [] def get_b0_filename(self): ''' :return: [('from', 'to')] ''' filename_from = self.text_from.get() filename_to = self.text_to.get() ext = extname(filename_to) if self.is_b0.get(): if self.is_dw.get(): filename_to = '%s_B0%s' % (filename_wo_ext(filename_to), ext) return [ [filename_from, filename_to] ] return [] def set_appa(self): filename_from = self.text_from.get() basename_from = os.path.basename(filename_from) basename_b_from = filename_wo_ext(basename_from) if 'pa' in basename_b_from.lower(): self.direction.set('PA') elif 'ap' in basename_b_from.lower(): self.direction.set('AP') else: pass def set_filename_to(self, middle=None): filename_from = self.text_from.get() basename_from = os.path.basename(filename_from) number = os.path.dirname(filename_from).split('/')[-1].split('_')[0] if number == '': number = str(self.row) else: try: int(number) except: number = str(self.row) ext = extname(basename_from) intermediate = self.direction.get() if intermediate == '': intermediate = 'DWI' if self.is_b0.get() and not self.is_dw.get(): intermediate += '_B0' self.text_to.delete(0, len(self.text_to.get())) self.text_to.insert(0, '%s%s_%s%s' % (self.prefix(), number, intermediate, ext)) def change_row(self, row): if self.row == row: return self.row = row i = 2*row j = self.column j += 0; self.button_up.grid(row=i, column=j) j += 1; self.label_from.grid(row=i, column=j) j += 1; self.text_from.grid(row=i, column=j, sticky=EW) j += 1; self.button_file_from.grid(row=i, column=j) j += 1; self.button_rm.grid(row=i, column=j) j += 1; self.radio_ap.grid(row=i, column=j) j += 1; self.radio_pa.grid(row=i, column=j) i += 1 j = 0 j += 0; self.button_dn.grid(row=i, column=j) j += 1; self.label_to.grid(row=i, column=j) j += 1; self.text_to.grid(row=i, column=j, sticky=EW) j += 1; self.button_file_to.grid(row=i, column=j) j += 1 j += 1; self.check_b0.grid(row=i, column=j) j += 1; self.check_dw.grid(row=i, column=j) def click_remove(self): self.container.remove(self.row) self.button_up.destroy() self.label_from.destroy() self.text_from.destroy() self.button_file_from.destroy() self.button_rm.destroy() self.radio_ap.destroy() self.radio_pa.destroy() self.button_dn.destroy() self.label_to.destroy() self.text_to.destroy() self.button_file_to.destroy() self.check_b0.destroy() self.check_dw.destroy() def click_up(self): self.container.up(self.row) def click_dn(self): self.container.dn(self.row)