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

Updates for working webinterface with new process_commands()

- fix passing sequence with new process_commands
- update process_commands as json.loads() parse recursively
- update index.html pseudo-section (+ hover info)
- comment double info log in run_sequence_async
- fix update_settings by adding '_settings' to common cmd_id with set_sequence (from http_interface)
Showing with 284 additions and 131 deletions
+284 -131
...@@ -7,6 +7,8 @@ from termcolor import colored ...@@ -7,6 +7,8 @@ from termcolor import colored
import pandas as pd import pandas as pd
import shutil import shutil
import time import time
import numpy as np
from io import StringIO
import threading import threading
import paho.mqtt.client as mqtt_client import paho.mqtt.client as mqtt_client
import paho.mqtt.publish as publish import paho.mqtt.publish as publish
...@@ -121,12 +123,10 @@ class MyServer(SimpleHTTPRequestHandler): ...@@ -121,12 +123,10 @@ class MyServer(SimpleHTTPRequestHandler):
received = False received = False
cmd_id = uuid.uuid4().hex cmd_id = uuid.uuid4().hex
dic = json.loads(self.rfile.read(int(self.headers['Content-Length']))) dic = json.loads(self.rfile.read(int(self.headers['Content-Length'])))
#print('++', dic, cmd_id)
rdic = {} # response dictionary rdic = {} # response dictionary
if dic['cmd'] == 'run_multiple_sequences': if dic['cmd'] == 'run_multiple_sequences':
payload = json.dumps({'cmd_id': cmd_id, 'cmd': 'run_multiple_sequences'}) payload = json.dumps({'cmd_id': cmd_id, 'cmd': 'run_multiple_sequences'})
publish.single(payload=payload, **publisher_config) publish.single(payload=payload, **publisher_config)
elif dic['cmd'] == 'interrupt': elif dic['cmd'] == 'interrupt':
payload = json.dumps({'cmd_id': cmd_id, 'cmd': 'interrupt'}) payload = json.dumps({'cmd_id': cmd_id, 'cmd': 'interrupt'})
publish.single(payload=payload, **publisher_config) publish.single(payload=payload, **publisher_config)
...@@ -151,13 +151,14 @@ class MyServer(SimpleHTTPRequestHandler): ...@@ -151,13 +151,14 @@ class MyServer(SimpleHTTPRequestHandler):
shutil.rmtree('data') shutil.rmtree('data')
os.mkdir('data') os.mkdir('data')
elif dic['cmd'] == 'update_settings': elif dic['cmd'] == 'update_settings':
# ohmpi.stop()
if 'sequence' in dic['config'].keys() and dic['config']['sequence'] is not None: if 'sequence' in dic['config'].keys() and dic['config']['sequence'] is not None:
sequence = dic['config']['sequence'] sequence = dic['config'].pop('sequence', None)
dic['config'].pop('sequence', None) sequence = np.loadtxt(StringIO(sequence)).astype(int).tolist() # list of list
payload = json.dumps({'cmd_id': cmd_id, 'cmd': 'set_sequence', 'args': sequence}) # we pass the sequence as a list of list as this object is easier to parse for the json.loads()
# of ohmpi._process_commands()
payload = json.dumps({'cmd_id': cmd_id, 'cmd': 'set_sequence', 'kwargs': {'sequence': sequence}})
publish.single(payload=payload, **publisher_config) publish.single(payload=payload, **publisher_config)
payload = json.dumps({'cmd_id': cmd_id, 'cmd': 'update_settings', 'args': dic['config']}) payload = json.dumps({'cmd_id': cmd_id + '_settings', 'cmd': 'update_settings', 'kwargs': {'config': dic['config']}})
cdic = dic['config'] cdic = dic['config']
publish.single(payload=payload, **publisher_config) publish.single(payload=payload, **publisher_config)
elif dic['cmd'] == 'invert': elif dic['cmd'] == 'invert':
...@@ -165,15 +166,19 @@ class MyServer(SimpleHTTPRequestHandler): ...@@ -165,15 +166,19 @@ class MyServer(SimpleHTTPRequestHandler):
elif dic['cmd'] == 'getResults': elif dic['cmd'] == 'getResults':
pass pass
elif dic['cmd'] == 'rsCheck': elif dic['cmd'] == 'rsCheck':
# ohmpi.rs_check()
payload = json.dumps({'cmd_id': cmd_id, 'cmd': 'rs_check'}) payload = json.dumps({'cmd_id': cmd_id, 'cmd': 'rs_check'})
publish.single(payload=payload, **publisher_config) publish.single(payload=payload, **publisher_config)
elif dic['cmd'] == 'getRsCheck':
fnames = sorted([fname for fname in os.listdir('data/') if fname[-7:] == '_rs.csv']) fnames = sorted([fname for fname in os.listdir('data/') if fname[-7:] == '_rs.csv'])
df = pd.read_csv('data/' + fnames[-1]) if len(fnames) > 0:
ddic = { df = pd.read_csv('data/' + fnames[-1])
'AB': (df['A'].astype('str') + '-' + df['B'].astype(str)).tolist(), ddic = {
'res': df['RS [kOhm]'].tolist() 'AB': (df['A'].astype('str') + '-' + df['B'].astype(str)).tolist(),
} 'res': df['RS [kOhm]'].tolist()
}
else:
ddic = {}
rdic['data'] = ddic rdic['data'] = ddic
elif dic['cmd'] == 'download': elif dic['cmd'] == 'download':
shutil.make_archive('data', 'zip', 'data') shutil.make_archive('data', 'zip', 'data')
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
<input id="cmax" type="number" value=""/> <input id="cmax" type="number" value=""/>
<button id="capplyBtn" type="button" class="btn btn-info">Apply</button> <button id="capplyBtn" type="button" class="btn btn-info">Apply</button>
<div id="gd"></div> <div id="gd"></div>
<div id="hoverinfo" style="margin-left:80px;"></div>
<div class="mb3 row"> <div class="mb3 row">
<label for="quadSelect">Quadrupole:</label> <label for="quadSelect">Quadrupole:</label>
<div class="col-sm-10"> <div class="col-sm-10">
...@@ -52,6 +53,7 @@ ...@@ -52,6 +53,7 @@
<!-- RS check --> <!-- RS check -->
<button id="rsBtn" type="button" class="btn btn-info">Check contact resistance</button> <button id="rsBtn" type="button" class="btn btn-info">Check contact resistance</button>
<button id="getRsBtn" type="button" class="btn btn-info">Get contact resistance</button>
<button id="rsClearBtn" type="button" class="btn btn-info">Clear plot</button> <button id="rsClearBtn" type="button" class="btn btn-info">Clear plot</button>
<div id="rs"></div> <div id="rs"></div>
...@@ -60,12 +62,12 @@ ...@@ -60,12 +62,12 @@
<!-- <button id="invertBtn" type="button" class="btn btn-primary">Invert</button> --> <!-- <button id="invertBtn" type="button" class="btn btn-primary">Invert</button> -->
<a id="download"></a> <a id="download"></a>
<!-- Modal for configuration --> <!-- Modal for settings -->
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">OhmPi configuration</h5> <h5 class="modal-title" id="exampleModalLabel">OhmPi settings</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> <button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span> <span aria-hidden="true">&times;</span>
</button> </button>
...@@ -75,13 +77,13 @@ ...@@ -75,13 +77,13 @@
<div class="form-group row"> <div class="form-group row">
<label for="nbElectrodes" class="col-sm-2 col-form-label">Nb electrodes</label> <label for="nbElectrodes" class="col-sm-2 col-form-label">Nb electrodes</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="number" class="form-control-number" id="nbElectrodes" value="64"> <input type="number" class="form-control-number" id="nbElectrodes" value=64>
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label for="injectionDuration" class="col-sm-2 col-form-label">Injection duration [s]</label> <label for="injectionDuration" class="col-sm-2 col-form-label">Injection duration [s]</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="number" class="form-control-number" id="injectionDuration" value="0.2"> <input type="number" class="form-control-number" id="injectionDuration" value=0.2>
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
...@@ -139,6 +141,7 @@ ...@@ -139,6 +141,7 @@
let interv = null // hold interval for automatic data retrieval let interv = null // hold interval for automatic data retrieval
let quads = [] // available quadrupoles for time-serie figure let quads = [] // available quadrupoles for time-serie figure
let squads = [] // selected quadrupoles for time-serie figure let squads = [] // selected quadrupoles for time-serie figure
let elecSpacing = 1 // 1 m
// useful functions // useful functions
function sendCommand(query, callback=null) { function sendCommand(query, callback=null) {
...@@ -185,20 +188,23 @@ ...@@ -185,20 +188,23 @@
stopBtn.addEventListener('click', stopBtnFunc) stopBtn.addEventListener('click', stopBtnFunc)
// set configuration // set configuration
function saveConfigBtnFunc() { function saveSettingsBtnFunc() {
// collect values from modal // collect values from modal
let formVals = {} let formVals = {}
for (let field of ['nbElectrodes', 'injectionDuration', formVals['nb_electrodes'] = parseInt(document.getElementById('nbElectrodes').value)
'nbMeasurements', 'sequenceDelay', 'nbStack']) { formVals['injection_duration'] = parseFloat(document.getElementById('injectionDuration').value)
formVals[field] = document.getElementById(field).value formVals['nb_meas'] = parseInt(document.getElementById('nbMeasurements').value)
} formVals['sequence_delay'] = parseInt(document.getElementById('sequenceDelay').value)
formVals['nb_stack'] = parseInt(document.getElementById('nbStack').value)
formVals['elec_spacing'] = parseFloat(document.getElementById('elecSpacing').value)
console.log(formVals) console.log(formVals)
elecSpacing = formVals['elec_spacing']
// define callback to send settigs to Pi // define callback to send settigs to Pi
function configCallback() { function settingsCallback() {
sendCommand(JSON.stringify({ sendCommand(JSON.stringify({
'cmd': 'update_settings', 'cmd': 'update_settings',
'config': formVals 'config': formVals
}), function(x) { }), function(x) {
console.log('update_settings', x) console.log('update_settings', x)
}) })
...@@ -217,59 +223,95 @@ ...@@ -217,59 +223,95 @@
reader.addEventListener('load', () => { reader.addEventListener('load', () => {
formVals['sequence'] = reader.result formVals['sequence'] = reader.result
console.log('file==', reader.result) console.log('file==', reader.result)
configCallback() settingsCallback()
}, false) }, false)
} else { } else {
console.log('no sequence uploaded') console.log('no sequence uploaded')
formVals['sequence'] = '' formVals['sequence'] = ''
configCallback() settingsCallback()
} }
} }
let saveConfigBtn = document.getElementById('saveConfigBtn') let saveConfigBtn = document.getElementById('saveConfigBtn')
saveConfigBtn.addEventListener('click', saveConfigBtnFunc) saveConfigBtn.addEventListener('click', saveSettingsBtnFunc)
// make pseudo plot // make pseudo plot
var trace = { var trace = {}
x: [], let layout = {}
y: [], let tdata = []
mode: 'markers', let layout2 = {}
marker: { let rsdata = []
size: 40, let rslayout = {}
color: [],
colorbar: { // initialize all plots
title: 'App. res. [Ohm.m]', function initPlots() {
cmin: 0, trace = {
cmax: 100, x: [],
} y: [],
} mode: 'markers',
} marker: {
let layout = { size: 40,
title: 'Pseudo-section', color: [],
yaxis: { colorbar: {
title: 'Pseudo-depth', title: 'App. res. [Ohm.m]',
autorange: 'reversed' cmin: 0,
}, cmax: 100,
xaxis: { }
title: 'X' }
} }
layout = {
title: 'Pseudo-section',
yaxis: {
title: 'Pseudo-depth',
autorange: 'reversed'
},
xaxis: {
title: 'X'
}
} }
Plotly.newPlot('gd', [trace], layout) Plotly.newPlot('gd', [trace], layout)
// make time-serie plot // make time-serie plot
let tdata = [] tdata = []
let layout2 = { layout2 = {
title: 'Time-serie', title: 'Time-serie',
yaxis: { yaxis: {
title: 'App. res. [Ohm.m]' title: 'App. res. [Ohm.m]'
}, },
xaxis: { xaxis: {
title: 'Sampling time' title: 'Sampling time'
} }
} }
Plotly.newPlot('ts', tdata, layout2) Plotly.newPlot('ts', tdata, layout2)
// bar chart for contact resistance
rsdata = []
rslayout = {
title: 'Contact resistances',
yaxis: {
title: 'Resistance [kOhm]'
},
xaxis: {
title: 'Consecutive electrodes'
}
}
Plotly.newPlot('rs', rsdata, rslayout)
}
initPlots()
// hover function
var hoverInfo = document.getElementById('hoverinfo')
document.getElementById('gd').on('plotly_hover', function(data){
var infotext = data.points.map(function(d){
return (Math.round(d.data.marker.color[d.pointIndex], 2) + ' Ohm.m');
});
hoverInfo.innerHTML = infotext.join('<br/>');
})
.on('plotly_unhover', function(data){
hoverInfo.innerHTML = '';
});
// add trace to time-serie plot // add trace to time-serie plot
function addTraceBtnFunc() { function addTraceBtnFunc() {
...@@ -301,30 +343,135 @@ ...@@ -301,30 +343,135 @@
let surveyName = el['target'].value let surveyName = el['target'].value
let df = data[surveyName] let df = data[surveyName]
if (df != undefined) { if (df != undefined) {
let a = df['a']
let b = df['b']
let m = df['m']
let n = df['n']
// let's assume electrodes are 1 m distance // let's assume electrodes are 1 m distance
// compute pseudo-depth (assume no topo) // compute pseudo-depth (assume no topo)
// compute app res (assumping flat, line survey) // compute app res (assumping flat, line survey)
let xpos = [] let xpos = []
let ypos = [] let ypos = []
let app = [] let app = []
for (let i = 0; i < a.length; i++) { for (let i = 0; i < df['a'].length; i++) {
let ab = (a[i] + b[i])/2 let a = df['a'][i]
let mn = (m[i] + n[i])/2 let b = df['b'][i]
let m = df['m'][i]
let n = df['n'][i]
// compute geometric factor assuming flat 2D surface
let am = Math.abs(a - m)*elecSpacing
let bm = Math.abs(b - m)*elecSpacing
let an = Math.abs(a - n)*elecSpacing
let bn = Math.abs(b - n)*elecSpacing
let K = 2*Math.PI/((1/am)-(1/bm)-(1/an)+(1/bn))
app.push(df['rho'][i]*K)
//console.log(K) // same as resipy for the wenner case
// computing pseudo-depth assuming 2D flat array
// let's sort the electrodes AB are the two left, MN, the two right
let abmn = [a, b, m, n]
abmn = abmn.sort((a, b) => a - b)
let ab = (abmn[0] + abmn[1])/2
let mn = (abmn[2] + abmn[3])/2
let dist = Math.abs(ab - mn) let dist = Math.abs(ab - mn)
xpos.push(Math.min(ab, mn) + dist/2) xpos.push((Math.min(ab, mn) + dist/2)*elecSpacing)
ypos.push(Math.sqrt(2)/2*dist) ypos.push((Math.sqrt(2)/2*dist)*elecSpacing)
let am = Math.abs(a[i] - m[i])
let bm = Math.abs(b[i] - m[i]) /*
let an = Math.abs(a[i] - n[i]) lookupDict = dict(zip(self.elec['label'], np.arange(self.elec.shape[0])))
let bn = Math.abs(a[i] - n[i]) array = self.df[['a','b','m','n']].replace(lookupDict).values.astype(int)
let K = (2*Math.PI)/((1/am)-(1/an)-(1/an)+(1/bn)) elecm = self.elec[['x','y','z']].values.astype(float).copy() # electrode matrix - should be array of floats so np.inf work properly
app.push(df['rho'][i]*-K)
} ### first determine if measurements are nested ###
console.log(app) #find mid points of AB
AB = (elecm[array[:,0]] + elecm[array[:,1]]) / 2 # mid points of AB
MN = (elecm[array[:,2]] + elecm[array[:,3]]) / 2 # mid points of MN
ABrad = np.sqrt(np.sum((elecm[array[:,0]] - AB)**2,axis=1)) # radius of AB circle
MNrad = np.sqrt(np.sum((elecm[array[:,2]] - MN)**2,axis=1)) # radius of MN circle
Amn = np.sqrt(np.sum((elecm[array[:,0]] - MN)**2,axis=1)) # distance of A to mid point of MN
Bmn = np.sqrt(np.sum((elecm[array[:,1]] - MN)**2,axis=1)) # distance of B to mid point of MN
Nab = np.sqrt(np.sum((elecm[array[:,2]] - AB)**2,axis=1)) # distance of N to mid point of AB
Mab = np.sqrt(np.sum((elecm[array[:,3]] - AB)**2,axis=1)) # distance of M to mid point of AB
iABinMN = (Amn < MNrad) & (Bmn < MNrad)
iMNinAB = (Nab < ABrad) & (Mab < ABrad)
inested = iABinMN | iMNinAB #if AB encompasses MN or MN encompasses AB
# so it will never be taken as minimium
elecm[self.elec['remote'].values,:] = np.inf
# compute midpoint position of AB and MN dipoles
elecx = elecm[:,0]
elecy = elecm[:,1]
#CURRENT ELECTRODE MIDPOINTS
caddx = np.abs(elecx[array[:,0]]-elecx[array[:,1]])/2
caddy = np.abs(elecy[array[:,0]]-elecy[array[:,1]])/2
caddx[np.isinf(caddx)] = 0
caddy[np.isinf(caddy)] = 0
cmiddlex = np.min([elecx[array[:,0]], elecx[array[:,1]]], axis=0) + caddx
cmiddley = np.min([elecy[array[:,0]], elecy[array[:,1]]], axis=0) + caddy
#POTENTIAL ELECTRODE MIDPOINTS
paddx = np.abs(elecx[array[:,2]]-elecx[array[:,3]])/2
paddy = np.abs(elecy[array[:,2]]-elecy[array[:,3]])/2
paddx[np.isinf(paddx)] = 0
paddy[np.isinf(paddy)] = 0
pmiddlex = np.min([elecx[array[:,2]], elecx[array[:,3]]], axis=0) + paddx
pmiddley = np.min([elecy[array[:,2]], elecy[array[:,3]]], axis=0) + paddy
# for non-nested measurements
xposNonNested = np.min([cmiddlex, pmiddlex], axis=0) + np.abs(cmiddlex-pmiddlex)/2
yposNonNested = np.min([cmiddley, pmiddley], axis=0) + np.abs(cmiddley-pmiddley)/2
pcdist = np.sqrt((cmiddlex-pmiddlex)**2 + (cmiddley-pmiddley)**2)
# zposNonNested = np.sqrt(2)/2*pcdist
zposNonNested = pcdist/4
if np.all(cmiddley-pmiddley == 0):
zposNonNested = 0.25*pcdist
else: # for 3D arrays where there are mid-line measurements, this works closer to inversion results
zposNonNested = np.sqrt(2)/2*pcdist
# for nested measurements use formula of Dalhin 2006
xposNested = np.zeros(len(pmiddlex))
yposNested = np.zeros(len(pmiddlex))
outerElec1 = np.zeros((len(pmiddlex), 2)) # position of one electrode of outer dipole
outerElec2 = np.zeros((len(pmiddlex), 2)) # position of one electrode of outer dipole
# innerMid = np.zeros((len(pmiddlex), 2)) # middle of inner dipole
if np.sum(iMNinAB) > 0:
xposNested[iMNinAB] = pmiddlex[iMNinAB]
yposNested[iMNinAB] = pmiddley[iMNinAB]
outerElec1[iMNinAB] = np.c_[elecx[array[iMNinAB,0]], elecy[array[iMNinAB,0]]]
outerElec2[iMNinAB] = np.c_[elecx[array[iMNinAB,1]], elecy[array[iMNinAB,1]]]
if np.sum(iABinMN) > 0:
xposNested[iABinMN] = cmiddlex[iABinMN]
yposNested[iABinMN] = cmiddley[iABinMN]
outerElec1[iABinMN] = np.c_[elecx[array[iABinMN,2]], elecy[array[iABinMN,2]]]
outerElec2[iABinMN] = np.c_[elecx[array[iABinMN,3]], elecy[array[iABinMN,3]]]
innerMid = np.c_[pmiddlex, pmiddley] # always use potential dipole
apdist = np.sqrt(np.sum((outerElec1-innerMid)**2, axis=1))
bpdist = np.sqrt(np.sum((outerElec2-innerMid)**2, axis=1))
zposNested = np.min([apdist, bpdist], axis=0)/3
xpos = np.zeros_like(pmiddlex)
ypos = np.zeros_like(pmiddlex)
zpos = np.zeros_like(pmiddlex)
xpos[~inested] = xposNonNested[~inested]
xpos[inested] = xposNested[inested]
ypos[~inested] = yposNonNested[~inested]
ypos[inested] = yposNested[inested]
zpos[~inested] = zposNonNested[~inested]
zpos[inested] = zposNested[inested]
*/
}
//console.log(app)
// update the trace and redraw the figure // update the trace and redraw the figure
trace['x'] = xpos trace['x'] = xpos
trace['y'] = ypos trace['y'] = ypos
...@@ -335,23 +482,17 @@ ...@@ -335,23 +482,17 @@
} }
} }
let surveySelect = document.getElementById('surveySelect') let surveySelect = document.getElementById('surveySelect')
// bar chart for contact resistance
let rsdata = []
let rslayout = {
title: 'Contact resistances',
yaxis: {
title: 'Resistance [kOhm]'
},
xaxis: {
title: 'Consecutive electrodes'
}
}
Plotly.newPlot('rs', rsdata, rslayout)
// run RS check // run RS check
function rsBtnFunc() { function rsBtnFunc() {
sendCommand('{"cmd": "rsCheck"}', function (res) { sendCommand('{"cmd": "rsCheck"}', function (a) {})
}
let rsBtn = document.getElementById('rsBtn')
rsBtn.addEventListener('click', rsBtnFunc)
// get RS check data
function getRsBtnFunc() {
sendCommand('{"cmd": "getRsCheck"}', function(res) {
// update the bar plot // update the bar plot
rsdata.push({ rsdata.push({
x: res['data']['AB'], x: res['data']['AB'],
...@@ -362,8 +503,8 @@ ...@@ -362,8 +503,8 @@
Plotly.redraw('rs') Plotly.redraw('rs')
}) })
} }
let rsBtn = document.getElementById('rsBtn') let getRsBtn = document.getElementById('getRsBtn')
rsBtn.addEventListener('click', rsBtnFunc) getRsBtn.addEventListener('click', getRsBtnFunc)
// clear RS graph // clear RS graph
function rsClearBtnFunc() { function rsClearBtnFunc() {
...@@ -416,24 +557,28 @@ ...@@ -416,24 +557,28 @@
surveySelectFunc({'target': surveySelect}) surveySelectFunc({'target': surveySelect})
// update list of quadrupoles if any // update list of quadrupoles if any
if (quads.length == 0) { let idiff = false
if (data[surveyNames[0]] != undefined) {
idiff = quads.length != data[surveyNames[0]]['a'].length
}
//console.log('idiff=', idiff, quads.length, data[surveyNames[0]]['a'].length)
if (((quads.length == 0) | idiff) & (data[surveyNames[0]] != undefined)){
console.log('updating list of quadrupoles') console.log('updating list of quadrupoles')
if (surveyNames.length > 0) { quads = []
let df = data[surveyNames[0]] let df = data[surveyNames[0]]
let quadSelect = document.getElementById('quadSelect') let quadSelect = document.getElementById('quadSelect')
quadSelect.innerHTML = '' quadSelect.innerHTML = ''
for (let i = 0; i < df['a'].length; i++) { for (let i = 0; i < df['a'].length; i++) {
quad = [df['a'][i], df['b'][i], df['m'][i], df['n'][i]] quad = [df['a'][i], df['b'][i], df['m'][i], df['n'][i]]
quads.push(quad) quads.push(quad)
let option = document.createElement('option') let option = document.createElement('option')
option.value = quad.join(', ') option.value = quad.join(', ')
option.innerText = quad.join(', ') option.innerText = quad.join(', ')
quadSelect.appendChild(option) quadSelect.appendChild(option)
}
console.log('quads=', quads)
} }
console.log('quads=', quads)
} }
// update time-serie figure // update time-serie figure
if (squads.length > 0) { if (squads.length > 0) {
...@@ -486,7 +631,7 @@ ...@@ -486,7 +631,7 @@
capplyBtn.addEventListener('click', function() { capplyBtn.addEventListener('click', function() {
surveySelectFunc({'target': surveySelect}) surveySelectFunc({'target': surveySelect})
}) })
// checkbox interaction for data download // checkbox interaction for data download
function dataRetrievalCheckFunc(x) { function dataRetrievalCheckFunc(x) {
if (x['target'].checked == true) { if (x['target'].checked == true) {
...@@ -504,6 +649,7 @@ ...@@ -504,6 +649,7 @@
data = {} data = {}
output.innerHTML = 'Status: ' + x['ohmpi_status'] + ' (all data cleared)' output.innerHTML = 'Status: ' + x['ohmpi_status'] + ' (all data cleared)'
console.log('all data removed') console.log('all data removed')
initPlots() // reset all plots
}) })
} }
let removeDataBtn = document.getElementById('removeDataBtn') let removeDataBtn = document.getElementById('removeDataBtn')
......
...@@ -655,7 +655,7 @@ class OhmPi(object): ...@@ -655,7 +655,7 @@ class OhmPi(object):
(V3.0 only) Injection time in seconds used for finding the best voltage. (V3.0 only) Injection time in seconds used for finding the best voltage.
""" """
self.exec_logger.debug('Starting measurement') self.exec_logger.debug('Starting measurement')
self.exec_logger.info('Waiting for data') self.exec_logger.info('Waiting for data') # do we need this as info? debug is enough I think (gb)
# check arguments # check arguments
if quad is None: if quad is None:
...@@ -936,7 +936,7 @@ class OhmPi(object): ...@@ -936,7 +936,7 @@ class OhmPi(object):
for i in range(0, quads.shape[0]): for i in range(0, quads.shape[0]):
quad = quads[i, :] # quadrupole quad = quads[i, :] # quadrupole
self.switch_mux_on(quad) # put before raising the pins (otherwise conflict i2c) self.switch_mux_on(quad) # put before raising the pins (otherwise conflict i2c)
d = self.run_measurement(quad=quad, nb_stack=1, injection_duration=1, tx_volt=tx_volt, autogain=False) d = self.run_measurement(quad=quad, nb_stack=1, injection_duration=0.2, tx_volt=tx_volt, autogain=False)
if self.idps: if self.idps:
voltage = tx_volt * 1000. # imposed voltage on dps5005 voltage = tx_volt * 1000. # imposed voltage on dps5005
...@@ -984,9 +984,9 @@ class OhmPi(object): ...@@ -984,9 +984,9 @@ class OhmPi(object):
Parameters Parameters
---------- ----------
filename : str filename : str
filename to save the last measurement dataframe Filename to save the last measurement dataframe.
last_measurement : dict last_measurement : dict
Last measurement taken in the form of a python dictionary Last measurement taken in the form of a python dictionary.
""" """
last_measurement = deepcopy(last_measurement) last_measurement = deepcopy(last_measurement)
if 'fulldata' in last_measurement: if 'fulldata' in last_measurement:
...@@ -1015,27 +1015,21 @@ class OhmPi(object): ...@@ -1015,27 +1015,21 @@ class OhmPi(object):
w.writerow(last_measurement) w.writerow(last_measurement)
def _process_commands(self, message): def _process_commands(self, message):
"""Processes commands received from the controller(s) """Process commands received from the controller(s).
Parameters Parameters
---------- ----------
message : str message : str
message containing a command and arguments or keywords and arguments Message containing a command and arguments or keywords and arguments
that can be passed as a JSON string.
""" """
try: try:
decoded_message = json.loads(message) decoded_message = json.loads(message)
print(f'decoded message: {decoded_message}') print(f'decoded message: {decoded_message}')
cmd_id = decoded_message.pop('cmd_id', None) cmd_id = decoded_message.pop('cmd_id', None)
cmd = decoded_message.pop('cmd', None) cmd = decoded_message.pop('cmd', None)
args = decoded_message.pop('args', '[]') args = decoded_message.pop('args', [])
if len(args) == 0: kwargs = decoded_message.pop('kwargs', {})
args = f'["{args}"]'
args = json.loads(args)
kwargs = decoded_message.pop('kwargs', '{}')
if len(kwargs) == 0:
kwargs= '{}'
kwargs = json.loads(kwargs)
self.exec_logger.debug(f'Calling method {cmd}({args}, {kwargs})') self.exec_logger.debug(f'Calling method {cmd}({args}, {kwargs})')
status = False status = False
# e = None # NOTE: Why this? # e = None # NOTE: Why this?
...@@ -1059,9 +1053,17 @@ class OhmPi(object): ...@@ -1059,9 +1053,17 @@ class OhmPi(object):
reply = json.dumps(reply) reply = json.dumps(reply)
self.exec_logger.debug(f'Execution report: {reply}') self.exec_logger.debug(f'Execution report: {reply}')
def set_sequence(self, sequence=sequence): def set_sequence(self, sequence=''):
"""Set a sequence from a string of text.
Parameters
----------
sequence : list of list of int
List of quadrupoles in formatted as [[A1, B1, M1, N1], [A2, B2, M2, N2], ...].
"""
try: try:
self.sequence = np.loadtxt(StringIO(sequence)).astype('uint32') self.sequence = np.array(sequence).astype(int)
# self.sequence = np.loadtxt(StringIO(sequence)).astype('uint32')
status = True status = True
except Exception as e: except Exception as e:
self.exec_logger.warning(f'Unable to set sequence: {e}') self.exec_logger.warning(f'Unable to set sequence: {e}')
...@@ -1115,7 +1117,7 @@ class OhmPi(object): ...@@ -1115,7 +1117,7 @@ class OhmPi(object):
# add command_id in dataset # add command_id in dataset
acquired_data.update({'cmd_id': cmd_id}) acquired_data.update({'cmd_id': cmd_id})
# log data to the data logger # log data to the data logger
self.data_logger.info(f'{acquired_data}') # self.data_logger.info(f'{acquired_data}') # already in run_measurement()
# save data and print in a text file # save data and print in a text file
self.append_and_save(filename, acquired_data) self.append_and_save(filename, acquired_data)
self.exec_logger.debug(f'quadrupole {i+1:d}/{n:d}') self.exec_logger.debug(f'quadrupole {i+1:d}/{n:d}')
......
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