From c7264ded3117d673484232b32888f432b2d33e2f Mon Sep 17 00:00:00 2001 From: Kienan Stewart Date: Sun, 4 Jan 2015 12:58:58 -0500 Subject: [PATCH] Reference profile implemented (no editing, or clearing except when data is cleared). Added an example reference profile --- example_reference_profile.csv | 5 ++ main.kv | 71 +++++++++++++++++++++++--- main.py | 93 ++++++++++++++++++++++++++++++++--- 3 files changed, 155 insertions(+), 14 deletions(-) create mode 100644 example_reference_profile.csv diff --git a/example_reference_profile.csv b/example_reference_profile.csv new file mode 100644 index 0000000..2dc87c5 --- /dev/null +++ b/example_reference_profile.csv @@ -0,0 +1,5 @@ +0,25 +120,67 +3720,67 +3840,76.67 +4740,76.66 diff --git a/main.kv b/main.kv index b550186..b470d1d 100644 --- a/main.kv +++ b/main.kv @@ -63,6 +63,26 @@ text: 'Set Output File' on_press: root.set_output(filechooser.path, text_input.text) +: + BoxLayout: + orientation: 'vertical' + Label: + text: 'Select a reference temperature profile (csv)' + size_hint_y: 0.1 + FileChooserListView: + size_hint_y: 0.8 + id: filechooser + filters: ['*.csv'] + BoxLayout: + size_hiny_y: 0.1 + orientation: 'horizontal' + Button: + text: 'Cancel' + on_press: root.cancel() + Button: + text: 'Set reference profile' + on_press: root.set_output(file = filechooser.selection) + : label_wid: "Temperature Monitor" current_temperature: current_temperature @@ -76,6 +96,8 @@ image_output_file: '' on_raw_data_output_file: mainplot.raw_data_output_file = self.raw_data_output_file on_image_output_file: mainplot.image_output_file = self.image_output_file + reference_profile_file: '' + on_reference_profile_file: mainplot.reference_profile_file = self.reference_profile_file BoxLayout: orientation: 'vertical' BoxLayout: @@ -93,23 +115,60 @@ on_state: root.set_state(self.state) Button: id: startstop_button - text: 'Pause' + text: 'Pause Data' on_press: startstop_widget.change_state() Button: id: clear_button - text: 'Clear' + text: 'Clear Graph' on_press: root.initiate_clear_dialog() - Button: - id: output_button - text: 'No File Chosen' - on_press: root.choose_output_file() SerialPortButton: id: serial_chooser_button on_serial_port_changed: root.serial_port_changed(self.text) + BoxLayout: + orientation: 'horizontal' + size_hint_y: 0.1 + BoxLayout: + orientation: 'vertical' + BoxLayout: + orientation: 'horizontal' + Label: + text: 'Output file' + size_hint_x: 0.3 + Button: + id: output_button + text: 'Choose output file' + on_press: root.choose_output_file() + Label: + id: output_file_selected + text: 'No file chosen' + BoxLayout: + orientation: 'vertical' + BoxLayout: + orientation: 'horizontal' + Label: + text: 'Reference Profile' + Button: + id: reference_profile_select + text: 'Choose Profile' + on_press: root.select_reference_profile() + size_hint_x: 0.5 + Button: + id: reference_profile_edit + text: 'Edit' + size_hint_x: 0.2 + Button: + id: reference_profile_clear + text: 'Clear' + size_hint_x: 0.2 + Label: + id: reference_profile_selected + text: 'No profile selected' PlotWidget: id: mainplot + reference_profile_file: '' on_image_output_file: self.update_image_output_file() on_raw_data_output_file: self.update_raw_data_output_file() + on_reference_profile_file: root.reference_profile_file = self.reference_profile_file size_hint_y: 0.8 StatusBar: size_hint_y: 0.1 diff --git a/main.py b/main.py index b16adf1..9d59451 100644 --- a/main.py +++ b/main.py @@ -67,6 +67,7 @@ class MainWindow(FloatLayout): lastStatus = DictProperty({}) image_output_file = StringProperty('') raw_data_output_file = StringProperty('') + reference_profile_file = StringProperty('') def __init__(self, **kwargs): super(MainWindow, self).__init__(**kwargs) @@ -176,8 +177,7 @@ class MainWindow(FloatLayout): Logger.debug('Choose Output File pressed') output_file_dialog = OutputFileDialog(cancel = self.dismiss_popup, set_output_file = self.set_output_file) - self._popup = Popup(title="Choose outputfile", content = output_file_dialog) - self._popup.open() + self.create_popup(title="Choose outputfile", content = output_file_dialog) def set_output_file(self, path, file_name, *args, **kwargs): @@ -199,7 +199,7 @@ class MainWindow(FloatLayout): self.image_output_file = files['image_file'] self.dismiss_popup() else: - # UI Feedback in the popup dialog + # @TODO UI Feedback in the popup dialog Logger.debug('MainWindow: Set output file errors: ' + str(errors)) @@ -219,6 +219,11 @@ class MainWindow(FloatLayout): return errors + def create_popup(self, *args, **kwargs): + self._popup = Popup(*args, **kwargs) + self._popup.open() + + def dismiss_popup(self, *args, **kwargs): self._popup.dismiss() @@ -232,9 +237,35 @@ class MainWindow(FloatLayout): if self.raw_data_output_file: root = self.raw_data_output_file.rsplit('.', 1) Logger.debug('MainWindow: ' + str(root)) - self.ids.output_button.text = root[0] + '[.csv|.png]' + self.ids.output_file_selected.text = root[0] + '[.csv|.png]' else: - self.ids.output_button.text = 'No File Chosen' + self.ids.output_file_selected.text = 'No file Chosen' + + + def select_reference_profile(self, *args, **kwargs): + dialog = SelectReferenceProfileDialog(output = self.set_reference_profile, + cancel = self.dismiss_popup) + self.create_popup(title='Reference Profile Selection', + content = dialog) + + + def set_reference_profile(self, *args, **kwargs): + Logger.debug('MainWindow: reference profile kwargs ' + str(kwargs)) + ref_file = '' + if kwargs['file']: + ref_file = kwargs['file'][0] + if not os.path.isfile(ref_file): + # Not a valid path/file + return + self.reference_profile_file = ref_file + self.dismiss_popup() + + + def on_reference_profile_file(self, *kargs, **kwargs): + if not self.reference_profile_file: + self.ids.reference_profile_selected.text = 'No profile selected' + else: + self.ids.reference_profile_selected.text = self.reference_profile_file class OutputFileDialog(FloatLayout): @@ -253,6 +284,22 @@ class OutputFileDialog(FloatLayout): self.set_output(*args, **kwargs) +class SelectReferenceProfileDialog(FloatLayout): + + def __init__(self, *args, **kwargs): + super(SelectReferenceProfileDialog, self).__init__(*args, **kwargs) + self.cancel = kwargs['cancel'] + self.output = kwargs['output'] + + + def cancel(self, *args, **kwargs): + self.cancel(*args, **kwargs) + + + def set_output(self, *args, **kwargs): + self.output(*args, **kwargs) + + class SerialPortButton(Spinner): __events__ = ('on_serial_port_changed',) @@ -318,6 +365,7 @@ class PlotWidget(Image): image_output_file = StringProperty('') raw_data_output_file = StringProperty('') + reference_profile_file = StringProperty('') def __init__(self, **kwargs): super(PlotWidget, self).__init__(**kwargs) @@ -332,11 +380,16 @@ class PlotWidget(Image): self.plot_axes.set_title('Recorded Temperature') self.image_data = None self._image_raw_data = None + self.reference_profile = None def clear_data(self): self.data = numpy.array([], dtype=float); + self.reference_profile_file = '' + self.reference_profile = None self.texture = None + self.image_output_file = '' + self.raw_data_output_file = '' def do_update(self): @@ -373,9 +426,21 @@ class PlotWidget(Image): #Logger.debug('transpoed data: ' + str(data)) #Logger.debug('transposed data shape: ' + str(data.shape)) t, temperature = numpy.split(data, 2, axis = 0) - #Logger.debug('time: ' + str(t[0])) - #Logger.debug('temperature: ' + str(temperature[0])) - self.plot_axes.plot(t[0], temperature[0]) + reference_data = None + if self.reference_profile is not None and self.reference_profile.any(): + reference_data = numpy.copy(self.reference_profile) + reference_data = reference_data.transpose() + t2, reference_temperature = numpy.split(reference_data, 2, axis = 0) + # Add t[0] to all reference points to make it fit on the current graph + t2 = numpy.add(t2, t[0][0]) + #Logger.debug('PlotWidget: reference profile t: ' + str(t2)) + #Logger.debug('PlotWidget: reference profile temp: ' + str(reference_temperature)) + #Logger.debug('PlotWidget: time: ' + str(t[0])) + #Logger.debug('PlotWidget: temperature: ' + str(temperature[0])) + if reference_data is not None and reference_data.any(): + self.plot_axes.plot(t[0], temperature[0], 'b', t2[0], reference_temperature[0], 'r') + else: + self.plot_axes.plot(t[0], temperature[0], 'b') image_data = StringIO.StringIO() self.figure.savefig(image_data, format = 'png') image_data.seek(0) @@ -419,6 +484,18 @@ class PlotWidget(Image): self.do_update() + def on_reference_profile_file(self, *args, **kwargs): + Logger.debug('PlotWidget: on_reference_profile_file ' + str(self.reference_profile_file)) + self.load_reference_profile() + + + def load_reference_profile(self): + if not self.reference_profile_file: + return + self.reference_profile = numpy.loadtxt(self.reference_profile_file, + delimiter=',') + Logger.debug('PlotWidget: reference_profile: ' + str(self.reference_profile)) + class YesNoModalView(Popup): def process(self, result, *args, **kwargs):