Skip to content
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# DStat Interface - An interface for the open hardware DStat potentiostat
# Copyright (C) 2014 Michael D. M. Dryden -
# Wheeler Microfluidics Laboratory <http://microfluidics.utoronto.ca>
#
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
class Error(Exception):
"""Copies Exception class"""
pass
class InputError(Error):
"""Exception raised for errors in the input. Extends Error class.
Attributes:
expr -- input expression in which the error occurred
msg -- error message
"""
def __init__(self, expr, msg):
self.expr = expr
self.msg = msg
class VarError(Error):
"""Exception raised for internal variable errors. Extends Error class.
Attributes:
var -- var in which the error occurred
msg -- error message
"""
def __init__(self, var, msg):
self.var = var
self.msg = msg
\ No newline at end of file
# __all__ = []
#
# import pkgutil
# import inspect
# from . import cal, chronoamp, cv
#
#
# for loader, name, is_pkg in pkgutil.walk_packages(__path__):
# print loader, name, is_pkg
# module = loader.find_module(name).load_module(name)
#
# for name, value in inspect.getmembers(module):
# if name.startswith('__'):
# continue
#
# globals()[name] = value
# __all__.append(name)
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# DStat Interface - An interface for the open hardware DStat potentiostat
# Copyright (C) 2017 Michael D. M. Dryden -
# Wheeler Microfluidics Laboratory <http://microfluidics.utoronto.ca>
#
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import time
import struct
import logging
logger = logging.getLogger(__name__)
import serial
from ..errors import InputError, VarError
from ..dstat import state
from ..experiments.experiment_template import Experiment, dstat_logger
def measure_offset(time):
gain_trim_table = [None, 'r100_trim', 'r3k_trim', 'r30k_trim', 'r300k_trim',
'r3M_trim', 'r30M_trim', 'r100M_trim']
parameters = {}
parameters['time'] = time
gain_offset = {}
for i in range(1,8):
parameters['gain'] = i
state.ser.start_exp(CALExp(parameters))
logger.info("measure_offset: %s", state.ser.get_proc(block=True))
gain_offset[gain_trim_table[i]] = state.ser.get_data(block=True)
return gain_offset
class CALExp(Experiment):
id = 'cal'
"""Offset calibration experiment"""
def __init__(self, parameters):
self.parameters = parameters
self.databytes = 8
self.scan = 0
self.data = []
self.commands = ["EA2 3 1 ", "EG"]
self.commands[1] += str(self.parameters['gain'])
self.commands[1] += " "
self.commands[1] += "0 "
self.commands.append(
("ER1 0", ["32768", str(self.parameters['time'])])
)
def serial_handler(self):
"""Handles incoming serial transmissions from DStat. Returns False
if stop button pressed and sends abort signal to instrument. Sends
data to self.data_pipe as result of self.data_handler).
"""
try:
while True:
if self.ctrl_pipe.poll():
input = self.ctrl_pipe.recv()
logger.debug("serial_handler: %s", input)
if input == ('a' or "DISCONNECT"):
self.serial.write('a')
logger.info("serial_handler: ABORT pressed!")
return False
for line in self.serial:
if self.ctrl_pipe.poll():
if self.ctrl_pipe.recv() == 'a':
self.serial.write('a')
logger.info("serial_handler: ABORT pressed!")
return False
if line.startswith('B'):
self.data.append(self.data_handler(
self.serial.read(size=self.databytes)))
elif line.lstrip().startswith("#"):
dstat_logger.info(line.lstrip().rstrip())
elif line.lstrip().startswith("@DONE"):
dstat_logger.debug(line.lstrip().rstrip())
self.serial.flushInput()
self.experiment_done()
return True
except serial.SerialException:
return False
def data_handler(self, data):
"""Takes data_input as tuple -- (scan, data).
Returns:
current
"""
seconds, milliseconds, current = struct.unpack('<HHl', data)
return current
def experiment_done(self):
"""Averages data points
"""
try:
sum = 0
self.data[0] = 0 # Skip first point
except IndexError:
return
for i in self.data:
sum += i
sum /= len(self.data)
if (sum > 32767):
sum = 32767
elif (sum < -32768):
sum = -32768
self.data_pipe.send(sum)
\ No newline at end of file
import time
import struct
import numpy as np
import serial
from ..interface.plot import mean, plotSpectrum, findBounds
from .experiment_template import PlotBox, Experiment, exp_logger
class ChronoampBox(PlotBox):
def setup(self):
self.plot_format = {
'current_time': {'xlabel': "Time (s)",
'ylabel': "Current (A)"
}
}
def format_plots(self):
"""
Creates and formats subplots needed. Overrides superclass.
"""
self.subplots = {'current_time': self.figure.add_subplot(111)}
for key, subplot in self.subplots.items():
subplot.ticklabel_format(style='sci', scilimits=(0, 3),
useOffset=False, axis='y')
subplot.plot([],[])
subplot.set_xlabel(self.plot_format[key]['xlabel'])
subplot.set_ylabel(self.plot_format[key]['ylabel'])
class Chronoamp(Experiment):
id = 'cae'
"""Chronoamperometry experiment"""
def setup(self):
self.datatype = "linearData"
self.datalength = 2
self.databytes = 8
self.data = {'current_time' : [([],[])]}
self.columns = ['Time (s)', 'Current (A)']
self.total_time = sum(self.parameters['time'])
self.plotlims = {'current_time': {'xlims': (0, self.total_time)}
}
self.commands.append(
("ER" + str(len(self.parameters['potential'])) + " 0 ", [])
)
for i in self.parameters['potential']:
self.commands[-1][1].append(str(int(i*(65536./3000)+32768)))
for i in self.parameters['time']:
self.commands[-1][1].append(str(i))
plot = ChronoampBox(['current_time'])
plot.setlims('current_time', **self.plotlims['current_time'])
self.plots.append(plot)
def data_handler(self, data_input):
"""Overrides Experiment method to not convert x axis to mV."""
scan, data = data_input
# 2*uint16 + int32
seconds, milliseconds, current = struct.unpack('<HHl', data)
return (scan, (
seconds+milliseconds/1000.,
(current+self.gain_trim)*(1.5/self.gain/8388607)
)
)
def store_data(self, incoming, newline):
"""Stores data in data attribute. Should not be called from subprocess.
Can be overriden for custom experiments."""
line, data = incoming
if newline is True:
self.data['current_time'].append(deepcopy(self.line_data))
for i, item in enumerate(self.data['current_time'][line]):
item.append(data[i])
def get_progress(self):
try:
return self.data['current_time'][-1][0][-1]/self.total_time
except IndexError:
return 0
class PDExp(Chronoamp):
"""Photodiode/PMT experiment"""
id = 'pde'
def setup(self):
self.plots.append(ChronoampBox('current_time'))
self.datatype = "linearData"
self.datalength = 2
self.databytes = 8
self.data = {'current_time' : [([],[])]}
self.columns = ['Time (s)', 'Current (A)']
self.plot_format = {
'current_time' : {
'labels' : self.columns,
'xlims' : (0, int(self.parameters['time']))
}
}
self.total_time = int(self.parameters['time'])
if self.parameters['shutter_true']:
if self.parameters['sync_true']:
self.commands.append("EZ")
self.commands[-1] += str(self.parameters['sync_freq'])
self.commands[-1] += " "
else:
self.commands.append(("E2", []))
command = "ER1 "
params = []
if self.parameters['interlock_true']:
command += "1 "
else:
command += "0 "
if self.parameters['voltage'] == 0: # Special case where V=0
params.append("65535")
else:
params.append(str(int(
65535-(self.parameters['voltage']*(65536./3000))))
)
params.append(str(self.parameters['time']))
self.commands.append((command, params))
if self.parameters['shutter_true']:
if self.parameters['sync_true']:
self.commands.append("Ez")
else:
self.commands.append("E1")
class FT_Box(PlotBox):
def updateline(self, Experiment, line_number):
def search_value(data, target):
for i in range(len(data)):
if data[i] > target:
return i
y = Experiment.data['data'][line_number][1]
x = Experiment.data['data'][line_number][0]
freq = Experiment.parameters['adc_rate_hz']
i = search_value(x, float(Experiment.parameters['fft_start']))
y1 = y[i:]
x1 = x[i:]
avg = mean(y1)
min_index, max_index = findBounds(y1)
y1[min_index] = avg
y1[max_index] = avg
f, Y = plotSpectrum(y1[min_index:max_index],freq)
self.axe1.lines[line_number].set_ydata(Y)
self.axe1.lines[line_number].set_xdata(f)
Experiment.data['ft'] = [(f, Y)]
def changetype(self, Experiment):
"""Change plot type. Set axis labels and x bounds to those stored
in the Experiment instance. Stores class instance in Experiment.
"""
self.axe1.set_xlabel("Freq (Hz)")
self.axe1.set_ylabel("|Y| (A/Hz)")
self.axe1.set_xlim(0, Experiment.parameters['adc_rate_hz']/2)
Experiment.plots['ft'] = self
self.figure.canvas.draw()
\ No newline at end of file
import time
import struct
from .experiment_template import PlotBox, Experiment
class CVExp(Experiment):
id = 'cve'
"""Cyclic Voltammetry experiment"""
def setup(self):
self.plotlims['current_voltage']['xlims'] = tuple(
sorted((int(self.parameters['v1']), int(self.parameters['v2'])))
)
super(CVExp, self).setup()
self.datatype = "CVData"
self.xlabel = "Voltage (mV)"
self.ylabel = "Current (A)"
self.datalength = 2 * self.parameters['scans'] # x and y for each scan
self.databytes = 6 # uint16 + int32
self.commands += "E"
self.commands[2] += "C"
self.commands[2] += str(self.parameters['clean_s'])
self.commands[2] += " "
self.commands[2] += str(self.parameters['dep_s'])
self.commands[2] += " "
self.commands[2] += str(int(
int(self.parameters['clean_mV'])/
self.re_voltage_scale*
(65536./3000)+32768
))
self.commands[2] += " "
self.commands[2] += str(int(
int(self.parameters['dep_mV'])/
self.re_voltage_scale*
(65536./3000)+32768
))
self.commands[2] += " "
self.commands[2] += str(int(
int(self.parameters['v1'])/
self.re_voltage_scale*
(65536./3000)+32768
))
self.commands[2] += " "
self.commands[2] += str(int(
int(self.parameters['v2'])/
self.re_voltage_scale*
(65536./3000)+32768
))
self.commands[2] += " "
self.commands[2] += str(int(
int(self.parameters['start'])/
self.re_voltage_scale*
(65536./3000)+32768
))
self.commands[2] += " "
self.commands[2] += str(self.parameters['scans'])
self.commands[2] += " "
self.commands[2] += str(int(
int(self.parameters['slope'])/
self.re_voltage_scale*
(65536./3000)
))
self.commands[2] += " "
def get_progress(self):
return (len(self.data['current_voltage'])-1) / float(self.parameters['scans'])
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# DStat Interface - An interface for the open hardware DStat potentiostat
# Copyright (C) 2014 Michael D. M. Dryden -
# Wheeler Microfluidics Laboratory <http://microfluidics.utoronto.ca>
#
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import division, absolute_import, print_function, unicode_literals
from ..dstat import state
import logging
try:
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GObject
except ImportError:
print("ERR: GTK not available")
sys.exit(1)
logger = logging.getLogger(__name__)
class BaseLoop(GObject.GObject):
__gsignals__ = {
b'experiment_done': (GObject.SIGNAL_RUN_FIRST, None, tuple()),
b'progress_update': (GObject.SIGNAL_RUN_FIRST, None, (float,))
}
def __init__(self, experiment, callbacks=None):
GObject.GObject.__init__(self)
self.line = None
self.lastdataline = 0
self.current_exp = experiment
self.experiment_proc = None
for signal, cb in callbacks.items():
try:
self.connect(signal, cb)
except TypeError:
logger.warning("Invalid signal %s", signal)
def run(self):
self.experiment_proc = [
GObject.idle_add(self.experiment_running_data),
GObject.idle_add(self.experiment_running_proc),
GObject.timeout_add(100, self.update_progress)
]
def experiment_running_data(self):
"""Receive data from experiment process and add to
current_exp.data['data].
Run in GTK main loop.
Returns:
True -- when experiment is continuing to keep function in GTK's queue.
False -- when experiment process signals EOFError or IOError to remove
function from GTK's queue.
"""
try:
incoming = state.ser.get_data()
while incoming is not None:
try:
self.line = incoming[0]
if self.line > self.lastdataline:
newline = True
try:
logger.info("running scan_process()")
self.current_exp.scan_process(self.lastdataline)
except AttributeError:
pass
self.lastdataline = self.line
else:
newline = False
self.current_exp.store_data(incoming, newline)
except TypeError:
pass
incoming = state.ser.get_data()
return True
except EOFError as err:
logger.error(err)
self.experiment_done()
return False
except IOError as err:
logger.error(err)
self.experiment_done()
return False
def experiment_running_proc(self):
"""Receive proc signals from experiment process.
Run in GTK main loop.
Returns:
True -- when experiment is continuing to keep function in GTK's queue.
False -- when experiment process signals EOFError or IOError to remove
function from GTK's queue.
"""
try:
ctrl_buffer = state.ser.get_ctrl()
try:
if ctrl_buffer is not None:
self.current_exp.ctrl_loop(ctrl_buffer)
except AttributeError:
pass
proc_buffer = state.ser.get_proc()
if proc_buffer is not None:
if proc_buffer in ["DONE", "SERIAL_ERROR", "ABORT"]:
self.experiment_done()
if proc_buffer == "SERIAL_ERROR":
self.on_serial_disconnect_clicked()
else:
logger.warning("Unrecognized experiment return code: %s",
proc_buffer)
return False
return True
except EOFError as err:
logger.warning("EOFError: %s", err)
self.experiment_done()
return False
except IOError as err:
logger.warning("IOError: %s", err)
self.experiment_done()
return False
def experiment_done(self):
logger.info("Experiment done")
for proc in self.experiment_proc:
GObject.source_remove(proc)
self.current_exp.scan_process(self.lastdataline)
self.current_exp.experiment_done()
self.emit("experiment_done")
def update_progress(self):
try:
progress = self.current_exp.get_progress()
except AttributeError:
progress = -1
self.emit("progress_update", progress)
return True
class PlotLoop(BaseLoop):
def experiment_running_plot(self, force_refresh=False):
"""Plot all data in current_exp.data.
Run in GTK main loop. Always returns True so must be manually
removed from GTK's queue.
"""
if self.line is None:
return True
for plot in self.current_exp.plots:
if (plot.scan_refresh and self.line > self.lastdataline):
while self.line > self.lastline:
# make sure all of last line is added
plot.updateline(self.current_exp, self.lastdataline)
self.lastdataline += 1
plot.updateline(self.current_exp, self.line)
plot.redraw()
else:
while self.line > self.lastdataline:
# make sure all of last line is added
plot.updateline(self.current_exp, self.lastdataline)
self.lastdataline += 1
plot.updateline(self.current_exp, self.line)
if plot.continuous_refresh is True or force_refresh is True:
plot.redraw()
return True
def run(self):
super(PlotLoop, self).run()
self.experiment_proc.append(
GObject.timeout_add(200, self.experiment_running_plot)
)
def experiment_done(self):
logger.info("Experiment done")
for proc in self.experiment_proc:
GObject.source_remove(proc)
self.current_exp.scan_process(self.lastdataline)
self.current_exp.experiment_done()
self.experiment_running_plot(force_refresh=True)
self.emit("experiment_done")
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# DStat Interface - An interface for the open hardware DStat potentiostat
# Copyright (C) 2017 Michael D. M. Dryden -
# Wheeler Microfluidics Laboratory <http://microfluidics.utoronto.ca>
#
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import logging
import struct
import time
from collections import OrderedDict
from copy import deepcopy
from datetime import datetime
from math import ceil
try:
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GObject
except ImportError:
print "ERR: GTK not available"
sys.exit(1)
from matplotlib.figure import Figure
import matplotlib.gridspec as gridspec
from matplotlib.backends.backend_gtk3agg \
import FigureCanvasGTK3Agg as FigureCanvas
from pandas import DataFrame
import seaborn as sns
sns.set(context='paper', style='darkgrid')
import serial
from ..dstat import state, comm
from ..dstat.comm import TransmitError
from . import experiment_loops
logger = logging.getLogger(__name__)
dstat_logger = logging.getLogger("{}.DSTAT".format(comm.__name__))
exp_logger = logging.getLogger("{}.Experiment".format(__name__))
class Experiment(GObject.Object):
"""Store and acquire a potentiostat experiment. Meant to be subclassed
to by different experiment types and not used instanced directly. Subclass
must instantiate self.plotbox as the PlotBox class to use and define id as
a class attribute.
"""
id = None
Loops = experiment_loops.PlotLoop
__gsignals__ = {
b'exp_ready': (GObject.SIGNAL_RUN_FIRST, None, ()),
b'exp_done': (GObject.SIGNAL_RUN_FIRST, None, ()),
}
def __init__(self, parameters):
"""Adds commands for gain and ADC."""
super(Experiment, self).__init__()
self.current_command = None
self.parameters = parameters
self.databytes = 8
self.datapoint = 0
self.scan = 0
self.time = 0
self.plots = []
self.re_voltage_scale = state.board_instance.re_voltage_scale
self.gain = state.board_instance.gain[int(self.parameters['gain'])]
try:
self.gain_trim = int(
state.settings[
state.board_instance.gain_trim[int(self.parameters['gain'])]
][1]
)
except AttributeError:
logger.debug("No gain trim table.")
self.commands = ["EA", "EG"]
if self.parameters['buffer_true']:
self.commands[0] += "2"
else:
self.commands[0] += "0"
self.commands[0] += " {p[adc_rate]} {p[adc_pga]} ".format(
p=self.parameters)
self.commands[1] += "{p[gain]} {p[short_true]:d} ".format(
p=self.parameters)
self.plotlims = {'current_voltage' : {'xlims' : (0, 1)}
}
self.setup()
self.time = [datetime.utcnow()]
def setup_loops(self, callbacks):
self.loops = self.__class__.Loops(self, callbacks)
self.loops.run()
def setup(self):
self.data = OrderedDict(current_voltage=[([], [])])
self.columns = ['Voltage (mV)', 'Current (A)']
# list of scans, tuple of dimensions, list of data
self.line_data = ([], [])
plot = PlotBox(['current_voltage'])
plot.setlims('current_voltage', **self.plotlims['current_voltage'])
self.plots.append(plot)
def write_command(self, cmd, params=None, retry=5):
"""Write command to serial with optional number of retries."""
def get_reply(retries=3):
while True:
reply = self.serial.readline().rstrip()
if reply.startswith('#'):
dstat_logger.info(reply)
elif reply == "":
retries -= 1
if retries <= 0:
raise TransmitError
else:
return reply
n = len(cmd)
if params is not None:
n_params = len(params)
for _ in range(retry):
tries = 5
while True:
time.sleep(0.2)
self.serial.reset_input_buffer()
self.serial.write('!{}\n'.format(n))
time.sleep(.1)
try:
reply = get_reply()
except TransmitError:
if tries <= 0:
continue
tries -= 1
pass
else:
break
if reply != "@ACK {}".format(n):
logger.warning("Expected ACK got: {}".format(reply))
continue
tries = 5
while True:
self.serial.write('{}\n'.format(cmd))
try:
reply = get_reply()
except TransmitError:
if tries <= 0:
continue
tries -= 1
pass
else:
break
if reply != "@RCV {}".format(n):
logger.warning("Expected RCV got: {}".format(reply))
continue
if params is None:
return True
tries = 5
while True:
try:
reply = get_reply()
except TransmitError:
if tries <= 0:
break
tries -= 1
pass
else:
break
if reply != "@RQP {}".format(n_params):
logger.warning("Expected RQP got: {}".format(reply))
continue
tries = 5
for i in params:
while True:
self.serial.write(i + " ")
try:
reply = get_reply()
if reply == "@RCVC {}".format(i):
break
except TransmitError:
if tries <= 0:
continue
tries -= 1
pass
else:
break
return True
return False
def run(self, ser, ctrl_pipe, data_pipe):
"""Execute experiment. Connects and sends handshake signal to DStat
then sends self.commands.
"""
self.serial = ser
self.ctrl_pipe = ctrl_pipe
self.data_pipe = data_pipe
exp_logger.info("Experiment running")
try:
for i in self.commands:
self.current_command = i
status = "DONE"
if isinstance(i, (str, unicode)):
logger.info("Command: %s", i)
if not self.write_command(i):
status = "ABORT"
break
else:
cmd = i[0]
data = i[1]
logger.info("Command: {}".format(cmd))
if not self.write_command(cmd, params=data):
status = "ABORT"
break
if not self.serial_handler():
status = "ABORT"
break
time.sleep(0.5)
except serial.SerialException:
status = "SERIAL_ERROR"
finally:
while self.ctrl_pipe.poll():
self.ctrl_pipe.recv()
return status
def serial_handler(self):
"""Handles incoming serial transmissions from DStat. Returns False
if stop button pressed and sends abort signal to instrument. Sends
data to self.data_pipe as result of self.data_handler).
"""
scan = 0
def check_ctrl():
if self.ctrl_pipe.poll():
input = self.ctrl_pipe.recv()
logger.info("serial_handler: %s", input)
if input == "DISCONNECT":
self.serial.write('a')
self.serial.reset_input_buffer()
logger.info("serial_handler: ABORT pressed!")
time.sleep(.3)
return False
elif input == 'a':
self.serial.write('a')
else:
self.serial.write(input)
try:
while True:
check_ctrl()
for line in self.serial:
check_ctrl()
if line.startswith('B'):
data = self.data_handler(
(scan, self.serial.read(size=self.databytes)))
data = self.data_postprocessing(data)
if data is not None:
self.data_pipe.send(data)
try:
self.datapoint += 1
except AttributeError: #Datapoint counting is optional
pass
elif line.lstrip().startswith('S'):
scan += 1
elif line.lstrip().startswith("#"):
dstat_logger.info(line.lstrip().rstrip())
elif line.lstrip().startswith("@DONE"):
dstat_logger.debug(line.lstrip().rstrip())
time.sleep(.3)
return True
except serial.SerialException:
return False
def data_handler(self, data_input):
"""Takes data_input as tuple -- (scan, data).
Returns:
(scan number, (voltage, current)) -- voltage in mV, current in A
"""
scan, data = data_input
voltage, current = struct.unpack('<Hl', data) #uint16 + int32
return (scan, (
(voltage-32768)*(3000./65536)*self.re_voltage_scale,
(current+self.gain_trim)*(1.5/8388607)/self.gain
)
)
def store_data(self, incoming, newline):
"""Stores data in data attribute. Should not be called from subprocess.
Can be overriden for custom experiments."""
line, data = incoming
if newline is True:
self.data['current_voltage'].append(deepcopy(self.line_data))
for i, item in enumerate(self.data['current_voltage'][line]):
item.append(data[i])
def data_postprocessing(self, data):
"""Discards first data point (usually gitched) by default, can be overridden
in subclass.
"""
try:
if self.datapoint <= 1:
return None
except AttributeError: # Datapoint counting is optional
pass
return data
def scan_process(self, line):
pass
def experiment_done(self):
"""Runs when experiment is finished (all data acquired)"""
self.data_to_pandas()
self.time += [datetime.utcnow()]
def export(self):
"""Return a dict containing data for saving."""
output = {
"datatype" : self.datatype,
"xlabel" : self.xlabel,
"ylabel" : self.ylabel,
"xmin" : self.xmin,
"xmax" : self.xmax,
"parameters" : self.parameters,
"data" : self.data,
"commands" : self.commands
}
return output
def data_to_pandas(self):
"""Convert data to pandas DataFrame and set as member of .df
attribute."""
self.df = OrderedDict()
for name, data in self.data.items():
try:
df = DataFrame(
columns=['Scan'] + list(self.plot_format[name]['labels']))
for n, line in enumerate(data): # Each scan
df = df.append(
DataFrame(
OrderedDict(zip(
['Scan'] + list(self.plot_format[name]['labels']),
[n] + list(line))
)
), ignore_index = True
)
except (AttributeError, KeyError):
try:
df = DataFrame(
columns=['Scan'] + list(self.columns))
for n, line in enumerate(data): # Each scan
df = df.append(
DataFrame(
OrderedDict(zip(
['Scan'] + list(self.columns),
[n] + list(line))
)
), ignore_index = True
)
except AttributeError as e: # Fallback if no self.columns
df = DataFrame(
columns=['Scan'] + ["{}{}".format(name, n)
for n in range(len(data))]
)
for n, line in enumerate(data):
df = df.append(
DataFrame(
OrderedDict(zip(
['Scan'] + ["{}{}".format(name, n)
for n in range(len(data))],
[n] + list(line))
)
), ignore_index = True
)
self.df[name] = df
def get_info_text(self):
"""Return string of text to disply on Info tab."""
buf = "#Time: S{} E{}\n".format(self.time[0], self.time[1])
buf += "#Commands:\n"
for line in self.commands:
buf += '#{}\n'.format(line)
return buf
def get_save_strings(self):
"""Return dict of strings with experiment parameters and data."""
buf = {}
buf['params'] = self.get_info_text()
buf.update(
{exp : df.to_csv(sep='\t', encoding='utf-8')
for exp, df in self.df.items()}
)
return buf
class PlotBox(object):
"""Contains data plot and associated methods."""
def __init__(self, plots=None):
"""Initializes plots. self.box should be reparented."""
self.name = "Main"
self.continuous_refresh = True
self.scan_refresh = False
if plots is not None:
self.plotnames = plots
else:
self.plotnames = []
self.subplots = {}
self.figure = Figure()
# self.figure.subplots_adjust(left=0.07, bottom=0.07,
# right=0.96, top=0.96)
self.setup()
self.format_plots() # Should be overriden by subclass
self.figure.set_tight_layout(True)
self.canvas = FigureCanvas(self.figure)
self.canvas.set_vexpand(True)
self.box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.box.pack_start(self.canvas, expand=True, fill=True, padding=0)
def setup(self):
self.plot_format = {
'current_voltage': {'xlabel': "Voltage (mV)",
'ylabel': "Current (A)"
}
}
def format_plots(self):
"""
Creates and formats subplots needed. Should be overriden by subclass
"""
# Calculate size of grid needed
if len(self.plotnames) > 1:
gs = gridspec.GridSpec(int(ceil(len(self.plotnames)/2.)),2)
else:
gs = gridspec.GridSpec(1,1)
for n, i in enumerate(self.plotnames):
self.subplots[i] = self.figure.add_subplot(gs[n])
for key, subplot in self.subplots.items():
subplot.ticklabel_format(style='sci', scilimits=(0, 3),
useOffset=False, axis='y')
subplot.plot([], [])
subplot.set_xlabel(self.plot_format[key]['xlabel'])
subplot.set_ylabel(self.plot_format[key]['ylabel'])
def clearall(self):
"""Remove all lines on plot. """
for name, plot in self.subplots.items():
for line in reversed(plot.lines):
line.remove()
self.addline()
def clearline(self, subplot, line_number):
"""Remove a single line.
Arguments:
subplot -- key in self.subplots
line_number -- line number in subplot
"""
self.subplots[subplot].lines[line_number].remove()
def addline(self):
"""Add a new line to plot. (initialized with dummy data)))"""
for subplot in self.subplots.values():
subplot.plot([], [])
def updateline(self, Experiment, line_number):
"""Update a line specified with new data.
Arguments:
Experiment -- Experiment instance
line_number -- line number to update
"""
for subplot in Experiment.data:
while True:
try:
self.subplots[subplot].lines[line_number].set_xdata(
Experiment.data[subplot][line_number][0])
self.subplots[subplot].lines[line_number].set_ydata(
Experiment.data[subplot][line_number][1])
except IndexError:
self.addline()
except KeyError:
pass
else:
break
# logger.warning("Tried to set line %s that doesn't exist.", line_number)
def setlims(self, plot, xlims=None, ylims=None):
"""Sets x and y limits.
"""
if xlims is not None:
self.subplots[plot].set_xlim(xlims)
if ylims is not None:
self.subplots[plot].set_ylim(ylims)
self.figure.canvas.draw()
def redraw(self):
"""Autoscale and refresh the plot."""
for name, plot in self.subplots.items():
plot.relim()
plot.autoscale(True, axis = 'y')
self.figure.canvas.draw()
return True
\ No newline at end of file
import time
import struct
from .experiment_template import Experiment
from ..dstat import state
class OCPExp(Experiment):
"""Open circuit potential measumement in statusbar."""
id = 'ocp'
def __init__(self):
self.re_voltage_scale = state.board_instance.re_voltage_scale
self.databytes = 8
self.commands = ["EA", "EP0 0 "]
self.commands[0] += "2 " # input buffer
self.commands[0] += "3 " # 2.5 Hz sample rate
self.commands[0] += "1 " # 2x PGA
def data_handler(self, data_input):
"""Overrides Experiment method to only send ADC values."""
scan, data = data_input
# 2*uint16 + int32
seconds, milliseconds, voltage = struct.unpack('<HHl', data)
return voltage/5.592405e6*self.re_voltage_scale
class PMTIdle(Experiment):
"""PMT idle mode."""
id = "pmt_idle"
def __init__(self):
self.databytes = 8
self.commands = ["EA", "EM"]
self.commands[0] += "2 " # input buffer
self.commands[0] += "3 " # 2.5 Hz sample rate
self.commands[0] += "1 " # 2x PGA
import time
import struct
from .experiment_template import PlotBox, Experiment
class LSVExp(Experiment):
"""Linear Scan Voltammetry experiment"""
id = 'lsv'
def setup(self):
self.plotlims['current_voltage']['xlims'] = tuple(
sorted(
(int(self.parameters['start']),
int(self.parameters['stop']))
)
)
super(LSVExp, self).setup()
self.datatype = "linearData"
self.datalength = 2
self.databytes = 6 # uint16 + int32
self.stop_mv = int(self.parameters['stop'])
self.max_mv = abs(int(self.parameters['start'])-int(self.parameters['stop']))
self.commands += "E"
self.commands[2] += "L"
self.commands[2] += str(self.parameters['clean_s'])
self.commands[2] += " "
self.commands[2] += str(self.parameters['dep_s'])
self.commands[2] += " "
self.commands[2] += str(int(
int(self.parameters['clean_mV'])/
self.re_voltage_scale*
(65536./3000)+32768
))
self.commands[2] += " "
self.commands[2] += str(int(
int(self.parameters['dep_mV'])/
self.re_voltage_scale*
(65536./3000)+32768
))
self.commands[2] += " "
self.commands[2] += str(int(
int(self.parameters['start'])/
self.re_voltage_scale*
(65536./3000)+32768
))
self.commands[2] += " "
self.commands[2] += str(int(
int(self.parameters['stop'])/
self.re_voltage_scale*
(65536./3000)+32768
))
self.commands[2] += " "
self.commands[2] += str(int(
int(self.parameters['slope'])/
self.re_voltage_scale*
(65536./3000)
))
self.commands[2] += " "
def get_progress(self):
try:
return 1 - (abs(self.stop_mv - self.data['current_voltage'][-1][0][-1])/self.max_mv)
except IndexError:
return 0
\ No newline at end of file
import time
import struct
from .experiment_template import PlotBox, Experiment
class PotBox(PlotBox):
def setup(self):
self.plot_format = {
'voltage_time': {'xlabel': "Time (s)",
'ylabel': "Voltage (V)"
}
}
def format_plots(self):
"""
Creates and formats subplots needed. Overrides superclass.
"""
self.subplots = {'voltage_time': self.figure.add_subplot(111)}
for key, subplot in self.subplots.items():
subplot.ticklabel_format(style='sci', scilimits=(0, 3),
useOffset=False, axis='y')
subplot.plot([],[])
subplot.set_xlabel(self.plot_format[key]['xlabel'])
subplot.set_ylabel(self.plot_format[key]['ylabel'])
class PotExp(Experiment):
id = 'pot'
"""Potentiometry experiment"""
def setup(self):
self.plots.append(PotBox(['voltage_time']))
self.datatype = "linearData"
self.datalength = 2
self.databytes = 8
self.data = {'voltage_time' : [([],[])]}
self.columns = ['Time (s)', 'Voltage (V)']
self.plotlims = {
'voltage_time': {
'xlims': (0, int(self.parameters['time']))
}
}
self.plots[-1].setlims('voltage_time', **self.plotlims['voltage_time'])
self.total_time = int(self.parameters['time'])
self.commands += "E"
self.commands[2] += "P"
self.commands[2] += str(self.parameters['time'])
self.commands[2] += " 1 " # potentiometry mode
def data_handler(self, data_input):
"""Overrides Experiment method to not convert x axis to mV."""
scan, data = data_input
# 2*uint16 + int32
seconds, milliseconds, voltage = struct.unpack('<HHl', data)
return (scan, (
seconds+milliseconds/1000.,
voltage*self.re_voltage_scale*(1.5/8388607.)
)
)
def store_data(self, incoming, newline):
"""Stores data in data attribute. Should not be called from subprocess.
Can be overriden for custom experiments."""
line, data = incoming
if newline is True:
self.data['voltage_time'].append(deepcopy(self.line_data))
for i, item in enumerate(self.data['voltage_time'][line]):
item.append(data[i])
def get_progress(self):
try:
return self.data['voltage_time'][-1][0][-1]/self.total_time
except IndexError:
return 0
\ No newline at end of file
import time
import struct
from copy import deepcopy
from .experiment_template import PlotBox, Experiment
class SWVBox(PlotBox):
def setup(self):
self.plot_format = {
'swv': {'xlabel': "Voltage (mV)",
'ylabel': "Current (A)"
}
}
def format_plots(self):
"""
Creates and formats subplots needed. Overrides superclass.
"""
self.subplots = {'swv': self.figure.add_subplot(111)}
for key, subplot in self.subplots.items():
subplot.ticklabel_format(style='sci', scilimits=(0, 3),
useOffset=False, axis='y')
subplot.plot([],[])
subplot.set_xlabel(self.plot_format[key]['xlabel'])
subplot.set_ylabel(self.plot_format[key]['ylabel'])
class SWVExp(Experiment):
"""Square Wave Voltammetry experiment"""
id = 'swv'
def setup(self):
self.datatype = "SWVData"
self.xlabel = "Voltage (mV)"
self.ylabel = "Current (A)"
self.data = {
'swv' : [([], [], [], [])]
} # voltage, current, forwards, reverse
self.line_data = ([], [], [], [])
self.datalength = 2 * self.parameters['scans']
self.databytes = 10
self.columns = ['Voltage (mV)', 'Net Current (A)',
'Forward Current (A)', 'Reverse Current (A)']
self.plotlims = {
'swv': {
'xlims': tuple(sorted(
(int(self.parameters['start']),
int(self.parameters['stop']))
)
)
}
}
plot = SWVBox()
plot.setlims('swv', **self.plotlims['swv'])
self.plots.append(plot)
self.stop_mv = int(self.parameters['stop'])
self.max_mv = abs(int(self.parameters['start']) - int(self.parameters['stop']))
self.scan_points = self.max_mv * 2 / float(self.parameters['step'])
self.commands += "E"
self.commands[2] += "S"
self.commands[2] += str(self.parameters['clean_s'])
self.commands[2] += " "
self.commands[2] += str(self.parameters['dep_s'])
self.commands[2] += " "
self.commands[2] += str(int(
int(self.parameters['clean_mV'])/
self.re_voltage_scale*
(65536./3000)+32768
))
self.commands[2] += " "
self.commands[2] += str(int(
int(self.parameters['dep_mV'])/
self.re_voltage_scale*
(65536./3000)+32768
))
self.commands[2] += " "
self.commands[2] += str(int(
int(self.parameters['start'])/
self.re_voltage_scale*
(65536./3000)+32768
))
self.commands[2] += " "
self.commands[2] += str(int(
int(self.parameters['stop'])/
self.re_voltage_scale*
(65536./3000)+32768
))
self.commands[2] += " "
self.commands[2] += str(int(
int(self.parameters['step'])/
self.re_voltage_scale*
(65536./3000)
))
self.commands[2] += " "
self.commands[2] += str(int(
int(self.parameters['pulse'])/
self.re_voltage_scale*
(65536./3000)
))
self.commands[2] += " "
self.commands[2] += str(self.parameters['freq'])
self.commands[2] += " "
self.commands[2] += str(self.parameters['scans'])
self.commands[2] += " "
def data_handler(self, input_data):
"""Overrides Experiment method to calculate difference current"""
scan, data = input_data
# uint16 + int32
voltage, forward, reverse = struct.unpack('<Hll', data)
f_trim = forward+self.gain_trim
r_trim = reverse+self.gain_trim
return (scan, (
(voltage-32768)*3000./65536*self.re_voltage_scale,
(f_trim-r_trim)*(1.5/self.gain/8388607),
f_trim*(1.5/self.gain/8388607),
r_trim*(1.5/self.gain/8388607)
)
)
def store_data(self, incoming, newline):
"""Stores data in data attribute. Should not be called from subprocess.
Can be overriden for custom experiments."""
line, data = incoming
if newline is True:
self.data['swv'].append(deepcopy(self.line_data))
for i, item in enumerate(self.data['swv'][line]):
item.append(data[i])
def get_progress(self):
try:
if int(self.parameters['scans']) != 0:
scans_prog = (len(self.data['swv'])-1) / float(self.parameters['scans'])
scan_prog = (len(self.data['swv'][-1][0])-1) / self.scan_points / float(self.parameters['scans'])
prog = scans_prog + scan_prog
if prog > 1:
prog = 1
return prog
else:
return 1 - (abs(self.stop_mv - self.data['swv'][-1][0][-1])/self.max_mv)
except IndexError:
return 0
class DPVExp(SWVExp):
"""Diffential Pulse Voltammetry experiment."""
id = 'dpv'
def setup(self):
self.datatype = "SWVData"
self.xlabel = "Voltage (mV)"
self.ylabel = "Current (A)"
self.data = {
'swv' : [([], [], [], [])]
} # voltage, current, forwards, reverse
self.line_data = ([], [], [], [])
self.datalength = 2
self.databytes = 10
self.columns = ['Voltage (mV)', 'Net Current (A)',
'Forward Current (A)', 'Reverse Current (A)']
self.plotlims = {
'swv': {
'xlims': tuple(sorted(
(int(self.parameters['start']),
int(self.parameters['stop']))
)
)
}
}
plot = SWVBox()
plot.setlims('swv', **self.plotlims['swv'])
self.plots.append(plot)
self.stop_mv = int(self.parameters['stop'])
self.max_mv = abs(int(self.parameters['start']) - int(self.parameters['stop']))
self.commands += "E"
self.commands[2] += "D"
self.commands[2] += str(self.parameters['clean_s'])
self.commands[2] += " "
self.commands[2] += str(self.parameters['dep_s'])
self.commands[2] += " "
self.commands[2] += str(int(
int(self.parameters['clean_mV'])/
self.re_voltage_scale*
(65536./3000)+32768
))
self.commands[2] += " "
self.commands[2] += str(int(
int(self.parameters['dep_mV'])/
self.re_voltage_scale*
(65536./3000)+32768
))
self.commands[2] += " "
self.commands[2] += str(int(
int(self.parameters['start'])/
self.re_voltage_scale*
(65536./3000)+32768
))
self.commands[2] += " "
self.commands[2] += str(int(
int(self.parameters['stop'])/
self.re_voltage_scale*
(65536./3000)+32768
))
self.commands[2] += " "
self.commands[2] += str(int(
int(self.parameters['step'])/
self.re_voltage_scale*
(65536./3000)
))
self.commands[2] += " "
self.commands[2] += str(int(
int(self.parameters['pulse'])/
self.re_voltage_scale*
(65536./3000)
))
self.commands[2] += " "
self.commands[2] += str(self.parameters['period'])
self.commands[2] += " "
self.commands[2] += str(self.parameters['width'])
self.commands[2] += " "
def get_progress(self):
try:
return 1 - (abs(self.stop_mv - self.data['swv'][-1][0][-1])/self.max_mv)
except IndexError:
return 0
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface> <interface>
<requires lib="gtk+" version="2.24"/> <requires lib="gtk+" version="3.10"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkWindow" id="window1"> <object class="GtkWindow" id="window1">
<property name="can_focus">False</property> <property name="can_focus">False</property>
<child> <child>
<object class="GtkScrolledWindow" id="scrolledwindow1"> <object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="hscrollbar_policy">automatic</property> <property name="hexpand">True</property>
<property name="vscrollbar_policy">automatic</property> <property name="vexpand">True</property>
<child> <child>
<object class="GtkViewport" id="viewport1"> <object class="GtkViewport" id="viewport1">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="shadow_type">none</property> <property name="shadow_type">none</property>
<child> <child>
<object class="GtkVBox" id="vbox1"> <object class="GtkBox" id="vbox1">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child> <child>
<object class="GtkFrame" id="frame1"> <object class="GtkFrame" id="frame2">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="label_xalign">0</property> <property name="label_xalign">0</property>
<property name="shadow_type">out</property> <property name="shadow_type">out</property>
<child> <child>
<object class="GtkAlignment" id="alignment1"> <object class="GtkAlignment" id="alignment2">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="bottom_padding">5</property> <property name="bottom_padding">5</property>
<property name="left_padding">5</property> <property name="left_padding">5</property>
<property name="right_padding">5</property> <property name="right_padding">5</property>
<child> <child>
<object class="GtkTable" id="table1"> <object class="GtkGrid">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="n_rows">3</property> <property name="row_homogeneous">True</property>
<property name="n_columns">3</property>
<child>
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Potential (mV)</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child> <child>
<object class="GtkLabel" id="label4"> <object class="GtkLabel" id="label8">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="label" translatable="yes">Time (s)</property> <property name="hexpand">True</property>
<property name="label" translatable="yes">Start (mV)</property>
</object> </object>
<packing> <packing>
<property name="left_attach">2</property> <property name="left_attach">0</property>
<property name="right_attach">3</property> <property name="top_attach">0</property>
<property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="label5"> <object class="GtkLabel" id="label9">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Stop (mV)</property>
</object> </object>
<packing> <packing>
<property name="y_options">GTK_FILL</property> <property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="label6"> <object class="GtkLabel" id="label10">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="label" translatable="yes">Cleaning</property> <property name="hexpand">True</property>
<property name="label" translatable="yes">Slope (mV/s)</property>
</object> </object>
<packing> <packing>
<property name="top_attach">1</property> <property name="left_attach">0</property>
<property name="bottom_attach">2</property> <property name="top_attach">2</property>
<property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="label7"> <object class="GtkEntry" id="start_entry">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">True</property>
<property name="label" translatable="yes">Deposition</property> <property name="invisible_char"></property>
<property name="width_chars">8</property>
<property name="text" translatable="yes">0</property>
<property name="xalign">1</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
</object> </object>
<packing> <packing>
<property name="top_attach">2</property> <property name="left_attach">1</property>
<property name="bottom_attach">3</property> <property name="top_attach">0</property>
<property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkEntry" id="clean_mV"> <object class="GtkEntry" id="stop_entry">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="invisible_char"></property> <property name="invisible_char"></property>
<property name="width_chars">8</property> <property name="width_chars">8</property>
<property name="text" translatable="yes">0</property> <property name="text" translatable="yes">0</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property> <property name="primary_icon_activatable">False</property>
<property name="secondary_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>
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property> <property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options"/>
<property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkEntry" id="dep_mV"> <object class="GtkEntry" id="slope_entry">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="invisible_char"></property> <property name="invisible_char"></property>
<property name="width_chars">8</property> <property name="width_chars">8</property>
<property name="text" translatable="yes">0</property> <property name="text" translatable="yes">0</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property> <property name="primary_icon_activatable">False</property>
<property name="secondary_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>
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property> <property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options"/>
<property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkEntry" id="dep_s"> <object class="GtkLabel" id="label11">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Amplitude (mV)</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label12">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Frequency (Hz)</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">4</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="amplitude_entry">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="invisible_char"></property> <property name="invisible_char"></property>
<property name="width_chars">8</property> <property name="width_chars">8</property>
<property name="text" translatable="yes">0</property> <property name="text" translatable="yes">0</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property> <property name="primary_icon_activatable">False</property>
<property name="secondary_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>
</object> </object>
<packing> <packing>
<property name="left_attach">2</property> <property name="left_attach">1</property>
<property name="right_attach">3</property> <property name="top_attach">3</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options"/>
<property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkEntry" id="clean_s"> <object class="GtkEntry" id="freq_entry">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="invisible_char"></property> <property name="invisible_char"></property>
<property name="width_chars">8</property> <property name="width_chars">8</property>
<property name="text" translatable="yes">0</property> <property name="text" translatable="yes">0</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property> <property name="primary_icon_activatable">False</property>
<property name="secondary_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>
</object> </object>
<packing> <packing>
<property name="left_attach">2</property> <property name="left_attach">1</property>
<property name="right_attach">3</property> <property name="top_attach">4</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options"/>
<property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
</object> </object>
...@@ -192,10 +183,10 @@ ...@@ -192,10 +183,10 @@
</object> </object>
</child> </child>
<child type="label"> <child type="label">
<object class="GtkLabel" id="label1"> <object class="GtkLabel" id="label2">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="label" translatable="yes">Preconditioning</property> <property name="label" translatable="yes">Experiment</property>
<property name="use_markup">True</property> <property name="use_markup">True</property>
</object> </object>
</child> </child>
...@@ -208,211 +199,215 @@ ...@@ -208,211 +199,215 @@
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkFrame" id="frame2"> <object class="GtkFrame" id="frame1">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="label_xalign">0</property> <property name="label_xalign">0</property>
<property name="shadow_type">out</property> <property name="shadow_type">out</property>
<child> <child>
<object class="GtkAlignment" id="alignment2"> <object class="GtkAlignment" id="alignment1">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="bottom_padding">5</property> <property name="bottom_padding">5</property>
<property name="left_padding">5</property> <property name="left_padding">5</property>
<property name="right_padding">5</property> <property name="right_padding">5</property>
<child> <child>
<object class="GtkTable" id="table2"> <object class="GtkGrid">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="n_rows">5</property> <property name="row_homogeneous">True</property>
<property name="n_columns">2</property>
<property name="column_spacing">10</property>
<property name="homogeneous">True</property>
<child> <child>
<object class="GtkLabel" id="label8"> <object class="GtkLabel" id="label3">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="label" translatable="yes">Start (mV)</property> <property name="label" translatable="yes">Potential (mV)</property>
</object> </object>
<packing> <packing>
<property name="y_options">GTK_FILL</property> <property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="label9"> <object class="GtkLabel" id="label4">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="label" translatable="yes">Stop (mV)</property> <property name="label" translatable="yes">Time (s)</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label6">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Cleaning</property>
</object> </object>
<packing> <packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property> <property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="label10"> <object class="GtkLabel" id="label7">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="label" translatable="yes">Slope (mV/s)</property> <property name="hexpand">True</property>
<property name="label" translatable="yes">Deposition</property>
</object> </object>
<packing> <packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property> <property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkEntry" id="start_entry"> <object class="GtkEntry" id="clean_mV">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="invisible_char"></property> <property name="invisible_char"></property>
<property name="width_chars">8</property> <property name="width_chars">8</property>
<property name="text" translatable="yes">0</property> <property name="text" translatable="yes">0</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property> <property name="primary_icon_activatable">False</property>
<property name="secondary_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>
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="left_attach">1</property>
<property name="right_attach">2</property> <property name="top_attach">1</property>
<property name="x_options"/>
<property name="y_options">GTK_FILL</property>
<property name="y_padding">3</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkEntry" id="stop_entry"> <object class="GtkEntry" id="dep_mV">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="invisible_char"></property> <property name="invisible_char"></property>
<property name="width_chars">8</property> <property name="width_chars">8</property>
<property name="text" translatable="yes">0</property> <property name="text" translatable="yes">0</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property> <property name="primary_icon_activatable">False</property>
<property name="secondary_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>
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="left_attach">1</property>
<property name="right_attach">2</property> <property name="top_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options"/>
<property name="y_options">GTK_FILL</property>
<property name="y_padding">3</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkEntry" id="slope_entry"> <object class="GtkEntry" id="dep_s">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="invisible_char"></property> <property name="invisible_char"></property>
<property name="width_chars">8</property> <property name="width_chars">8</property>
<property name="text" translatable="yes">0</property> <property name="text" translatable="yes">0</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property> <property name="primary_icon_activatable">False</property>
<property name="secondary_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>
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="left_attach">2</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property> <property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options"/>
<property name="y_options">GTK_FILL</property>
<property name="y_padding">3</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label11">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Amplitude (mV)</property>
</object>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="label12"> <object class="GtkEntry" id="clean_s">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Frequency (Hz)</property>
</object>
<packing>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="amplitude_entry">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="invisible_char"></property> <property name="invisible_char"></property>
<property name="width_chars">8</property> <property name="width_chars">8</property>
<property name="text" translatable="yes">0</property> <property name="text" translatable="yes">0</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property> <property name="primary_icon_activatable">False</property>
<property name="secondary_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>
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="left_attach">2</property>
<property name="right_attach">2</property> <property name="top_attach">1</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options"/>
<property name="y_options">GTK_FILL</property>
<property name="y_padding">3</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkEntry" id="freq_entry"> <object class="GtkLabel" id="label5">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">False</property>
<property name="invisible_char"></property>
<property name="width_chars">8</property>
<property name="text" translatable="yes">0</property>
<property name="xalign">1</property>
<property name="invisible_char_set">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>
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="left_attach">9</property>
<property name="right_attach">2</property> <property name="top_attach">0</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options"/>
<property name="y_options">GTK_FILL</property>
<property name="y_padding">3</property>
</packing> </packing>
</child> </child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object> </object>
</child> </child>
</object> </object>
</child> </child>
<child type="label"> <child type="label">
<object class="GtkLabel" id="label2"> <object class="GtkLabel" id="label1">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="label" translatable="yes">Experiment</property> <property name="label" translatable="yes">Preconditioning</property>
<property name="use_markup">True</property> <property name="use_markup">True</property>
</object> </object>
</child> </child>
...@@ -428,16 +423,15 @@ ...@@ -428,16 +423,15 @@
<object class="GtkLabel" id="label13"> <object class="GtkLabel" id="label13">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="xpad">20</property>
<property name="ypad">20</property>
<property name="label" translatable="yes">Experiment not yet implemented</property> <property name="label" translatable="yes">Experiment not yet implemented</property>
<attributes> <attributes>
<attribute name="weight" value="bold"/> <attribute name="weight" value="bold"/>
</attributes> </attributes>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">True</property>
<property name="fill">False</property> <property name="fill">True</property>
<property name="padding">6</property>
<property name="position">2</property> <property name="position">2</property>
</packing> </packing>
</child> </child>
......
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface> <interface>
<requires lib="gtk+" version="2.24"/> <requires lib="gtk+" version="3.10"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkListStore" id="gain_liststore"> <object class="GtkListStore" id="gain_liststore">
<columns> <columns>
<!-- column-name index --> <!-- column-name index -->
...@@ -196,13 +196,15 @@ ...@@ -196,13 +196,15 @@
<object class="GtkWindow" id="window1"> <object class="GtkWindow" id="window1">
<property name="can_focus">False</property> <property name="can_focus">False</property>
<child> <child>
<object class="GtkVBox" id="vbox1"> <object class="GtkBox" id="vbox1">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child> <child>
<object class="GtkVBox" id="vbox2"> <object class="GtkBox" id="vbox2">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child> <child>
<object class="GtkFrame" id="adc_frame"> <object class="GtkFrame" id="adc_frame">
<property name="visible">True</property> <property name="visible">True</property>
...@@ -217,12 +219,11 @@ ...@@ -217,12 +219,11 @@
<property name="left_padding">5</property> <property name="left_padding">5</property>
<property name="right_padding">5</property> <property name="right_padding">5</property>
<child> <child>
<object class="GtkTable" id="table1"> <object class="GtkGrid">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="n_rows">3</property> <property name="row_homogeneous">True</property>
<property name="n_columns">2</property> <property name="column_homogeneous">True</property>
<property name="row_spacing">2</property>
<child> <child>
<object class="GtkLabel" id="label2"> <object class="GtkLabel" id="label2">
<property name="visible">True</property> <property name="visible">True</property>
...@@ -230,6 +231,10 @@ ...@@ -230,6 +231,10 @@
<property name="tooltip_text" translatable="yes">Gain of the ADC's programmable gain amplifier. Default is 2 - gives full scale input.</property> <property name="tooltip_text" translatable="yes">Gain of the ADC's programmable gain amplifier. Default is 2 - gives full scale input.</property>
<property name="label" translatable="yes">PGA Setting</property> <property name="label" translatable="yes">PGA Setting</property>
</object> </object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="label3"> <object class="GtkLabel" id="label3">
...@@ -238,8 +243,8 @@ ...@@ -238,8 +243,8 @@
<property name="label" translatable="yes">Sample Rate</property> <property name="label" translatable="yes">Sample Rate</property>
</object> </object>
<packing> <packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property> <property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -252,10 +257,7 @@ ...@@ -252,10 +257,7 @@
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property> <property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_EXPAND</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -266,8 +268,8 @@ ...@@ -266,8 +268,8 @@
<property name="label" translatable="yes">Input Buffer</property> <property name="label" translatable="yes">Input Buffer</property>
</object> </object>
<packing> <packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property> <property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -278,7 +280,7 @@ ...@@ -278,7 +280,7 @@
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="left_attach">1</property>
<property name="right_attach">2</property> <property name="top_attach">0</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -289,9 +291,31 @@ ...@@ -289,9 +291,31 @@
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property> <property name="top_attach">1</property>
<property name="bottom_attach">2</property> </packing>
</child>
<child>
<object class="GtkLabel" id="label7">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Short CE and RE terminals together.</property>
<property name="label" translatable="yes">2 Electrode Mode</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="short_checkbutton">
<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="left_attach">1</property>
<property name="top_attach">3</property>
</packing> </packing>
</child> </child>
</object> </object>
...@@ -309,8 +333,7 @@ ...@@ -309,8 +333,7 @@
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">False</property> <property name="fill">True</property>
<property name="padding">2</property>
<property name="position">0</property> <property name="position">0</property>
</packing> </packing>
</child> </child>
...@@ -328,9 +351,10 @@ ...@@ -328,9 +351,10 @@
<property name="left_padding">5</property> <property name="left_padding">5</property>
<property name="right_padding">5</property> <property name="right_padding">5</property>
<child> <child>
<object class="GtkHBox" id="hbox1"> <object class="GtkGrid">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="column_homogeneous">True</property>
<child> <child>
<object class="GtkLabel" id="label6"> <object class="GtkLabel" id="label6">
<property name="visible">True</property> <property name="visible">True</property>
...@@ -339,9 +363,8 @@ ...@@ -339,9 +363,8 @@
<property name="label" translatable="yes">Gain</property> <property name="label" translatable="yes">Gain</property>
</object> </object>
<packing> <packing>
<property name="expand">True</property> <property name="left_attach">0</property>
<property name="fill">True</property> <property name="top_attach">0</property>
<property name="position">0</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -351,9 +374,8 @@ ...@@ -351,9 +374,8 @@
<property name="model">gain_liststore</property> <property name="model">gain_liststore</property>
</object> </object>
<packing> <packing>
<property name="expand">True</property> <property name="left_attach">1</property>
<property name="fill">True</property> <property name="top_attach">0</property>
<property name="position">1</property>
</packing> </packing>
</child> </child>
</object> </object>
...@@ -378,8 +400,9 @@ ...@@ -378,8 +400,9 @@
</child> </child>
</object> </object>
<packing> <packing>
<property name="expand">True</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">False</property>
<property name="padding">2</property>
<property name="position">0</property> <property name="position">0</property>
</packing> </packing>
</child> </child>
......
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# DStat Interface - An interface for the open hardware DStat potentiostat
# Copyright (C) 2014 Michael D. M. Dryden -
# Wheeler Microfluidics Laboratory <http://microfluidics.utoronto.ca>
#
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os.path
from pkg_resources import parse_version
try:
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
except ImportError:
print "ERR: GTK not available"
sys.exit(1)
from ..errors import InputError, VarError
from ..dstat import state
mod_dir = os.path.dirname(os.path.abspath(__file__))
class adc_pot(object):
def __init__(self):
self.builder = Gtk.Builder()
self.builder.add_from_file(os.path.join(mod_dir,'adc_pot.glade'))
self.builder.connect_signals(self)
self.cell = Gtk.CellRendererText()
ui_keys = ['buffer_true',
'short_true',
'pga_index',
'srate_index',
'gain_index'
]
ui_cont = map(self.builder.get_object, ['buffer_checkbutton',
'short_checkbutton',
'pga_combobox',
'srate_combobox',
'gain_combobox'
]
)
self.ui = dict(zip(ui_keys, ui_cont))
#initialize comboboxes
self.ui['pga_index'].pack_start(self.cell, True)
self.ui['pga_index'].add_attribute(self.cell, 'text', 1)
self.ui['pga_index'].set_active(1)
self.ui['srate_index'].pack_start(self.cell, True)
self.ui['srate_index'].add_attribute(self.cell, 'text', 1)
self.ui['srate_index'].set_active(7)
self.gain_liststore = self.builder.get_object('gain_liststore')
self.ui['gain_index'].pack_start(self.cell, True)
self.ui['gain_index'].add_attribute(self.cell, 'text', 1)
# self.ui['gain_index'].set_active(2)
self._params = {}
@property
def params(self):
"""Dict of parameters."""
try:
self._get_params()
except InputError as e:
raise e
finally:
return self._params
def _get_params(self):
"""Updates self._params from UI."""
for i in self.ui:
self._params[i] = self.ui[i].get_active()
srate_model = self.ui['srate_index'].get_model()
self._params['adc_rate'] = srate_model[self._params['srate_index']][2]
srate = srate_model[self._params['srate_index']][1]
if srate.endswith("kHz"):
sample_rate = float(srate.rstrip(" kHz"))*1000
else:
sample_rate = float(srate.rstrip(" Hz"))
self._params['adc_rate_hz'] = sample_rate
pga_model = self.ui['pga_index'].get_model()
self._params['adc_pga'] = pga_model[self._params['pga_index']][2]
gain_model = self.ui['gain_index'].get_model()
self._params['gain'] = gain_model[self._params['gain_index']][2]
if self._params['gain_index'] not in range(len(gain_model)):
raise InputError(self._params['gain_index'],
"Select a potentiostat gain.")
@params.setter
def params(self, params):
if self._params is {}:
self._params = dict.fromkeys(self.ui.keys())
for i in self._params:
if i in params:
self._params[i] = params[i]
self._set_params()
def _set_params(self):
"""Updates UI with new parameters."""
for i in self.ui:
self.ui[i].set_active(self._params[i])
def set_version(self, boost=None):
""" Sets menus for DStat version. """
try:
if self.version == state.board_instance:
return
except AttributeError:
pass
self.version = state.board_instance
self.gain_liststore.clear()
for n, i in enumerate(self.version.gain_labels):
self.gain_liststore.append((n, i, str(n)))
self.ui['gain_index'].set_active(self.version.gain_default_index)
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.10"/>
<object class="GtkDialog" id="analysis_dialog">
<property name="can_focus">False</property>
<property name="border_width">5</property>
<property name="title" translatable="yes">Analysis Options…</property>
<property name="type_hint">dialog</property>
<child internal-child="vbox">
<object class="GtkBox" id="dialog-vbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<placeholder/>
</child>
<child>
<object class="GtkButton" id="ok_button">
<property name="label">gtk-ok</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkSpinButton" id="stats_start_spin">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="invisible_char"></property>
<property name="text" translatable="yes">0.00</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="adjustment">stats_start_adj</property>
<property name="climb_rate">0.050000000000000003</property>
<property name="digits">2</property>
<property name="numeric">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="stats_stop_spin">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="invisible_char"></property>
<property name="text" translatable="yes">0.00</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="adjustment">stats_stop_adj</property>
<property name="climb_rate">0.050000000000000003</property>
<property name="digits">2</property>
<property name="numeric">True</property>
<property name="update_policy">if-valid</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="stats_button">
<property name="label" translatable="yes">Generate Summary Stats</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="halign">center</property>
<property name="image_position">bottom</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="stats_start_button">
<property name="label" translatable="yes">Stat Start (mV or s)</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="hexpand">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="stats_stop_button">
<property name="label" translatable="yes">Stat Stop (mV or s)</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="hexpand">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="0">ok_button</action-widget>
</action-widgets>
</object>
<object class="GtkAdjustment" id="stats_start_adj">
<property name="lower">-3000</property>
<property name="upper">9999</property>
<property name="step_increment">0.5</property>
<property name="page_increment">10</property>
</object>
<object class="GtkAdjustment" id="stats_stop_adj">
<property name="lower">-3000</property>
<property name="upper">9999</property>
<property name="step_increment">0.5</property>
<property name="page_increment">10</property>
</object>
</interface>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.10"/>
<object class="GtkWindow" id="window1">
<property name="can_focus">False</property>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkViewport" id="viewport1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkBox" id="vbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="row_homogeneous">True</property>
<child>
<object class="GtkEntry" id="time_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="max_length">5</property>
<property name="invisible_char"></property>
<property name="width_chars">8</property>
<property name="text" translatable="yes">0</property>
<property name="xalign">1</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</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">Measurement Time (s)</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Resistor</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Trim Value (ADC units)</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">100 Ω</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">3 kΩ</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">4</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label6">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">30 kΩ</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">5</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">300 kΩ</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">6</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label8">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">3 MΩ</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">7</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label9">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">30 MΩ</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">8</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label10">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">100 MΩ</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">9</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="30k_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="max_length">6</property>
<property name="invisible_char"></property>
<property name="width_chars">8</property>
<property name="text" translatable="yes">0</property>
<property name="xalign">1</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">5</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="3k_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="max_length">6</property>
<property name="invisible_char"></property>
<property name="width_chars">8</property>
<property name="text" translatable="yes">0</property>
<property name="xalign">1</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">4</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="100_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="max_length">6</property>
<property name="invisible_char"></property>
<property name="width_chars">8</property>
<property name="text" translatable="yes">0</property>
<property name="xalign">1</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">3</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="300k_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="max_length">6</property>
<property name="invisible_char"></property>
<property name="width_chars">8</property>
<property name="text" translatable="yes">0</property>
<property name="xalign">1</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">6</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="3M_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="max_length">6</property>
<property name="invisible_char"></property>
<property name="width_chars">8</property>
<property name="text" translatable="yes">0</property>
<property name="xalign">1</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">7</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="30M_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="max_length">6</property>
<property name="invisible_char"></property>
<property name="width_chars">8</property>
<property name="text" translatable="yes">0</property>
<property name="xalign">1</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">8</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="100M_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="max_length">6</property>
<property name="invisible_char"></property>
<property name="width_chars">8</property>
<property name="text" translatable="yes">0</property>
<property name="xalign">1</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">9</property>
</packing>
</child>
<child>
<object class="GtkButton" id="read_button">
<property name="label" translatable="yes">Read from EEPROM</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_read_button_clicked" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">11</property>
</packing>
</child>
<child>
<object class="GtkButton" id="write_button">
<property name="label" translatable="yes">Write to EEPROM</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_write_button_clicked" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">12</property>
</packing>
</child>
<child>
<object class="GtkButton" id="measure_button">
<property name="label" translatable="yes">Measure</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_measure_button_clicked" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">10</property>
</packing>
</child>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="width">2</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<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="label13">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="label" translatable="yes">Measure with WE open.
Offsets cannot exceed 16 bit unsigned int.</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface> <interface>
<requires lib="gtk+" version="2.24"/> <requires lib="gtk+" version="3.10"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkListStore" id="ca_list"> <object class="GtkListStore" id="ca_list">
<columns> <columns>
<!-- column-name millivolts --> <!-- column-name millivolts -->
...@@ -18,29 +18,34 @@ ...@@ -18,29 +18,34 @@
<object class="GtkScrolledWindow" id="scrolledwindow1"> <object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="hscrollbar_policy">automatic</property> <property name="hexpand">True</property>
<property name="vscrollbar_policy">automatic</property> <property name="vexpand">True</property>
<child> <child>
<object class="GtkViewport" id="viewport1"> <object class="GtkViewport" id="viewport1">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="shadow_type">none</property> <property name="shadow_type">none</property>
<child> <child>
<object class="GtkVBox" id="vbox1"> <object class="GtkBox" id="vbox1">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child> <child>
<object class="GtkTable" id="table1"> <object class="GtkGrid">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="n_rows">3</property> <property name="row_homogeneous">True</property>
<property name="n_columns">2</property> <property name="column_homogeneous">True</property>
<child> <child>
<object class="GtkLabel" id="label1"> <object class="GtkLabel" id="label1">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="label" translatable="yes">Potential (mV)</property> <property name="label" translatable="yes">Potential (mV)</property>
</object> </object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkEntry" id="potential_entry"> <object class="GtkEntry" id="potential_entry">
...@@ -51,18 +56,13 @@ ...@@ -51,18 +56,13 @@
<property name="text" translatable="yes">0</property> <property name="text" translatable="yes">0</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<property name="truncate_multiline">True</property> <property name="truncate_multiline">True</property>
<property name="invisible_char_set">True</property>
<property name="caps_lock_warning">False</property> <property name="caps_lock_warning">False</property>
<property name="primary_icon_activatable">False</property> <property name="primary_icon_activatable">False</property>
<property name="secondary_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>
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="left_attach">1</property>
<property name="right_attach">2</property> <property name="top_attach">0</property>
<property name="x_options"/>
<property name="y_options">GTK_SHRINK</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -72,8 +72,8 @@ ...@@ -72,8 +72,8 @@
<property name="label" translatable="yes">Time (s)</property> <property name="label" translatable="yes">Time (s)</property>
</object> </object>
<packing> <packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property> <property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -85,20 +85,13 @@ ...@@ -85,20 +85,13 @@
<property name="text" translatable="yes">0</property> <property name="text" translatable="yes">0</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<property name="truncate_multiline">True</property> <property name="truncate_multiline">True</property>
<property name="invisible_char_set">True</property>
<property name="caps_lock_warning">False</property> <property name="caps_lock_warning">False</property>
<property name="primary_icon_activatable">False</property> <property name="primary_icon_activatable">False</property>
<property name="secondary_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>
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property> <property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options"/>
<property name="y_options">GTK_SHRINK</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -111,8 +104,8 @@ ...@@ -111,8 +104,8 @@
<signal name="clicked" handler="on_add_button_clicked" swapped="no"/> <signal name="clicked" handler="on_add_button_clicked" swapped="no"/>
</object> </object>
<packing> <packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property> <property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -126,29 +119,26 @@ ...@@ -126,29 +119,26 @@
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property> <property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing> </packing>
</child> </child>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">False</property>
<property name="padding">5</property>
<property name="position">0</property> <property name="position">0</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkVBox" id="vbox2"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child> <child>
<object class="GtkTreeView" id="treeview"> <object class="GtkTreeView" id="treeview">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="model">ca_list</property> <property name="model">ca_list</property>
<property name="headers_clickable">False</property>
<property name="reorderable">True</property> <property name="reorderable">True</property>
<property name="rules_hint">True</property> <property name="rules_hint">True</property>
<property name="enable_search">False</property> <property name="enable_search">False</property>
...@@ -157,6 +147,9 @@ ...@@ -157,6 +147,9 @@
<property name="show_expanders">False</property> <property name="show_expanders">False</property>
<property name="rubber_banding">True</property> <property name="rubber_banding">True</property>
<property name="enable_grid_lines">both</property> <property name="enable_grid_lines">both</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
</object> </object>
<packing> <packing>
<property name="expand">True</property> <property name="expand">True</property>
...@@ -169,7 +162,6 @@ ...@@ -169,7 +162,6 @@
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="spacing">2</property> <property name="spacing">2</property>
<property name="has_resize_grip">False</property>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
......
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface> <interface>
<requires lib="gtk+" version="2.24"/> <requires lib="gtk+" version="3.10"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkWindow" id="window1"> <object class="GtkWindow" id="window1">
<property name="can_focus">False</property> <property name="can_focus">False</property>
<child> <child>
<object class="GtkScrolledWindow" id="scrolledwindow1"> <object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="hscrollbar_policy">automatic</property> <property name="hexpand">True</property>
<property name="vscrollbar_policy">automatic</property> <property name="vexpand">True</property>
<child> <child>
<object class="GtkViewport" id="viewport1"> <object class="GtkViewport" id="viewport1">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="shadow_type">none</property> <property name="shadow_type">none</property>
<child> <child>
<object class="GtkVBox" id="vbox1"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child> <child>
<object class="GtkFrame" id="frame1"> <object class="GtkFrame" id="frame1">
<property name="visible">True</property> <property name="visible">True</property>
...@@ -33,21 +34,21 @@ ...@@ -33,21 +34,21 @@
<property name="left_padding">5</property> <property name="left_padding">5</property>
<property name="right_padding">5</property> <property name="right_padding">5</property>
<child> <child>
<object class="GtkTable" id="table1"> <object class="GtkGrid">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="n_rows">3</property> <property name="row_homogeneous">True</property>
<property name="n_columns">3</property> <property name="column_homogeneous">True</property>
<child> <child>
<object class="GtkLabel" id="label3"> <object class="GtkLabel" id="label3">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="vexpand">False</property>
<property name="label" translatable="yes">Potential (mV)</property> <property name="label" translatable="yes">Potential (mV)</property>
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="left_attach">1</property>
<property name="right_attach">2</property> <property name="top_attach">0</property>
<property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -58,8 +59,7 @@ ...@@ -58,8 +59,7 @@
</object> </object>
<packing> <packing>
<property name="left_attach">2</property> <property name="left_attach">2</property>
<property name="right_attach">3</property> <property name="top_attach">0</property>
<property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -68,7 +68,8 @@ ...@@ -68,7 +68,8 @@
<property name="can_focus">False</property> <property name="can_focus">False</property>
</object> </object>
<packing> <packing>
<property name="y_options">GTK_FILL</property> <property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -78,9 +79,8 @@ ...@@ -78,9 +79,8 @@
<property name="label" translatable="yes">Cleaning</property> <property name="label" translatable="yes">Cleaning</property>
</object> </object>
<packing> <packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property> <property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -90,9 +90,8 @@ ...@@ -90,9 +90,8 @@
<property name="label" translatable="yes">Deposition</property> <property name="label" translatable="yes">Deposition</property>
</object> </object>
<packing> <packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property> <property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -103,19 +102,12 @@ ...@@ -103,19 +102,12 @@
<property name="width_chars">8</property> <property name="width_chars">8</property>
<property name="text" translatable="yes">0</property> <property name="text" translatable="yes">0</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property> <property name="primary_icon_activatable">False</property>
<property name="secondary_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>
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property> <property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options"/>
<property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -126,19 +118,12 @@ ...@@ -126,19 +118,12 @@
<property name="width_chars">8</property> <property name="width_chars">8</property>
<property name="text" translatable="yes">0</property> <property name="text" translatable="yes">0</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property> <property name="primary_icon_activatable">False</property>
<property name="secondary_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>
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property> <property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options"/>
<property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -149,19 +134,12 @@ ...@@ -149,19 +134,12 @@
<property name="width_chars">8</property> <property name="width_chars">8</property>
<property name="text" translatable="yes">0</property> <property name="text" translatable="yes">0</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property> <property name="primary_icon_activatable">False</property>
<property name="secondary_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>
</object> </object>
<packing> <packing>
<property name="left_attach">2</property> <property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">2</property> <property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options"/>
<property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -172,19 +150,12 @@ ...@@ -172,19 +150,12 @@
<property name="width_chars">8</property> <property name="width_chars">8</property>
<property name="text" translatable="yes">0</property> <property name="text" translatable="yes">0</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property> <property name="primary_icon_activatable">False</property>
<property name="secondary_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>
</object> </object>
<packing> <packing>
<property name="left_attach">2</property> <property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">1</property> <property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options"/>
<property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
</object> </object>
...@@ -221,13 +192,11 @@ ...@@ -221,13 +192,11 @@
<property name="left_padding">5</property> <property name="left_padding">5</property>
<property name="right_padding">5</property> <property name="right_padding">5</property>
<child> <child>
<object class="GtkTable" id="table2"> <object class="GtkGrid">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="n_rows">5</property> <property name="row_homogeneous">True</property>
<property name="n_columns">2</property> <property name="column_homogeneous">True</property>
<property name="column_spacing">10</property>
<property name="homogeneous">True</property>
<child> <child>
<object class="GtkLabel" id="label8"> <object class="GtkLabel" id="label8">
<property name="visible">True</property> <property name="visible">True</property>
...@@ -235,7 +204,8 @@ ...@@ -235,7 +204,8 @@
<property name="label" translatable="yes">Start (mV)</property> <property name="label" translatable="yes">Start (mV)</property>
</object> </object>
<packing> <packing>
<property name="y_options">GTK_FILL</property> <property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -245,9 +215,8 @@ ...@@ -245,9 +215,8 @@
<property name="label" translatable="yes">Vertex 1 (mV)</property> <property name="label" translatable="yes">Vertex 1 (mV)</property>
</object> </object>
<packing> <packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property> <property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -257,9 +226,8 @@ ...@@ -257,9 +226,8 @@
<property name="label" translatable="yes">Vertex 2 (mV)</property> <property name="label" translatable="yes">Vertex 2 (mV)</property>
</object> </object>
<packing> <packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property> <property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -270,18 +238,12 @@ ...@@ -270,18 +238,12 @@
<property name="width_chars">8</property> <property name="width_chars">8</property>
<property name="text" translatable="yes">0</property> <property name="text" translatable="yes">0</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property> <property name="primary_icon_activatable">False</property>
<property name="secondary_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>
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="left_attach">1</property>
<property name="right_attach">2</property> <property name="top_attach">0</property>
<property name="x_options"/>
<property name="y_options">GTK_FILL</property>
<property name="y_padding">3</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -292,20 +254,12 @@ ...@@ -292,20 +254,12 @@
<property name="width_chars">8</property> <property name="width_chars">8</property>
<property name="text" translatable="yes">0</property> <property name="text" translatable="yes">0</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property> <property name="primary_icon_activatable">False</property>
<property name="secondary_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>
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property> <property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options"/>
<property name="y_options">GTK_FILL</property>
<property name="y_padding">3</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -316,20 +270,12 @@ ...@@ -316,20 +270,12 @@
<property name="width_chars">8</property> <property name="width_chars">8</property>
<property name="text" translatable="yes">0</property> <property name="text" translatable="yes">0</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property> <property name="primary_icon_activatable">False</property>
<property name="secondary_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>
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property> <property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options"/>
<property name="y_options">GTK_FILL</property>
<property name="y_padding">3</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -339,9 +285,8 @@ ...@@ -339,9 +285,8 @@
<property name="label" translatable="yes">Slope (mV/s)</property> <property name="label" translatable="yes">Slope (mV/s)</property>
</object> </object>
<packing> <packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property> <property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -351,9 +296,8 @@ ...@@ -351,9 +296,8 @@
<property name="label" translatable="yes">Scans</property> <property name="label" translatable="yes">Scans</property>
</object> </object>
<packing> <packing>
<property name="left_attach">0</property>
<property name="top_attach">4</property> <property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -364,20 +308,12 @@ ...@@ -364,20 +308,12 @@
<property name="width_chars">8</property> <property name="width_chars">8</property>
<property name="text" translatable="yes">0</property> <property name="text" translatable="yes">0</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property> <property name="primary_icon_activatable">False</property>
<property name="secondary_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>
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property> <property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options"/>
<property name="y_options">GTK_FILL</property>
<property name="y_padding">3</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -388,20 +324,12 @@ ...@@ -388,20 +324,12 @@
<property name="width_chars">8</property> <property name="width_chars">8</property>
<property name="text" translatable="yes">0</property> <property name="text" translatable="yes">0</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property> <property name="primary_icon_activatable">False</property>
<property name="secondary_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>
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">4</property> <property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options"/>
<property name="y_options">GTK_FILL</property>
<property name="y_padding">3</property>
</packing> </packing>
</child> </child>
</object> </object>
...@@ -420,7 +348,7 @@ ...@@ -420,7 +348,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">False</property> <property name="fill">False</property>
<property name="padding">2</property> <property name="padding">1</property>
<property name="position">1</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
......
from __future__ import division, absolute_import, print_function, unicode_literals
import logging
logger = logging.getLogger(__name__)
from collections import OrderedDict
try:
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
except ImportError:
print("ERR: GTK not available")
sys.exit(1)
class DataPage(object):
def __init__(self, notebook, name="Data"):
"""Make new notebook page and adds to notebook."""
self.box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.combobox = Gtk.ComboBoxText()
self.scroll = Gtk.ScrolledWindow(vexpand=True)
self.textview = Gtk.TextView(cursor_visible=False, monospace=True,
editable=False)
self.scroll.add(self.textview)
self.box.add(self.combobox)
self.box.add(self.scroll)
self.name = name
self.buffers = {}
self.combobox.connect('changed', self.combobox_changed)
notebook.append_page(self.box, Gtk.Label(label=name))
def add_exp(self, exp):
"""Add all data from exp to page."""
for name, df in exp.df.items():
self.combobox.append(id=name, text=name)
self.buffers[name] = Gtk.TextBuffer()
self.buffers[name].set_text(df.to_string())
self.box.show_all()
self.combobox.set_active(0)
def clear_exps(self):
self.combobox.remove_all()
self.buffers = {}
def combobox_changed(self, object):
"""Switch displayed data buffer."""
try:
self.textview.set_buffer(
self.buffers[self.combobox.get_active_id()]
)
except KeyError:
pass
class InfoPage(object):
def __init__(self, notebook, name="Info"):
"""Make new notebook page and adds to notebook."""
self.box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.buffer = Gtk.TextBuffer()
self.scroll = Gtk.ScrolledWindow(vexpand=True)
self.textview = Gtk.TextView(cursor_visible=False, monospace=True,
editable=False, buffer=self.buffer)
self.scroll.add(self.textview)
self.box.add(self.scroll)
self.name = name
notebook.append_page(self.box, Gtk.Label(label=name))
self.box.show_all()
def clear(self):
"""Clear buffer"""
self.buffer.set_text('')
def set_text(self, text):
self.buffer.set_text(text)
def add_line(self, line):
self.buffer.insert_at_cursor('{}\n'.format(line))
\ No newline at end of file