diff --git a/dstatInterface/dstatInterface.xcodeproj/project.pbxproj b/dstatInterface/dstatInterface.xcodeproj/project.pbxproj index 6371382929b9f627d60a7074a43dc02e99d5e76e..9fedcac4413bba0fbe1c6486ab4392a7aae472e0 100644 --- a/dstatInterface/dstatInterface.xcodeproj/project.pbxproj +++ b/dstatInterface/dstatInterface.xcodeproj/project.pbxproj @@ -7,7 +7,9 @@ objects = { /* Begin PBXFileReference section */ + 5F05410F1994220800185C41 /* build_windows.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = build_windows.py; sourceTree = "<group>"; }; 5F87883C19072E86007B53E0 /* mpltest.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = mpltest.py; sourceTree = "<group>"; }; + 5FB0B8E1198ACD4B00FA6CB7 /* microdrop.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = microdrop.py; sourceTree = "<group>"; }; 5FCB541B190591CD00CEB148 /* interface */ = {isa = PBXFileReference; lastKnownFileType = folder; path = interface; sourceTree = "<group>"; }; 5FCB541D1905923800CEB148 /* interface_test.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = interface_test.py; sourceTree = "<group>"; }; 5FCB54231905B6EE00CEB148 /* dstat_comm.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = dstat_comm.py; sourceTree = "<group>"; }; @@ -22,7 +24,9 @@ children = ( 5FF00FDC1942BD16004D38A8 /* setup.py */, 5F87883C19072E86007B53E0 /* mpltest.py */, + 5F05410F1994220800185C41 /* build_windows.py */, 5FCB541D1905923800CEB148 /* interface_test.py */, + 5FB0B8E1198ACD4B00FA6CB7 /* microdrop.py */, 5FCB54231905B6EE00CEB148 /* dstat_comm.py */, 5FCB541B190591CD00CEB148 /* interface */, 5FDC0DFD18FDAD79003F857A /* mpl.py */, diff --git a/dstatInterface/interface/dstatInterface.glade b/dstatInterface/interface/dstatInterface.glade deleted file mode 100644 index ba074302e10d9eefd38816f915f25d55a3aa2287..0000000000000000000000000000000000000000 --- a/dstatInterface/interface/dstatInterface.glade +++ /dev/null @@ -1,651 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<interface> - <requires lib="gtk+" version="2.24"/> - <!-- interface-naming-policy project-wide --> - <object class="GtkListStore" id="ExpComboListStore"> - <columns> - <!-- column-name index --> - <column type="guint"/> - <!-- column-name name --> - <column type="gchararray"/> - </columns> - <data> - <row> - <col id="0">0</col> - <col id="1" translatable="yes">Chronoamperometry</col> - </row> - <row> - <col id="0">1</col> - <col id="1" translatable="yes">Linear Sweep Voltammetry</col> - </row> - <row> - <col id="0">2</col> - <col id="1" translatable="yes">Cyclic Voltammetry</col> - </row> - <row> - <col id="0">3</col> - <col id="1" translatable="yes">Square Wave Voltammetry</col> - </row> - <row> - <col id="0">4</col> - <col id="1" translatable="yes">Differential Pulse Voltammetry</col> - </row> - <row> - <col id="0">5</col> - <col id="1" translatable="yes">AC Voltammetry</col> - </row> - <row> - <col id="0">6</col> - <col id="1" translatable="yes">Photodiode</col> - </row> - </data> - </object> - <object class="GtkAboutDialog" id="aboutdialog1"> - <property name="can_focus">False</property> - <property name="border_width">5</property> - <property name="type_hint">dialog</property> - <property name="program_name">Dstat Interface</property> - <property name="version">0.1</property> - <property name="copyright" translatable="yes">© Michael Dryden 2014</property> - <property name="license" translatable="yes">GNU</property> - <property name="authors">Michael Dryden</property> - <child internal-child="vbox"> - <object class="GtkVBox" id="dialog-vbox1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">2</property> - <child internal-child="action_area"> - <object class="GtkHButtonBox" id="dialog-action_area1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="layout_style">end</property> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <placeholder/> - </child> - </object> - </child> - </object> - <object class="GtkTextBuffer" id="databuffer1"/> - <object class="GtkTextBuffer" id="databuffer2"/> - <object class="GtkImage" id="image1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="yalign">0.47999998927116394</property> - <property name="stock">gtk-missing-image</property> - </object> - <object class="GtkImage" id="image2"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="stock">gtk-save-as</property> - </object> - <object class="GtkListStore" id="serial_liststore"> - <columns> - <!-- column-name serial --> - <column type="gchararray"/> - </columns> - </object> - <object class="GtkAdjustment" id="updatesamples_adj"> - <property name="upper">100</property> - <property name="value">5</property> - <property name="step_increment">1</property> - <property name="page_increment">10</property> - </object> - <object class="GtkWindow" id="window1"> - <property name="can_focus">False</property> - <property name="border_width">6</property> - <property name="title" translatable="yes">Main</property> - <property name="default_width">1200</property> - <property name="default_height">800</property> - <signal name="destroy" handler="on_window1_destroy" swapped="no"/> - <child> - <object class="GtkVBox" id="vbox1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkMenuBar" id="menubar1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkMenuItem" id="menuitem1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">_File</property> - <property name="use_underline">True</property> - <child type="submenu"> - <object class="GtkMenu" id="menu1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkImageMenuItem" id="gtk_new"> - <property name="label">gtk-new</property> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="use_underline">True</property> - <property name="use_stock">True</property> - </object> - </child> - <child> - <object class="GtkImageMenuItem" id="gtk-open"> - <property name="label">gtk-open</property> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="use_underline">True</property> - <property name="use_stock">True</property> - </object> - </child> - <child> - <object class="GtkImageMenuItem" id="file_save_exp"> - <property name="label">Save current data...</property> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="image">image2</property> - <property name="use_stock">False</property> - <signal name="activate" handler="on_file_save_exp_activate" swapped="no"/> - </object> - </child> - <child> - <object class="GtkImageMenuItem" id="gtk-save-as"> - <property name="label">gtk-save-as</property> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="use_underline">True</property> - <property name="use_stock">True</property> - </object> - </child> - <child> - <object class="GtkImageMenuItem" id="gtk_quit"> - <property name="label">gtk-quit</property> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="use_underline">True</property> - <property name="use_stock">True</property> - <signal name="activate" handler="on_gtk_quit_activate" swapped="no"/> - </object> - </child> - </object> - </child> - </object> - </child> - <child> - <object class="GtkMenuItem" id="menuitem2"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">_Edit</property> - <property name="use_underline">True</property> - <child type="submenu"> - <object class="GtkMenu" id="menu2"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkImageMenuItem" id="imagemenuitem7"> - <property name="label">gtk-copy</property> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="use_underline">True</property> - <property name="use_stock">True</property> - </object> - </child> - <child> - <object class="GtkImageMenuItem" id="imagemenuitem8"> - <property name="label">gtk-paste</property> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="use_underline">True</property> - <property name="use_stock">True</property> - </object> - </child> - </object> - </child> - </object> - </child> - <child> - <object class="GtkMenuItem" id="gtk_view"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">_View</property> - <property name="use_underline">True</property> - <child type="submenu"> - <object class="GtkMenu" id="menu5"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkImageMenuItem" id="push_status"> - <property name="label">Push Status</property> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="use_stock">False</property> - </object> - </child> - <child> - <object class="GtkImageMenuItem" id="pop_status"> - <property name="label">Pop Status</property> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="use_stock">False</property> - </object> - </child> - <child> - <object class="GtkImageMenuItem" id="clear_status"> - <property name="label">Clear Status</property> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="use_stock">False</property> - </object> - </child> - </object> - </child> - </object> - </child> - <child> - <object class="GtkMenuItem" id="menuitem4"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">_Help</property> - <property name="use_underline">True</property> - <child type="submenu"> - <object class="GtkMenu" id="menu3"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkImageMenuItem" id="gtk_about"> - <property name="label">gtk-about</property> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="use_underline">True</property> - <property name="use_stock">True</property> - <signal name="activate" handler="on_gtk_about_activate" swapped="no"/> - </object> - </child> - </object> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkHPaned" id="hpaned1"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="position">300</property> - <property name="position_set">True</property> - <child> - <object class="GtkVBox" id="vbox2"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkVBox" id="vbox3"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkHBox" id="gain_adc_box"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">2</property> - <child> - <placeholder/> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label7"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Experiment:</property> - <attributes> - <attribute name="weight" value="semibold"/> - </attributes> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="padding">10</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkComboBox" id="expcombobox"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="model">ExpComboListStore</property> - <signal name="changed" handler="on_expcombobox_changed" swapped="no"/> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">2</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkHBox" id="exp_section_box"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <placeholder/> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkHBox" id="hbox1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkButton" id="pot_start"> - <property name="label">gtk-execute</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="use_stock">True</property> - <signal name="clicked" handler="on_pot_start_clicked" swapped="no"/> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkButton" id="pot_stop"> - <property name="label">gtk-stop</property> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="use_stock">True</property> - <signal name="clicked" handler="on_pot_stop_clicked" swapped="no"/> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkSpinner" id="spinner"> - <property name="visible">True</property> - <property name="can_focus">False</property> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">2</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="padding">5</property> - <property name="position">2</property> - </packing> - </child> - </object> - <packing> - <property name="resize">False</property> - <property name="shrink">True</property> - </packing> - </child> - <child> - <object class="GtkNotebook" id="notebook1"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <child> - <object class="GtkVBox" id="vbox4"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkHBox" id="hbox3"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkCheckButton" id="plotinteractive_checkbutton"> - <property name="label" translatable="yes">Plot updates during measurement</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="draw_indicator">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkSpinButton" id="samples_spinbutton"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="invisible_char">â—</property> - <property name="truncate_multiline">True</property> - <property name="primary_icon_activatable">False</property> - <property name="secondary_icon_activatable">False</property> - <property name="primary_icon_sensitive">True</property> - <property name="secondary_icon_sensitive">True</property> - <property name="adjustment">updatesamples_adj</property> - <property name="snap_to_ticks">True</property> - <property name="numeric">True</property> - <property name="update_policy">if-valid</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="padding">5</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">samples per update</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="padding">5</property> - <property name="position">2</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label4"> - <property name="visible">True</property> - <property name="can_focus">False</property> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">3</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkHBox" id="plotbox"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <placeholder/> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - </child> - <child type="tab"> - <object class="GtkLabel" id="label2"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Plot</property> - </object> - <packing> - <property name="tab_fill">False</property> - </packing> - </child> - <child> - <object class="GtkScrolledWindow" id="scrolledwindow1"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hscrollbar_policy">automatic</property> - <property name="vscrollbar_policy">automatic</property> - <child> - <object class="GtkTextView" id="datatextview1"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">False</property> - <property name="left_margin">10</property> - <property name="right_margin">10</property> - <property name="buffer">databuffer1</property> - </object> - </child> - </object> - <packing> - <property name="position">1</property> - </packing> - </child> - <child type="tab"> - <object class="GtkLabel" id="label3"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Raw Data</property> - </object> - <packing> - <property name="position">1</property> - <property name="tab_fill">False</property> - </packing> - </child> - <child> - <object class="GtkScrolledWindow" id="scrolledwindow2"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hscrollbar_policy">automatic</property> - <property name="vscrollbar_policy">automatic</property> - <child> - <object class="GtkTextView" id="datatextview2"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">False</property> - <property name="left_margin">10</property> - <property name="right_margin">10</property> - <property name="buffer">databuffer2</property> - </object> - </child> - </object> - <packing> - <property name="position">2</property> - </packing> - </child> - <child type="tab"> - <object class="GtkLabel" id="label5"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Extra Data</property> - </object> - <packing> - <property name="position">2</property> - <property name="tab_fill">False</property> - </packing> - </child> - </object> - <packing> - <property name="resize">True</property> - <property name="shrink">True</property> - </packing> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkHBox" id="hbox2"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkComboBox" id="serial_combobox"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="model">serial_liststore</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkButton" id="serial_refresh"> - <property name="label">gtk-refresh</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="use_stock">True</property> - <signal name="clicked" handler="on_serial_refresh_clicked" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkStatusbar" id="statusbar"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">2</property> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">2</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">2</property> - </packing> - </child> - </object> - </child> - </object> -</interface> diff --git a/dstatInterface/interface/dstatinterface.glade b/dstatInterface/interface/dstatinterface.glade index ba074302e10d9eefd38816f915f25d55a3aa2287..6b1062a172816a5543303c918182dd7edbdf0d5a 100644 --- a/dstatInterface/interface/dstatinterface.glade +++ b/dstatInterface/interface/dstatinterface.glade @@ -85,18 +85,17 @@ <property name="can_focus">False</property> <property name="stock">gtk-save-as</property> </object> + <object class="GtkImage" id="image3"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="stock">gtk-save</property> + </object> <object class="GtkListStore" id="serial_liststore"> <columns> <!-- column-name serial --> <column type="gchararray"/> </columns> </object> - <object class="GtkAdjustment" id="updatesamples_adj"> - <property name="upper">100</property> - <property name="value">5</property> - <property name="step_increment">1</property> - <property name="page_increment">10</property> - </object> <object class="GtkWindow" id="window1"> <property name="can_focus">False</property> <property name="border_width">6</property> @@ -151,12 +150,13 @@ </object> </child> <child> - <object class="GtkImageMenuItem" id="gtk-save-as"> - <property name="label">gtk-save-as</property> + <object class="GtkImageMenuItem" id="file_save_plot"> + <property name="label">Save Plot…</property> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="use_underline">True</property> - <property name="use_stock">True</property> + <property name="image">image3</property> + <property name="use_stock">False</property> + <signal name="activate" handler="on_file_save_plot_activate" swapped="no"/> </object> </child> <child> @@ -174,31 +174,32 @@ </object> </child> <child> - <object class="GtkMenuItem" id="menuitem2"> + <object class="GtkMenuItem" id="menu_dropbot"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="label" translatable="yes">_Edit</property> + <property name="label" translatable="yes">Dropbot</property> <property name="use_underline">True</property> <child type="submenu"> <object class="GtkMenu" id="menu2"> <property name="visible">True</property> <property name="can_focus">False</property> <child> - <object class="GtkImageMenuItem" id="imagemenuitem7"> - <property name="label">gtk-copy</property> + <object class="GtkImageMenuItem" id="menu_dropbot_connect"> + <property name="label">gtk-connect</property> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="use_underline">True</property> <property name="use_stock">True</property> + <signal name="activate" handler="on_menu_dropbot_connect_activate" swapped="no"/> </object> </child> <child> - <object class="GtkImageMenuItem" id="imagemenuitem8"> - <property name="label">gtk-paste</property> + <object class="GtkImageMenuItem" id="menu_dropbot_disconnect"> + <property name="label">gtk-disconnect</property> <property name="visible">True</property> + <property name="sensitive">False</property> <property name="can_focus">False</property> - <property name="use_underline">True</property> <property name="use_stock">True</property> + <signal name="activate" handler="on_menu_dropbot_disconnect_activate" swapped="no"/> </object> </child> </object> @@ -426,8 +427,8 @@ <property name="visible">True</property> <property name="can_focus">False</property> <child> - <object class="GtkCheckButton" id="plotinteractive_checkbutton"> - <property name="label" translatable="yes">Plot updates during measurement</property> + <object class="GtkCheckButton" id="autosave_checkbutton"> + <property name="label" translatable="yes">Autosave</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">False</property> @@ -440,51 +441,41 @@ </packing> </child> <child> - <object class="GtkSpinButton" id="samples_spinbutton"> + <object class="GtkFileChooserButton" id="autosavedir_button"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="invisible_char">â—</property> - <property name="truncate_multiline">True</property> - <property name="primary_icon_activatable">False</property> - <property name="secondary_icon_activatable">False</property> - <property name="primary_icon_sensitive">True</property> - <property name="secondary_icon_sensitive">True</property> - <property name="adjustment">updatesamples_adj</property> - <property name="snap_to_ticks">True</property> - <property name="numeric">True</property> - <property name="update_policy">if-valid</property> + <property name="can_focus">False</property> + <property name="action">select-folder</property> + <property name="preview_widget_active">False</property> + <property name="title" translatable="yes">Select a Save Folder</property> </object> <packing> - <property name="expand">False</property> + <property name="expand">True</property> <property name="fill">True</property> - <property name="padding">5</property> <property name="position">1</property> </packing> </child> <child> - <object class="GtkLabel" id="label1"> + <object class="GtkEntry" id="autosavename"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">samples per update</property> + <property name="can_focus">True</property> + <property name="has_tooltip">True</property> + <property name="max_length">32</property> + <property name="invisible_char">â—</property> + <property name="text" translatable="yes">file</property> + <property name="caps_lock_warning">False</property> + <property name="primary_icon_stock">gtk-file</property> + <property name="primary_icon_activatable">False</property> + <property name="secondary_icon_activatable">False</property> + <property name="primary_icon_sensitive">True</property> + <property name="secondary_icon_sensitive">True</property> + <property name="primary_icon_tooltip_text" translatable="yes">File name</property> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="padding">5</property> <property name="position">2</property> </packing> </child> - <child> - <object class="GtkLabel" id="label4"> - <property name="visible">True</property> - <property name="can_focus">False</property> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">3</property> - </packing> - </child> </object> <packing> <property name="expand">False</property> @@ -648,4 +639,10 @@ </object> </child> </object> + <object class="GtkAdjustment" id="updatesamples_adj"> + <property name="upper">100</property> + <property name="value">5</property> + <property name="step_increment">1</property> + <property name="page_increment">10</property> + </object> </interface> diff --git a/dstatInterface/interface/save.py b/dstatInterface/interface/save.py index 4789d408d2ab596dca851e6edbacf560a9c5722a..4456d08f27347a589ab654ea16eac6603d02f031 100644 --- a/dstatInterface/interface/save.py +++ b/dstatInterface/interface/save.py @@ -1,49 +1,154 @@ #!/usr/bin/env python +# -*- coding: utf-8 -*- -import gtk, io +import gtk, io, os import numpy as np +from datetime import datetime -class npSave: - def __init__(self, current_exp): - self.exp = current_exp - self.fcd = gtk.FileChooserDialog("Save...", None, gtk.FILE_CHOOSER_ACTION_SAVE, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK)) +def manSave(current_exp): + exp = current_exp + fcd = gtk.FileChooserDialog("Save...", None, gtk.FILE_CHOOSER_ACTION_SAVE, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK)) + + filters = [gtk.FileFilter()] + filters[0].set_name("NumPy binary (.npy)") + filters[0].add_pattern("*.npy") + filters.append(gtk.FileFilter()) + filters[1].set_name("Space separated text (.txt)") + filters[1].add_pattern("*.txt") + + fcd.set_do_overwrite_confirmation(True) + for i in filters: + fcd.add_filter(i) + + response = fcd.run() + + if response == gtk.RESPONSE_OK: + path = fcd.get_filename() + print "Selected filepath: %s" % path + filter_selection = fcd.get_filter().get_name() - self.filters = [gtk.FileFilter()] - self.filters[0].set_name("NumPy binary (.npy)") - self.filters[0].add_pattern("*.npy") - self.filters.append(gtk.FileFilter()) - self.filters[1].set_name("Space separated text (.txt)") - self.filters[1].add_pattern("*.txt") + if filter_selection.endswith("(.npy)"): + npy(exp, path) + elif filter_selection.endswith("(.txt)"): + text(exp, path) + fcd.destroy() - self.fcd.set_do_overwrite_confirmation(True) - for i in self.filters: - self.fcd.add_filter(i) - - self.response = self.fcd.run() + elif response == gtk.RESPONSE_CANCEL: + fcd.destroy() + +def plotSave(plot): + fcd = gtk.FileChooserDialog("Save Plot…", None, gtk.FILE_CHOOSER_ACTION_SAVE, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK)) + + filters = [gtk.FileFilter()] + filters[0].set_name("Portable Document Format (.pdf)") + filters[0].add_pattern("*.pdf") + filters.append(gtk.FileFilter()) + filters[1].set_name("Portable Network Graphics (.png)") + filters[1].add_pattern("*.png") + + fcd.set_do_overwrite_confirmation(True) + for i in filters: + fcd.add_filter(i) + + response = fcd.run() + + if response == gtk.RESPONSE_OK: + path = fcd.get_filename() + print "Selected filepath: %s" % path + filter_selection = fcd.get_filter().get_name() - if self.response == gtk.RESPONSE_OK: - self.path = self.fcd.get_filename() - print "Selected filepath: %s" % self.path - filter_selection = self.fcd.get_filter().get_name() - - if filter_selection.endswith("(.npy)"): - self.npy() - elif filter_selection.endswith("(.txt)"): - self.text() - self.fcd.destroy() - - def npy(self): - self.data = np.array(self.exp.data) - np.save(self.path, self.data()) - - def text(self): - if not self.path.endswith(".txt"): - self.path += ".txt" + if filter_selection.endswith("(.pdf)"): + if not path.endswith(".pdf"): + path += ".pdf" + + elif filter_selection.endswith("(.png)"): + if not path.endswith(".png"): + path += ".png" + + plot.figure.savefig(path) #savefig determines format from file extension + fcd.destroy() + + elif response == gtk.RESPONSE_CANCEL: + fcd.destroy() + +def autoSave(current_exp, dir_button, name, expnumber): + if name == "": + name = "file" + path = dir_button.get_filename() + path += '/' + path += name + path += str(expnumber) + + text(current_exp, path, auto=True) + +def autoPlot(plot, dir_button, name, expnumber): + if name == "": + name = "file" + + path = dir_button.get_filename() + path += '/' + path += name + path += str(expnumber) + + if path.endswith(".pdf"): + path = path.rstrip(".pdf") + + j = 1 + while os.path.exists("".join([path, ".pdf"])): + if j > 1: + path = path[:-len(str(j))] + path += str(j) + j += 1 + + path += ".pdf" + plot.figure.savefig(path) + + +def npy(exp, path, auto=False): + if path.endswith(".npy"): + path = path.rstrip(".npy") + + data = np.array(exp.data) + + if auto == True: + j = 1 + while os.path.exists("".join([path, ".npy"])): + if j > 1: + path = path[:-len(str(j))] + path += str(j) + j += 1 + + np.save(path, data) + +def text(exp, path, auto=False): + if path.endswith(".txt"): + path = path.rstrip(".txt") + + if auto == True: + j = 1 - self.data = np.array(self.exp.data) - header = "" - for i in self.exp.commands: - header += i - np.savetxt(self.path, self.data.transpose(), header=header, newline='\n') + while os.path.exists("".join([path, ".txt"])): + if j > 1: + path = path[:-len(str(j))] + path += str(j) + j += 1 + + path += ".txt" + file = open(path, 'w') + + time = datetime.now() + + data = np.array(exp.data) + header = "".join(['#', time.isoformat(), "\n#"]) + for i in exp.commands: + header += i + + file.write("".join([header, '\n'])) + for col in zip(*exp.data): + for row in col: + file.write(str(row)+ " ") + file.write('\n') + + file.close() diff --git a/dstatInterface/interface_test.py b/dstatInterface/interface_test.py index 49076362e437d45413fdcb753d9a5df97e33657e..abca328e397154c6b03f2ba4c5b572e8f2e954ec 100644 --- a/dstatInterface/interface_test.py +++ b/dstatInterface/interface_test.py @@ -1,4 +1,5 @@ #!/usr/bin/env python +# -*- coding: utf-8 -*- import sys try: @@ -34,6 +35,7 @@ import multiprocessing import time import mpltest +import microdrop class Error(Exception): pass @@ -76,10 +78,15 @@ class main: self.pd = pd.pd() self.error_context_id = self.statusbar.get_context_id("error") + self.message_context_id = self.statusbar.get_context_id("message") self.plotwindow = self.builder.get_object('plotbox') - self.plotint_checkbox = self.builder.get_object('plotinteractive_checkbutton') - self.updatelimit_adj = self.builder.get_object('updatesamples_adj') + + #setup autosave + self.autosave_checkbox = self.builder.get_object('autosave_checkbutton') + self.autosavedir_button = self.builder.get_object('autosavedir_button') + self.autosavename = self.builder.get_object('autosavename') + self.plot = mpltest.plotbox(self.plotwindow) #fill exp_section @@ -138,6 +145,13 @@ class main: self.acv_container.hide() self.pd_container.hide() + self.expnumber = 0 + + self.menu_dropbot_connect = self.builder.get_object('menu_dropbot_connect') + self.menu_dropbot_disconnect = self.builder.get_object('menu_dropbot_disconnect') + self.dropbot_enabled = False + self.dropbot_triggered = False + def exp_param_show(self, selection): self.chronoamp_container.hide() self.lsv_container.hide() @@ -190,6 +204,18 @@ class main: self.serial_liststore.append([i]) def on_pot_start_clicked(self, data=None): + + def exceptions(): #cleans up after errors + if self.dropbot_enabled == True: + if self.dropbot_triggered == True: + self.dropbot_triggered = False + print "finallydone" + self.microdrop.reply(microdrop.EXPFINISHED) + self.microdrop_proc = gobject.timeout_add(500, self.microdrop_listen) + self.spinner.stop() + self.startbutton.set_sensitive(True) + self.stopbutton.set_sensitive(False) + selection = self.expcombobox.get_active() parameters = {} view_parameters = {} @@ -207,9 +233,6 @@ class main: parameters['adc_pga'] = pga_model.get_value(self.adc_pot.pga_combobox.get_active_iter(), 2) parameters['gain'] = gain_model.get_value(self.adc_pot.gain_combobox.get_active_iter(), 2) - view_parameters['update'] = self.plotint_checkbox.get_active() - view_parameters['updatelimit'] = int(self.updatelimit_adj.get_value()) - self.line = 0 self.lastline = 0 self.lastdataline = 0 @@ -244,6 +267,7 @@ class main: self.plot_proc = gobject.timeout_add(200, self.experiment_running_plot) gobject.idle_add(self.experiment_running) + return elif selection == 1: #LSV parameters['clean_mV'] = int(self.lsv.clean_mV.get_text()) @@ -289,6 +313,7 @@ class main: self.plot_proc = gobject.timeout_add(200, self.experiment_running_plot) gobject.idle_add(self.experiment_running) + return elif selection == 2: #CV parameters['clean_mV'] = int(self.cv.clean_mV.get_text()) @@ -340,6 +365,7 @@ class main: self.plot_proc = gobject.timeout_add(200, self.experiment_running_plot) gobject.idle_add(self.experiment_running) + return elif selection == 3: #SWV parameters['clean_mV'] = int(self.swv.clean_mV.get_text()) @@ -398,6 +424,7 @@ class main: self.plot_proc = gobject.timeout_add(200, self.experiment_running_plot) gobject.idle_add(self.experiment_running) + return elif selection == 4: #DPV parameters['clean_mV'] = int(self.dpv.clean_mV.get_text()) @@ -454,35 +481,27 @@ class main: self.plot_proc = gobject.timeout_add(200, self.experiment_running_plot) gobject.idle_add(self.experiment_running) + return else: self.statusbar.push(self.error_context_id, "Experiment not yet implemented.") - self.startbutton.set_sensitive(True) - self.stopbutton.set_sensitive(False) + exceptions() except ValueError: - self.spinner.stop() self.statusbar.push(self.error_context_id, "Experiment parameters must be integers.") - self.startbutton.set_sensitive(True) - self.stopbutton.set_sensitive(False) + exceptions() except InputError as e: - self.spinner.stop() self.statusbar.push(self.error_context_id, e.msg) - self.startbutton.set_sensitive(True) - self.stopbutton.set_sensitive(False) + exceptions() except SerialException: - self.spinner.stop() self.statusbar.push(self.error_context_id, "Could not establish serial connection.") - self.startbutton.set_sensitive(True) - self.stopbutton.set_sensitive(False) + exceptions() except AssertionError as e: - self.spinner.stop() self.statusbar.push(self.error_context_id, str(e)) - self.startbutton.set_sensitive(True) - self.stopbutton.set_sensitive(False) + exceptions() def experiment_running(self): try: @@ -519,7 +538,7 @@ class main: def experiment_done(self): gobject.source_remove(self.plot_proc) #stop automatic plot update self.experiment_running_plot() #make sure all data updated on plot - + self.databuffer.set_text("") self.databuffer.place_cursor(self.databuffer.get_start_iter()) self.rawbuffer.insert_at_cursor("\n") @@ -528,16 +547,26 @@ class main: for col in zip(*self.current_exp.data): for row in col: - self.rawbuffer.insert_at_cursor(str(row)+ "\t") + self.rawbuffer.insert_at_cursor(str(row)+ " ") self.rawbuffer.insert_at_cursor("\n") - if self.current_exp.data_extra: for col in zip(*self.current_exp.data_extra): for row in col: - self.databuffer.insert_at_cursor(str(row)+ "\t") + self.databuffer.insert_at_cursor(str(row)+ " ") self.databuffer.insert_at_cursor("\n") + + if self.autosave_checkbox.get_active(): + save.autoSave(self.current_exp, self.autosavedir_button, self.autosavename.get_text(), self.expnumber) + save.autoPlot(self.plot, self.autosavedir_button, self.autosavename.get_text(), self.expnumber) + self.expnumber += 1 + if self.dropbot_enabled == True: + if self.dropbot_triggered == True: + self.dropbot_triggered = False + print "expdone" + self.microdrop.reply(microdrop.EXPFINISHED) + self.microdrop_proc = gobject.timeout_add(500, self.microdrop_listen) self.spinner.stop() self.startbutton.set_sensitive(True) @@ -550,7 +579,50 @@ class main: def on_file_save_exp_activate(self, menuitem, data=None): if self.current_exp: - self.save = save.npSave(self.current_exp) + save_inst = save.manSave(self.current_exp) + + def on_file_save_plot_activate(self, menuitem, data=None): + save_inst = save.plotSave(self.plot) + + def on_menu_dropbot_connect_activate(self, menuitem, data=None): + self.microdrop = microdrop.microdropConnection() + self.dropbot_enabled = True + self.menu_dropbot_connect.set_sensitive(False) + self.menu_dropbot_disconnect.set_sensitive(True) + self.statusbar.push(self.message_context_id, "Waiting for µDrop to connect…") + self.microdrop_proc = gobject.timeout_add(500, self.microdrop_listen) + + def on_menu_dropbot_disconnect_activate(self, menuitem, data= None): + gobject.source_remove(self.microdrop_proc) + self.microdrop.reset() + del self.microdrop + self.dropbot_enabled = False + self.menu_dropbot_connect.set_sensitive(True) + self.menu_dropbot_disconnect.set_sensitive(False) + + def microdrop_listen(self): + drdy, data = self.microdrop.listen() + if drdy == False: + return True + if self.microdrop.connected == False: + if data == microdrop.CONREQ: + print "INFO: µDrop connected" + self.statusbar.push(self.message_context_id, "µDrop connected.") + self.microdrop.reply(microdrop.CONREP) + self.microdrop.connected = True + else: + print "WAR: Invalid µDrop connection request." + self.microdrop.reply(microdrop.INVAL_CMD) + elif data == microdrop.STARTEXP: + self.dropbot_triggered = True + self.on_pot_start_clicked() + return False + else: + print "WAR: Received invalid command from µDrop" + self.microdrop.reply(microdrop.INVAL_CMD) + return True + + if __name__ == "__main__": diff --git a/dstatInterface/microdrop.py b/dstatInterface/microdrop.py new file mode 100644 index 0000000000000000000000000000000000000000..95ea34cbe86d9998730c12a9eb91151e23782028 --- /dev/null +++ b/dstatInterface/microdrop.py @@ -0,0 +1,51 @@ +import zmq +import zmq.error + +#signals +CONREQ = "0" +CONREP = "1" +STARTEXP = "10" +EXPFINISHED = "11" +INVAL_CMD = "99" + +#States +RECV = 0 +SEND = 1 + +class microdropConnection: + + def __init__(self, port=6789): + self.port = port + self.connected = False + self.state = RECV + + self.ctx = zmq.Context() + self.soc = zmq.Socket(self.ctx, zmq.REP) + self.soc.bind("".join(['tcp://*:',str(self.port)])) + + def listen(self): + if self.state == SEND: + print "WAR: Microdrop Connection state invalid, resetting..." + self.reset() + self.__init__(self.port) + try: + message = self.soc.recv(flags=zmq.NOBLOCK, copy=True) + self.state = SEND + return (True, message) + except zmq.Again: + return (False, "") + + def reply(self, data): + if self.state == RECV: + print "WAR: Microdrop Connection state invalid, resetting..." + self.reset() + self.__init__(self.port) + return False + self.state = RECV + self.soc.send(data) + return True + + def reset(self): + self.soc.unbind("".join(['tcp://*:',str(self.port)])) + del self.soc + del self.ctx