Commit d45b5938 authored by Guillaume Blanchy's avatar Guillaume Blanchy
Browse files

UI mqtt: working run_sequence and remove_data + fulldata to be fixed

Showing with 125 additions and 47 deletions
+125 -47
...@@ -6,7 +6,8 @@ import subprocess ...@@ -6,7 +6,8 @@ import subprocess
# launch webserver # launch webserver
from ohmpi.utils import change_config from ohmpi.utils import change_config
change_config('../configs/config_mb_2023.py', verbose=False) #change_config('../configs/config_mb_2023.py', verbose=False)
change_config('../configs/config_mb_2023_4_mux_2023.py', verbose=False)
from ohmpi.ohmpi import OhmPi from ohmpi.ohmpi import OhmPi
from ohmpi.config import OHMPI_CONFIG from ohmpi.config import OHMPI_CONFIG
......
...@@ -84,8 +84,11 @@ if within_ohmpi: ...@@ -84,8 +84,11 @@ if within_ohmpi:
print('Starting test with OhmPi.') print('Starting test with OhmPi.')
k = OhmPi() k = OhmPi()
k.get_data()
# k.load_sequence(os.path.join(os.path.dirname(__file__), '../sequences/test_circuit_1423.txt')) # k.load_sequence(os.path.join(os.path.dirname(__file__), '../sequences/test_circuit_1423.txt'))
k.reset_mux() # k.reset_mux()
# k.run_sequence(injection_duration=0.2)
# k.rs_check(tx_volt=4)
# k.test_mux(mux_id=None, activation_time=0.2) # k.test_mux(mux_id=None, activation_time=0.2)
# k._hw.switch_mux([A, B, M, N], state='on') # k._hw.switch_mux([A, B, M, N], state='on')
# k._hw.vab_square_wave(12.,1., cycles=2) # k._hw.vab_square_wave(12.,1., cycles=2)
...@@ -99,11 +102,11 @@ if within_ohmpi: ...@@ -99,11 +102,11 @@ if within_ohmpi:
# k._hw.switch_mux([A, B, M, N], state='off') # k._hw.switch_mux([A, B, M, N], state='off')
# print(f'OhmPiHardware Resistance: {k._hw.last_rho :.2f} ohm, dev. {k._hw.last_dev:.2f} %, rx bias: {k._hw.rx._bias:.2f} mV') # print(f'OhmPiHardware Resistance: {k._hw.last_rho :.2f} ohm, dev. {k._hw.last_dev:.2f} %, rx bias: {k._hw.rx._bias:.2f} mV')
# k._hw._plot_readings() # k._hw._plot_readings()
A, B, M, N = (16, 13, 15, 14) # A, B, M, N = (16, 13, 15, 14)
A, B, M, N = (1, 4, 2, 3) # A, B, M, N = (1, 4, 2, 3)
d = k.run_measurement([A, B, M, N], injection_duration=0.5, nb_stack=2, duty_cycle=0.5) # d = k.run_measurement([A, B, M, N], injection_duration=0.5, nb_stack=2, duty_cycle=0.5)
print(d) # print(d)
k._hw._plot_readings() # k._hw._plot_readings()
# print(f'OhmPiHardware: Resistance: {k._hw.last_resistance() :.2f} ohm, dev. {k._hw.last_dev():.2f} %, sp: {k._hw.sp:.2f} mV, rx bias: {k._hw.rx._bias:.2f} mV') # print(f'OhmPiHardware: Resistance: {k._hw.last_resistance() :.2f} ohm, dev. {k._hw.last_dev():.2f} %, sp: {k._hw.sp:.2f} mV, rx bias: {k._hw.rx._bias:.2f} mV')
# print(f'OhmPi: Resistance: {d["R [ohm]"] :.2f} ohm, dev. {d["R_std [%]"]:.2f} %, rx bias: {k._hw.rx._bias:.2f} mV') # print(f'OhmPi: Resistance: {d["R [ohm]"] :.2f} ohm, dev. {d["R_std [%]"]:.2f} %, rx bias: {k._hw.rx._bias:.2f} mV')
# k._hw._plot_readings(save_fig=False) # k._hw._plot_readings(save_fig=False)
......
env.sh 0 → 100755
# execute this file with "source env.sh"
PYTHONPATH=`pwd`
source ./ohmpy/bin/activate
...@@ -310,18 +310,6 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl ...@@ -310,18 +310,6 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl
} }
console.log(formVals) console.log(formVals)
// define callback to send settings to Pi
function configCallback() {
sendCommand(JSON.stringify({
'cmd': 'update_settings',
'kwargs': {
'config': formVals
}
}), function(x) {
console.log('update_settings', x)
})
}
// deal with the potential file containing the sequence // deal with the potential file containing the sequence
// https://stackoverflow.com/questions/19038919/is-it-possible-to-upload-a-text-file-to-input-in-html-js // https://stackoverflow.com/questions/19038919/is-it-possible-to-upload-a-text-file-to-input-in-html-js
if (!window.FileReader) { if (!window.FileReader) {
...@@ -333,8 +321,27 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl ...@@ -333,8 +321,27 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl
const reader = new FileReader() const reader = new FileReader()
reader.readAsText(input.files[0]) reader.readAsText(input.files[0])
reader.addEventListener('load', () => { reader.addEventListener('load', () => {
formVals['sequence'] = reader.result // parse the file and make it a list of list of int
console.log('file==', reader.result) var a = reader.result.split(/\r?\n|\r|\n/g)
var seq = new Array()
var eof = false
for (var i = 0; i < a.length; i++) {
b = a[i].split(' ')
var arr = new Array(4)
for (var j = 0; j < b.length; j++) {
val = parseInt(b[j])
if (isNaN(val) == true) {
eof = true
break
}
arr[j] = val
}
if (eof == true) {
break
}
seq.push(arr)
}
formVals['sequence'] = seq
configCallback() configCallback()
}, false) }, false)
} else { } else {
...@@ -343,6 +350,17 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl ...@@ -343,6 +350,17 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl
configCallback() configCallback()
} }
// define callback to send settings to Pi
function configCallback() {
sendCommand(JSON.stringify({
'cmd': 'update_settings',
'kwargs': {
'settings': formVals
}
}), function(x) {
console.log('update_settings', x)
})
}
} }
let saveConfigBtn = document.getElementById('saveConfigBtn') let saveConfigBtn = document.getElementById('saveConfigBtn')
...@@ -430,18 +448,24 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl ...@@ -430,18 +448,24 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl
let ypos = [] let ypos = []
let app = [] let app = []
for (let i = 0; i < a.length; i++) { for (let i = 0; i < a.length; i++) {
let ab = (a[i] + b[i])/2 let emin = Math.min(...[a[i], b[i], m[i], n[i]])
let mn = (m[i] + n[i])/2 let emax = Math.max(...[a[i], b[i], m[i], n[i]])
let dist = Math.abs(ab - mn) let dist = Math.abs(emax - emin)
xpos.push(Math.min(ab, mn) + dist/2) xpos.push(emin + dist/2)
ypos.push(Math.sqrt(2)/2*dist) ypos.push(Math.sqrt(2)/2 * dist)
// let ab = (a[i] + b[i])/2
// let mn = (m[i] + n[i])/2
// xpos.push(Math.min(ab, mn) + dist/2)
// ypos.push(Math.sqrt(2)/2*dist)
let am = Math.abs(a[i] - m[i]) let am = Math.abs(a[i] - m[i])
let bm = Math.abs(b[i] - m[i]) let bm = Math.abs(b[i] - m[i])
let an = Math.abs(a[i] - n[i]) let an = Math.abs(a[i] - n[i])
let bn = Math.abs(a[i] - n[i]) let bn = Math.abs(a[i] - n[i])
let K = (2*Math.PI)/((1/am)-(1/an)-(1/an)+(1/bn)) let K = (2*Math.PI)/((1/am)-(1/an)-(1/an)+(1/bn))
app.push(df['rho'][i]*-K) app.push(df['rho'][i]*K)
} }
console.log('xpos', xpos)
console.log('ypos', ypos)
console.log(app) console.log(app)
// update the trace and redraw the figure // update the trace and redraw the figure
trace['x'] = xpos trace['x'] = xpos
...@@ -469,7 +493,7 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl ...@@ -469,7 +493,7 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl
// run RS check // run RS check
function rsBtnFunc() { function rsBtnFunc() {
sendCommand('{"cmd": "rsCheck"}', function (res) { sendCommand('{"cmd": "rs_check"}', function (res) {
// update the bar plot // update the bar plot
rsdata.push({ rsdata.push({
x: res['data']['AB'], x: res['data']['AB'],
...@@ -707,7 +731,7 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl ...@@ -707,7 +731,7 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl
// remove data // remove data
function removeDataBtnFunc() { function removeDataBtnFunc() {
sendCommand('{"cmd": "removeData"}',function(x) { sendCommand('{"cmd": "remove_data"}',function(x) {
data = {} data = {}
output.innerHTML = 'Status: ' + x['status'] + ' (all data cleared)' output.innerHTML = 'Status: ' + x['status'] + ' (all data cleared)'
console.log('all data removed') console.log('all data removed')
......
This diff is collapsed.
...@@ -35,9 +35,34 @@ HARDWARE_CONFIG = { ...@@ -35,9 +35,34 @@ HARDWARE_CONFIG = {
# overwritten by properties defined in each the board dict below. # overwritten by properties defined in each the board dict below.
# if defined in board specs, values out of specs will be bounded to remain in specs # if defined in board specs, values out of specs will be bounded to remain in specs
# omitted properties in config will be set to board specs default values if they exist # omitted properties in config will be set to board specs default values if they exist
{'boards': {}, {'boards':
{'mux_A':
{'model': 'mux_2023_0_X',
'mux_tca_address': 0x70,
'roles': {'A': 'X'},
'cabling': {(i, j): ('mux_A', i) for j in ['A'] for i in range(1, 65)},
'voltage_max': 12.},
'mux_B':
{'model': 'mux_2023_0_X',
'mux_tca_address': 0x71,
'roles': {'B': 'X'},
'cabling': {(i, j): ('mux_B', i) for j in ['B'] for i in range(1, 65)},
'voltage_max': 12.},
'mux_M':
{'model': 'mux_2023_0_X',
'mux_tca_address': 0x72,
'roles': {'M': 'X'},
'cabling': {(i, j): ('mux_M', i) for j in ['M'] for i in range(1, 65)},
'voltage_max': 12.},
'mux_N':
{'model': 'mux_2023_0_X',
'mux_tca_address': 0x73,
'roles': {'N': 'X'},
'cabling': {(i, j): ('mux_N', i) for j in ['N'] for i in range(1, 65)},
'voltage_max': 12.},
},
'default': {'interface_name': 'i2c', 'default': {'interface_name': 'i2c',
'voltage_max': 100., 'voltage_max': 12.,
'current_max': 3.} 'current_max': 3.}
} }
} }
...@@ -45,7 +70,7 @@ HARDWARE_CONFIG = { ...@@ -45,7 +70,7 @@ HARDWARE_CONFIG = {
# SET THE LOGGING LEVELS, MQTT BROKERS AND MQTT OPTIONS ACCORDING TO YOUR NEEDS # SET THE LOGGING LEVELS, MQTT BROKERS AND MQTT OPTIONS ACCORDING TO YOUR NEEDS
# Execution logging configuration # Execution logging configuration
EXEC_LOGGING_CONFIG = { EXEC_LOGGING_CONFIG = {
'logging_level': logging.DEBUG, # TODO: set logging level back to INFO 'logging_level': logging.INFO, # TODO: set logging level back to INFO
'log_file_logging_level': logging.DEBUG, 'log_file_logging_level': logging.DEBUG,
'logging_to_console': True, 'logging_to_console': True,
'file_name': f'exec{logging_suffix}.log', 'file_name': f'exec{logging_suffix}.log',
......
...@@ -186,18 +186,21 @@ class OhmPi(object): ...@@ -186,18 +186,21 @@ class OhmPi(object):
os.mkdir(ddir) os.mkdir(ddir)
last_measurement = deepcopy(last_measurement) last_measurement = deepcopy(last_measurement)
# TODO need to make all the full data of the same size (pre-populate
# readings with NaN in hardware_system.OhmPiHardware.read_values())
if 'fulldata' in last_measurement: if 'fulldata' in last_measurement:
d = last_measurement['fulldata'] # d = last_measurement['fulldata']
n = d.shape[0] # n = d.shape[0]
if n > 1: # if n > 1:
idic = dict(zip(['i' + str(i) for i in range(n)], d[:, 0])) # idic = dict(zip(['i' + str(i) for i in range(n)], d[:, 0]))
udic = dict(zip(['u' + str(i) for i in range(n)], d[:, 1])) # udic = dict(zip(['u' + str(i) for i in range(n)], d[:, 1]))
tdic = dict(zip(['t' + str(i) for i in range(n)], d[:, 2])) # tdic = dict(zip(['t' + str(i) for i in range(n)], d[:, 2]))
last_measurement.update(idic) # last_measurement.update(idic)
last_measurement.update(udic) # last_measurement.update(udic)
last_measurement.update(tdic) # last_measurement.update(tdic)
last_measurement.pop('fulldata') last_measurement.pop('fulldata')
if os.path.isfile(filename): if os.path.isfile(filename):
# Load data file and append data to it # Load data file and append data to it
with open(filename, 'a') as f: with open(filename, 'a') as f:
...@@ -265,11 +268,15 @@ class OhmPi(object): ...@@ -265,11 +268,15 @@ class OhmPi(object):
with open(os.path.join(ddir, fname), 'r') as f: with open(os.path.join(ddir, fname), 'r') as f:
headers = f.readline().split(',') headers = f.readline().split(',')
# fixing possible incompatibilities with cod eversion # fixing possible incompatibilities with code version
for i, header in enumerate(headers): for i, header in enumerate(headers):
if header == 'R [ohm]': if header == 'R [ohm]':
headers[i] = 'R [Ohm]' headers[i] = 'R [Ohm]'
icols = np.where(np.in1d(headers, ['A', 'B', 'M', 'N', 'R [Ohm]']))[0] icols = list(np.where(np.in1d(headers, ['A', 'B', 'M', 'N', 'R [Ohm]']))[0])
print(headers)
print('+++++', icols)
print(np.array(headers)[np.array(icols)])
print(np.loadtxt(os.path.join(ddir, fname), delimiter=',', skiprows=1, usecols=icols).shape)
data = np.loadtxt(os.path.join(ddir, fname), delimiter=',', data = np.loadtxt(os.path.join(ddir, fname), delimiter=',',
skiprows=1, usecols=icols) skiprows=1, usecols=icols)
data = data[None, :] if len(data.shape) == 1 else data data = data[None, :] if len(data.shape) == 1 else data
...@@ -414,8 +421,9 @@ class OhmPi(object): ...@@ -414,8 +421,9 @@ class OhmPi(object):
Unique command identifier Unique command identifier
""" """
self.exec_logger.debug(f'Removing all data following command {cmd_id}') self.exec_logger.debug(f'Removing all data following command {cmd_id}')
rmtree('data') datadir = os.path.join(os.path.dirname(__file__), '../data')
os.mkdir('data') rmtree(datadir)
os.mkdir(datadir)
def restart(self, cmd_id=None): def restart(self, cmd_id=None):
"""Restarts the Raspberry Pi """Restarts the Raspberry Pi
...@@ -490,6 +498,7 @@ class OhmPi(object): ...@@ -490,6 +498,7 @@ class OhmPi(object):
# duty_cycle = kwargs.pop('duty_cycle', self.settings['duty_cycle']) # duty_cycle = kwargs.pop('duty_cycle', self.settings['duty_cycle'])
# tx_volt = float(kwargs.pop('tx_volt', self.settings['tx_volt'])) # tx_volt = float(kwargs.pop('tx_volt', self.settings['tx_volt']))
bypass_check = kwargs['bypass_check'] if 'bypass_check' in kwargs.keys() else False bypass_check = kwargs['bypass_check'] if 'bypass_check' in kwargs.keys() else False
d = {}
if self.switch_mux_on(quad, bypass_check=bypass_check, cmd_id=cmd_id): if self.switch_mux_on(quad, bypass_check=bypass_check, cmd_id=cmd_id):
self._hw.vab_square_wave(tx_volt, cycle_duration=injection_duration*2/duty_cycle, cycles=nb_stack, duty_cycle=duty_cycle) self._hw.vab_square_wave(tx_volt, cycle_duration=injection_duration*2/duty_cycle, cycles=nb_stack, duty_cycle=duty_cycle)
if 'delay' in kwargs.keys(): if 'delay' in kwargs.keys():
...@@ -720,7 +729,7 @@ class OhmPi(object): ...@@ -720,7 +729,7 @@ class OhmPi(object):
# TODO: we could build a smarter RS-Check by selecting adjacent electrodes based on their locations and try to # TODO: we could build a smarter RS-Check by selecting adjacent electrodes based on their locations and try to
# isolate electrodes that are responsible for high resistances (ex: AB high, AC low, BC high # isolate electrodes that are responsible for high resistances (ex: AB high, AC low, BC high
# -> might be a problem at B (cf what we did with WofE) # -> might be a problem at B (cf what we did with WofE)
def rs_check(self, tx_volt=12., cmd_id=None): def rs_check(self, tx_volt=5., cmd_id=None):
# TODO: add a default value for rs-check in config.py import it in ohmpi.py and add it in rs_check definition # TODO: add a default value for rs-check in config.py import it in ohmpi.py and add it in rs_check definition
"""Checks contact resistances """Checks contact resistances
...@@ -731,6 +740,9 @@ class OhmPi(object): ...@@ -731,6 +740,9 @@ class OhmPi(object):
cmd_id : str, optional cmd_id : str, optional
Unique command identifier Unique command identifier
""" """
self._hw.tx.pwr.voltage = float(tx_volt)
# create custom sequence where MN == AB # create custom sequence where MN == AB
# we only check the electrodes which are in the sequence (not all might be connected) # we only check the electrodes which are in the sequence (not all might be connected)
if self.sequence is None: if self.sequence is None:
...@@ -912,6 +924,8 @@ class OhmPi(object): ...@@ -912,6 +924,8 @@ class OhmPi(object):
try: try:
if isinstance(settings, dict): if isinstance(settings, dict):
self.settings.update(settings) self.settings.update(settings)
if 'sequence' in settings:
self.set_sequence(settings['sequence'])
else: else:
with open(settings) as json_file: with open(settings) as json_file:
dic = json.load(json_file) dic = json.load(json_file)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment