Commit 609eb3d5 authored by Olivier Kaufmann's avatar Olivier Kaufmann
Browse files

Merge branch 'master' of gitlab-ssh.irstea.fr:reversaal/OhmPi

Showing with 605 additions and 556 deletions
+605 -556
doc/source/Ohmpi_V2_00/step_n_3/a/MUX_07.jpg

4.34 MB | W: | H:

doc/source/Ohmpi_V2_00/step_n_3/a/MUX_07.jpg

3.56 MB | W: | H:

doc/source/Ohmpi_V2_00/step_n_3/a/MUX_07.jpg
doc/source/Ohmpi_V2_00/step_n_3/a/MUX_07.jpg
doc/source/Ohmpi_V2_00/step_n_3/a/MUX_07.jpg
doc/source/Ohmpi_V2_00/step_n_3/a/MUX_07.jpg
  • 2-up
  • Swipe
  • Onion skin
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="utf8"/> <meta charset="utf8"/>
<title>OhmPi Acquisition Board</title> <title>OhmPi Acquisition Board</title>
<link rel="shortcut icon" type="image/jpg" href="logo_ohmpi.jpg"/> <link rel="shortcut icon" type="image/jpg" href="logo_ohmpi.jpg"/>
<!-- dependencies (need to be local as no internet in AP mode)--> <!-- dependencies (need to be local as no internet in AP mode)-->
<script src="js/plotly-basic-2.8.3.min.js"></script> <script src="js/plotly-basic-2.8.3.min.js"></script>
<script src="js/jquery-3.4.1.min.js"></script> <script src="js/jquery-3.4.1.min.js"></script>
<link type="text/css" href="css/bootstrap.min.css" rel="stylesheet"> <link type="text/css" href="css/bootstrap.min.css" rel="stylesheet">
<!-- <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script> --> <!-- <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script> -->
<!-- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6" crossorigin="anonymous"> --> <!-- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6" crossorigin="anonymous"> -->
<!-- <script src="js/danfojs/bundle.min.js"></script> --> <!-- <script src="js/danfojs/bundle.min.js"></script> -->
</head> </head>
<body> <body>
<div class='container'> <div class='container'>
<h1>OhmPi Acquisition Board</h1> <h1>OhmPi Acquisition Board</h1>
<!-- nb stacks, on-time --> <!-- nb stacks, on-time -->
<button id="setConfigBtn" type="button" class="btn btn-secondary" data-toggle="modal" data-target="#exampleModal">Settings</button> <button id="setConfigBtn" type="button" class="btn btn-secondary" data-toggle="modal" data-target="#exampleModal">Settings</button>
<button id='startBtn' type="button" class="btn btn-primary">Start</button> <button id='startBtn' type="button" class="btn btn-primary">Start</button>
<button id='stopBtn' type="button" class="btn btn-warning">Stop</button> <button id='stopBtn' type="button" class="btn btn-warning">Stop</button>
<!-- upload button for csv which display the table ABMN --> <!-- upload button for csv which display the table ABMN -->
<button id="removeDataBtn" type="button" class="btn btn-danger">Clear data</button> <button id="removeDataBtn" type="button" class="btn btn-danger">Clear data</button>
<button id="getDataBtn" type="button" class="btn btn-info">Get data</button> <button id="getDataBtn" type="button" class="btn btn-info">Get data</button>
<div class="form-check"> <div class="form-check">
<input id="dataRetrievalCheck" class="form-check-input" type="checkbox" value=""> <input id="dataRetrievalCheck" class="form-check-input" type="checkbox" value="">
<label class="form-check-label" for="dataRetrievalCheck"> <label class="form-check-label" for="dataRetrievalCheck">
Automaticaly get data every 1 second Automaticaly get data every 1 second
</label> </label>
</div> </div>
<div id='output'>Status: idle</div> <div id='output'>Status: idle</div>
<!-- Pseudo section --> <!-- Pseudo section -->
<select id='surveySelect' class='custom-select'> <select id='surveySelect' class='custom-select'>
</select> </select>
<input id="cmin" type="number" value="0"/> <input id="cmin" type="number" value="0"/>
<input id="cmax" type="number" value="150"/> <input id="cmax" type="number" value="150"/>
<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 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">
<select id='quadSelect' class='custom-select'></select> <select id='quadSelect' class='custom-select'></select>
</div> </div>
</div> </div>
<!-- trace figure --> <!-- trace figure -->
<button id="addTraceBtn" type="button" class="btn btn-info">Add trace</button> <button id="addTraceBtn" type="button" class="btn btn-info">Add trace</button>
<button id="removeTracesBtn" type="button" class="btn btn-info">Remove all traces</button> <button id="removeTracesBtn" type="button" class="btn btn-info">Remove all traces</button>
<div id="ts"></div> <div id="ts"></div>
<!-- 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="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>
<!-- Additional buttons --> <!-- Additional buttons -->
<button id="downloadBtn" type="button" class="btn btn-primary">Download data</button> <button id="downloadBtn" type="button" class="btn btn-primary">Download data</button>
<!-- <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 configuration -->
<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 configuration</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>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form> <form>
<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">
<label for="nbMeasurements" class="col-sm-2 col-form-label">Nb Measurements</label> <label for="nbMeasurements" class="col-sm-2 col-form-label">Nb Measurements</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="number" class="form-control-number" id="nbMeasurements" value="1"> <input type="number" class="form-control-number" id="nbMeasurements" value="1">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label for="sequenceDelay" class="col-sm-2 col-form-label">Sequence delay [s]</label> <label for="sequenceDelay" class="col-sm-2 col-form-label">Sequence delay [s]</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="number" class="form-control-number" id="sequenceDelay" value="100"> <input type="number" class="form-control-number" id="sequenceDelay" value="100">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label for="nbStack" class="col-sm-2 col-form-label">Nb stack</label> <label for="nbStack" class="col-sm-2 col-form-label">Nb stack</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="number" class="form-control-number" id="nbStack" value="1"> <input type="number" class="form-control-number" id="nbStack" value="1">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label for="sequence" class="col-sm-2 col-form-label">Sequence</label> <label for="sequence" class="col-sm-2 col-form-label">Sequence</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="file" class="form-control" id="sequence"> <input type="file" class="form-control" id="sequence">
</div> </div>
</div> </div>
</form> <div class="form-group row">
</div> <label for="elecSpacing" class="col-sm-2 col-form-label">Electrode spacing [m]</label>
<div class="modal-footer"> <div class="col-sm-10">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button> <input type="number" class="form-control" id="elecSpacing", value="1">
<button id="saveConfigBtn" type="button" data-dismiss="modal" class="btn btn-primary">Save</button> </div>
</div> </div>
</div> </form>
</div> </div>
</div> <div class="modal-footer">
<button id="restartBtn" type="button" class="btn btn-danger">Restart</button> <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button id="shutdownBtn" type="button" class="btn btn-danger">Shutdown</button> <button id="saveConfigBtn" type="button" data-dismiss="modal" class="btn btn-primary">Save</button>
<footer>v0.2.0</footer> </div>
</div> </div>
</div>
<script type="text/javascript"> </div>
//let serverUrl = 'http://10.3.141.1:8080' <button id="restartBtn" type="button" class="btn btn-danger">Restart</button>
//let serverUrl = 'http://0.0.0.0:8080' <button id="shutdownBtn" type="button" class="btn btn-danger">Shutdown</button>
//let serverUrl = 'http://localhost:8080' <footer>v0.2.0</footer>
let serverUrl = 'http://' + window.location.host </div>
console.log('serverUrl =', serverUrl)
let output = document.getElementById('output') <script type="text/javascript">
let data = {} // hold data of all surveys //let serverUrl = 'http://10.3.141.1:8080'
let interv = null // hold interval for automatic data retrieval //let serverUrl = 'http://0.0.0.0:8080'
let quads = [] // available quadrupoles for time-serie figure //let serverUrl = 'http://localhost:8080'
let squads = [] // selected quadrupoles for time-serie figure let serverUrl = 'http://' + window.location.host
console.log('serverUrl =', serverUrl)
// useful functions let output = document.getElementById('output')
function sendCommand(query, callback=null) { let data = {} // hold data of all surveys
// dic in the form: {'command': X, ...} as JSON let interv = null // hold interval for automatic data retrieval
if (callback == null) { let quads = [] // available quadrupoles for time-serie figure
function callback(x) { let squads = [] // selected quadrupoles for time-serie figure
console.log('default callback:', x) let elecSpacing = 1 // m
}
} // useful functions
let xhr = new XMLHttpRequest(); function sendCommand(query, callback=null) {
xhr.onreadystatechange = function() { // dic in the form: {'command': X, ...} as JSON
if (this.readyState == 4) { if (callback == null) {
if (xhr.status == 200) { function callback(x) {
callback(JSON.parse(xhr.response)) console.log('default callback:', x)
} }
} }
} let xhr = new XMLHttpRequest();
xhr.open('POST', serverUrl) xhr.onreadystatechange = function() {
xhr.setRequestHeader('Content-Type', 'application/json') if (this.readyState == 4) {
xhr.send(query) if (xhr.status == 200) {
} callback(JSON.parse(xhr.response))
}
// start button }
function startBtnFunc() { }
sendCommand('{"command": "start"}', function(x) { xhr.open('POST', serverUrl)
console.log(x['status']) xhr.setRequestHeader('Content-Type', 'application/json')
if (x['status'] == 'running') { xhr.send(query)
output.innerHTML = 'Status: measuring...' console.log('sendCommand:', query)
} }
})
} // start button
let startBtn = document.getElementById('startBtn') function startBtnFunc() {
startBtn.addEventListener('click', startBtnFunc) sendCommand('{"command": "start"}', function(x) {
console.log(x['status'])
// stop button if (x['status'] == 'running') {
function stopBtnFunc() { output.innerHTML = 'Status: measuring...'
sendCommand('{"command": "stop"}', function(x) { }
output.innerHTML = 'Status: ' + x['status'] })
clearInterval(interv) }
getData() let startBtn = document.getElementById('startBtn')
}) startBtn.addEventListener('click', startBtnFunc)
}
let stopBtn = document.getElementById('stopBtn') // stop button
stopBtn.addEventListener('click', stopBtnFunc) function stopBtnFunc() {
sendCommand('{"command": "stop"}', function(x) {
// set configuration output.innerHTML = 'Status: ' + x['status']
function saveConfigBtnFunc() { clearInterval(interv)
// collect values from modal document.getElementById('dataRetrievalCheck').checked = false
let formVals = {} getData()
for (let field of ['nbElectrodes', 'injectionDuration', })
'nbMeasurements', 'sequenceDelay', 'nbStack']) { }
formVals[field] = document.getElementById(field).value let stopBtn = document.getElementById('stopBtn')
} stopBtn.addEventListener('click', stopBtnFunc)
console.log(formVals)
// set configuration
// define callback to send settigs to Pi function saveConfigBtnFunc() {
function configCallback() { // collect values from modal
sendCommand(JSON.stringify({ let formVals = {}
'command': 'setConfig', for (let field of ['nbElectrodes', 'injectionDuration',
'config': formVals 'nbMeasurements', 'sequenceDelay', 'nbStack', 'elecSpacing']) {
}), function(x) { formVals[field] = document.getElementById(field).value
console.log('setconfig:', x) }
}) console.log(formVals)
} elecSpacing = formVals['elecSpacing']
// deal with the potential file containing the sequence // define callback to send settigs to Pi
// https://stackoverflow.com/questions/19038919/is-it-possible-to-upload-a-text-file-to-input-in-html-js function configCallback() {
if (!window.FileReader) { sendCommand(JSON.stringify({
alert('Your browser is not supported'); 'command': 'setConfig',
return false; 'config': formVals
} }), function(x) {
let input = document.getElementById('sequence') console.log('setconfig:', x)
if (input.files.length) { })
const reader = new FileReader() }
reader.readAsText(input.files[0])
reader.addEventListener('load', () => { // deal with the potential file containing the sequence
formVals['sequence'] = reader.result // https://stackoverflow.com/questions/19038919/is-it-possible-to-upload-a-text-file-to-input-in-html-js
console.log('file==', reader.result) if (!window.FileReader) {
configCallback() alert('Your browser is not supported');
}, false) return false;
} else { }
console.log('no sequence uploaded') let input = document.getElementById('sequence')
formVals['sequence'] = '' if (input.files.length) {
configCallback() const reader = new FileReader()
} reader.readAsText(input.files[0])
reader.addEventListener('load', () => {
formVals['sequence'] = reader.result
} console.log('file==', reader.result)
let saveConfigBtn = document.getElementById('saveConfigBtn') configCallback()
saveConfigBtn.addEventListener('click', saveConfigBtnFunc) }, false)
} else {
// make pseudo plot console.log('no sequence uploaded')
var trace = { formVals['sequence'] = ''
x: [], configCallback()
y: [], }
mode: 'markers',
marker: {
size: 40, }
color: [], let saveConfigBtn = document.getElementById('saveConfigBtn')
colorbar: { saveConfigBtn.addEventListener('click', saveConfigBtnFunc)
title: 'App. res. [Ohm.m]',
cmin: 0, // make pseudo plot
cmax: 100, var trace = {}
} let layout = {}
} let tdata = []
} let layout2 = {}
let layout = { let rsdata = []
title: 'Pseudo-section', let rslayout = {}
yaxis: {
title: 'Pseudo-depth', // initialize all plots
autorange: 'reversed' function initPlots() {
}, trace = {
xaxis: { x: [],
title: 'X' y: [],
} mode: 'markers',
marker: {
} size: 40,
Plotly.newPlot('gd', [trace], layout) color: [],
colorbar: {
// make time-serie plot title: 'App. res. [Ohm.m]',
let tdata = [] cmin: 0,
let layout2 = { cmax: 100,
title: 'Time-serie', }
yaxis: { }
title: 'App. res. [Ohm.m]' }
}, layout = {
xaxis: { title: 'Pseudo-section',
title: 'Sampling time' yaxis: {
} title: 'Pseudo-depth',
} autorange: 'reversed'
Plotly.newPlot('ts', tdata, layout2) },
xaxis: {
// add trace to time-serie plot title: 'X'
function addTraceBtnFunc() { }
let val = document.getElementById('quadSelect').value
squads.push(val.split(', ')) }
tdata.push({ Plotly.newPlot('gd', [trace], layout)
x: [],
y: [], // make time-serie plot
name: val, tdata = []
type: 'scatter' layout2 = {
}) title: 'Time-serie',
Plotly.newPlot('ts', tdata, layout2) yaxis: {
getData() title: 'App. res. [Ohm.m]'
} },
let addTraceBtn = document.getElementById('addTraceBtn') xaxis: {
addTraceBtn.addEventListener('click', addTraceBtnFunc) title: 'Sampling time'
}
// remove all traces from time-serie plot }
function removeTracesBtnFunc() { Plotly.newPlot('ts', tdata, layout2)
squads = []
tdata = [] // bar chart for contact resistance
Plotly.newPlot('ts', tdata, layout2) rsdata = []
} rslayout = {
let removeTracesBtn = document.getElementById('removeTracesBtn') title: 'Contact resistances',
removeTracesBtn.addEventListener('click', removeTracesBtnFunc) yaxis: {
title: 'Resistance [kOhm]'
// callback function to draw the plot },
function surveySelectFunc(el) { xaxis: {
let surveyName = el['target'].value title: 'Consecutive electrodes'
let df = data[surveyName] }
if (df != undefined) { }
let a = df['a'] Plotly.newPlot('rs', rsdata, rslayout)
let b = df['b'] }
let m = df['m'] initPlots()
let n = df['n']
// let's assume electrodes are 1 m distance // add trace to time-serie plot
// compute pseudo-depth (assume no topo) function addTraceBtnFunc() {
// compute app res (assumping flat, line survey) let val = document.getElementById('quadSelect').value
let xpos = [] squads.push(val.split(', '))
let ypos = [] tdata.push({
let app = [] x: [],
for (let i = 0; i < a.length; i++) { y: [],
let ab = (a[i] + b[i])/2 name: val,
let mn = (m[i] + n[i])/2 type: 'scatter'
let dist = Math.abs(ab - mn) })
xpos.push(Math.min(ab, mn) + dist/2) Plotly.newPlot('ts', tdata, layout2)
ypos.push(Math.sqrt(2)/2*dist) getData()
let am = Math.abs(a[i] - m[i]) }
let bm = Math.abs(b[i] - m[i]) let addTraceBtn = document.getElementById('addTraceBtn')
let an = Math.abs(a[i] - n[i]) addTraceBtn.addEventListener('click', addTraceBtnFunc)
let bn = Math.abs(a[i] - n[i])
let K = (2*Math.PI)/((1/am)-(1/an)-(1/an)+(1/bn)) // remove all traces from time-serie plot
app.push(df['rho'][i]*-K) function removeTracesBtnFunc() {
} squads = []
console.log(app) tdata = []
// update the trace and redraw the figure Plotly.newPlot('ts', tdata, layout2)
trace['x'] = xpos }
trace['y'] = ypos let removeTracesBtn = document.getElementById('removeTracesBtn')
trace['marker']['color'] = app removeTracesBtn.addEventListener('click', removeTracesBtnFunc)
trace['marker']['cmax'] = document.getElementById('cmax').value
trace['marker']['cmin'] = document.getElementById('cmin').value // callback function to draw the plot
Plotly.redraw('gd') function surveySelectFunc(el) {
} let surveyName = el['target'].value
} let df = data[surveyName]
let surveySelect = document.getElementById('surveySelect') if (df != undefined) {
// let's assume electrodes are 1 m distance
// bar chart for contact resistance // compute pseudo-depth (assume no topo)
let rsdata = [] // compute app res (assumping flat, line survey)
let rslayout = { let xpos = []
title: 'Contact resistances', let ypos = []
yaxis: { let app = []
title: 'Resistance [kOhm]' for (let i = 0; i < df['a'].length; i++) {
}, let a = df['a'][i]
xaxis: { let b = df['b'][i]
title: 'Consecutive electrodes' let m = df['m'][i]
} let n = df['n'][i]
} // let's sort the electrodes AB are the two left, MN, the two right
Plotly.newPlot('rs', rsdata, rslayout) // TODO not sure this is correct, resipy code is much more complex here
let abmn = [a, b, m, n]
// run RS check abmn = abmn.sort((a, b) => a - b)
function rsBtnFunc() { a = abmn[0]
sendCommand('{"command": "rsCheck"}', function (res) { b = abmn[1]
// update the bar plot m = abmn[2]
rsdata.push({ n = abmn[3]
x: res['data']['AB'], let ab = (a + b)/2
y: res['data']['res'], let mn = (m + n)/2
name: 'RS', let dist = Math.abs(ab - mn)
type: 'bar' xpos.push((Math.min(ab, mn) + dist/2)*elecSpacing)
}) ypos.push((Math.sqrt(2)/2*dist)*elecSpacing)
Plotly.redraw('rs') let am = Math.abs(a - m)*elecSpacing
}) let bm = Math.abs(b - m)*elecSpacing
} let an = Math.abs(a - n)*elecSpacing
let rsBtn = document.getElementById('rsBtn') let bn = Math.abs(a - n)*elecSpacing
rsBtn.addEventListener('click', rsBtnFunc) let K = (2*Math.PI)/((1/am)-(1/an)-(1/an)+(1/bn))
app.push(df['rho'][i]*K)
// clear RS graph }
function rsClearBtnFunc() { console.log(app)
rsdata = [] // update the trace and redraw the figure
Plotly.newPlot('rs', rsdata, rslayout) trace['x'] = xpos
} trace['y'] = ypos
let rsClearBtn = document.getElementById('rsClearBtn') trace['marker']['color'] = app
rsClearBtn.addEventListener('click', rsClearBtnFunc) trace['marker']['cmax'] = document.getElementById('cmax').value
trace['marker']['cmin'] = document.getElementById('cmin').value
// getData Plotly.redraw('gd')
function getData() { }
sendCommand(JSON.stringify({ }
'command': 'getData', let surveySelect = document.getElementById('surveySelect')
'surveyNames': Object.keys(data).slice(0, -1)
// last survey is often partial so we download it again
}), function(ddic) { // run RS check
// update status function rsBtnFunc() {
output.innerHTML = 'Status: ' + ddic['status'] sendCommand('{"command": "rsCheck"}', function (res) {
// update the bar plot
// update data dic with new data rsdata.push({
data = { // destructuring assignement (magic! :o) x: res['data']['AB'],
...data, y: res['data']['res'],
...ddic['data'] // value from second dic are preferred name: 'RS',
} type: 'bar'
})
// dropdown with number of surveys and +++ Plotly.redraw('rs')
let surveyNames = Object.keys(data).sort() })
}
// remove listener as we will replace the choices let rsBtn = document.getElementById('rsBtn')
surveySelect.removeEventListener('change', surveySelectFunc) rsBtn.addEventListener('click', rsBtnFunc)
surveySelect.innerHTML = '' // clearing all child nodes
// clear RS graph
// add choices again function rsClearBtnFunc() {
for (let surveyName of surveyNames) { rsdata = []
let option = document.createElement('option') Plotly.newPlot('rs', rsdata, rslayout)
option.innerText = surveyName }
option.value = surveyName let rsClearBtn = document.getElementById('rsClearBtn')
surveySelect.appendChild(option) rsClearBtn.addEventListener('click', rsClearBtnFunc)
}
// getData
// listener again function getData() {
surveySelect.addEventListener('change', surveySelectFunc) sendCommand(JSON.stringify({
'command': 'getData',
// plot last one by default 'surveyNames': Object.keys(data).slice(0, -1)
surveySelect.value = surveyNames[surveyNames.length - 1] // last survey is often partial so we download it again
}), function(ddic) {
// call the function directly // update status
// (as progammatically chaging the value does not trigger the event) output.innerHTML = 'Status: ' + ddic['status']
surveySelectFunc({'target': surveySelect})
// update data dic with new data
// update list of quadrupoles if any data = { // destructuring assignement (magic! :o)
if (quads.length == 0) { ...data,
console.log('updating list of quadrupoles') ...ddic['data'] // value from second dic are preferred
let df = data[surveyNames[0]] }
let quadSelect = document.getElementById('quadSelect')
quadSelect.innerHTML = '' // dropdown with number of surveys and +++
for (let i = 0; i < df['a'].length; i++) { let surveyNames = Object.keys(data).sort()
quad = [df['a'][i], df['b'][i], df['m'][i], df['n'][i]]
quads.push(quad) // remove listener as we will replace the choices
let option = document.createElement('option') surveySelect.removeEventListener('change', surveySelectFunc)
option.value = quad.join(', ') surveySelect.innerHTML = '' // clearing all child nodes
option.innerText = quad.join(', ')
quadSelect.appendChild(option) // add choices again
} for (let surveyName of surveyNames) {
console.log('quads=', quads) let option = document.createElement('option')
} option.innerText = surveyName
option.value = surveyName
// update time-serie figure surveySelect.appendChild(option)
if (squads.length > 0) { }
// transform all surveyNames to datetime // listener again
let xt = [] surveySelect.addEventListener('change', surveySelectFunc)
for (surveyName of surveyNames) {
let a = surveyName.split('_').slice(-1)[0] // plot last one by default
xt.push(a.slice(0, 4) + '-' surveySelect.value = surveyNames[surveyNames.length - 1]
+ a.slice(4, 6) + '-'
+ a.slice(6, 8) + ' ' // call the function directly
+ a.slice(9, 11) + ':' // (as progammatically chaging the value does not trigger the event)
+ a.slice(11, 13) + ':' surveySelectFunc({'target': surveySelect})
+ a.slice(13, 15))
} // update list of quadrupoles if any
//console.log(xt) let idiff = false
if (data[surveyNames[0]] != undefined) {
// create one new trace per selected quadrupole idiff = quads.length != data[surveyNames[0]]['a'].length
for (let k = 0; k < squads.length; k++) { }
squad = squads[k] //console.log('idiff=', idiff, quads.length, data[surveyNames[0]]['a'].length)
let x = [] if (((quads.length == 0) | idiff) & (data[surveyNames[0]] != undefined)){
let y = [] console.log('updating list of quadrupoles')
for (let i = 0; i < surveyNames.length; i++) { quads = []
df = data[surveyNames[i]] let df = data[surveyNames[0]]
for (let j = 0; j < df['a'].length; j++) { let quadSelect = document.getElementById('quadSelect')
if (df['a'][j] == squad[0] quadSelect.innerHTML = ''
&& df['b'][j] == squad[1] for (let i = 0; i < df['a'].length; i++) {
&& df['m'][j] == squad[2] quad = [df['a'][i], df['b'][i], df['m'][i], df['n'][i]]
&& df['n'][j] == squad[3]) { quads.push(quad)
y.push(df['rho'][j]) let option = document.createElement('option')
x.push(xt[i]) option.value = quad.join(', ')
break option.innerText = quad.join(', ')
} quadSelect.appendChild(option)
} }
} console.log('quads=', quads)
}
// update trace dictionnary
tdata[k]['x'] = x // update time-serie figure
tdata[k]['y'] = y if (squads.length > 0) {
}
//console.log(tdata) // transform all surveyNames to datetime
Plotly.redraw('ts') let xt = []
} for (surveyName of surveyNames) {
}) let a = surveyName.split('_').slice(-1)[0]
} xt.push(a.slice(0, 4) + '-'
let getDataBtn = document.getElementById('getDataBtn') + a.slice(4, 6) + '-'
getDataBtn.addEventListener('click', getData) + a.slice(6, 8) + ' '
+ a.slice(9, 11) + ':'
// apply new colorscale + a.slice(11, 13) + ':'
let capplyBtn = document.getElementById('capplyBtn') + a.slice(13, 15))
capplyBtn.addEventListener('click', function() { }
surveySelectFunc({'target': surveySelect}) //console.log(xt)
})
// create one new trace per selected quadrupole
// checkbox interaction for data download for (let k = 0; k < squads.length; k++) {
function dataRetrievalCheckFunc(x) { squad = squads[k]
if (x['target'].checked == true) { let x = []
interv = setInterval(getData, 1000) // every 5s let y = []
} else { for (let i = 0; i < surveyNames.length; i++) {
clearInterval(interv) df = data[surveyNames[i]]
} for (let j = 0; j < df['a'].length; j++) {
} if (df['a'][j] == squad[0]
let dataRetrievalCheck = document.getElementById('dataRetrievalCheck') && df['b'][j] == squad[1]
dataRetrievalCheck.addEventListener('change', dataRetrievalCheckFunc) && df['m'][j] == squad[2]
&& df['n'][j] == squad[3]) {
// remove data y.push(df['rho'][j])
function removeDataBtnFunc() { x.push(xt[i])
sendCommand('{"command": "removeData"}',function(x) { break
data = {} }
output.innerHTML = 'Status: ' + x['status'] + ' (all data cleared)' }
console.log('all data removed') }
})
} // update trace dictionnary
let removeDataBtn = document.getElementById('removeDataBtn') tdata[k]['x'] = x
removeDataBtn.addEventListener('click', removeDataBtnFunc) tdata[k]['y'] = y
}
// shutdown Pi //console.log(tdata)
function shutdownBtnFunc() { Plotly.redraw('ts')
sendCommand('{"command": "shutdown"}', function(x) { }
console.log('shuting down...') })
}) }
} let getDataBtn = document.getElementById('getDataBtn')
let shutdownBtn = document.getElementById('shutdownBtn') getDataBtn.addEventListener('click', getData)
shutdownBtn.addEventListener('click', shutdownBtnFunc)
// apply new colorscale
// restart Pi let capplyBtn = document.getElementById('capplyBtn')
function restartBtnFunc() { capplyBtn.addEventListener('click', function() {
sendCommand('{"command": "restart"}', function(x) { surveySelectFunc({'target': surveySelect})
console.log('rebooting...') })
})
} // checkbox interaction for data download
let restartBtn = document.getElementById('restartBtn') function dataRetrievalCheckFunc(x) {
restartBtn.addEventListener('click', restartBtnFunc) if (x['target'].checked == true) {
interv = setInterval(getData, 1000) // every 1s
// invert data } else {
// function invertBtnFunc() { clearInterval(interv)
// sendCommand('{"command": "invert"}', function(x) { }
// console.log('inversion results', x) }
// }) let dataRetrievalCheck = document.getElementById('dataRetrievalCheck')
// } dataRetrievalCheck.addEventListener('change', dataRetrievalCheckFunc)
// let invertBtn = document.getElementById('invertBtn')
// invertBtn.addEventListener('click', invertBtnFunc)
// remove data
// download data function removeDataBtnFunc() {
function downloadBtnFunc() { sendCommand('{"command": "removeData"}',function(x) {
sendCommand('{"command": "download"}', function(x) { data = {}
let dwl = document.getElementById('download') output.innerHTML = 'Status: ' + x['status'] + ' (all data cleared)'
dwl.setAttribute('href', serverUrl + '/data.zip') console.log('all data removed')
dwl.setAttribute('download', 'data.zip') initPlots() // reset all plots
dwl.click() })
}) }
} let removeDataBtn = document.getElementById('removeDataBtn')
let downloadBtn = document.getElementById('downloadBtn') removeDataBtn.addEventListener('click', removeDataBtnFunc)
downloadBtn.addEventListener('click', downloadBtnFunc)
// shutdown Pi
function shutdownBtnFunc() {
</script> sendCommand('{"command": "shutdown"}', function(x) {
console.log('shuting down...')
<!-- Boostrap scripts (at the end of the page for faster loading time)--> })
<script src="js/bootstrap.bundle.min.js"></script> }
<!-- <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/js/bootstrap.bundle.min.js" integrity="sha384-JEW9xMcG8R+pH31jmWH6WWP0WintQrMb4s7ZOdauHnUtxwoG2vI5DkLtS3qm9Ekf" crossorigin="anonymous"></script> --> let shutdownBtn = document.getElementById('shutdownBtn')
</body> shutdownBtn.addEventListener('click', shutdownBtnFunc)
</html>
// restart Pi
function restartBtnFunc() {
sendCommand('{"command": "restart"}', function(x) {
console.log('rebooting...')
})
}
let restartBtn = document.getElementById('restartBtn')
restartBtn.addEventListener('click', restartBtnFunc)
// invert data
// function invertBtnFunc() {
// sendCommand('{"command": "invert"}', function(x) {
// console.log('inversion results', x)
// })
// }
// let invertBtn = document.getElementById('invertBtn')
// invertBtn.addEventListener('click', invertBtnFunc)
// download data
function downloadBtnFunc() {
sendCommand('{"command": "download"}', function(x) {
let dwl = document.getElementById('download')
dwl.setAttribute('href', serverUrl + '/data.zip')
dwl.setAttribute('download', 'data.zip')
dwl.click()
})
}
let downloadBtn = document.getElementById('downloadBtn')
downloadBtn.addEventListener('click', downloadBtnFunc)
</script>
<!-- Boostrap scripts (at the end of the page for faster loading time)-->
<script src="js/bootstrap.bundle.min.js"></script>
<!-- <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/js/bootstrap.bundle.min.js" integrity="sha384-JEW9xMcG8R+pH31jmWH6WWP0WintQrMb4s7ZOdauHnUtxwoG2vI5DkLtS3qm9Ekf" crossorigin="anonymous"></script> -->
</body>
</html>
...@@ -54,7 +54,7 @@ class OhmPi(object): ...@@ -54,7 +54,7 @@ class OhmPi(object):
sequence: 1, 2, 3, 4 is used. sequence: 1, 2, 3, 4 is used.
""" """
def __init__(self, config=None, sequence=None, mqtt=True, on_pi=None): def __init__(self, config=None, sequence=None, mqtt=False, on_pi=None):
# flags and attributes # flags and attributes
if on_pi is None: if on_pi is None:
_, on_pi = OhmPi.get_platform() _, on_pi = OhmPi.get_platform()
...@@ -562,12 +562,14 @@ class OhmPi(object): ...@@ -562,12 +562,14 @@ class OhmPi(object):
current = AnalogIn(self.ads_current, ads.P0).voltage / (50 * self.r_shunt) current = AnalogIn(self.ads_current, ads.P0).voltage / (50 * self.r_shunt)
voltage = -AnalogIn(self.ads_voltage, ads.P0, ads.P1).voltage * 2.5 voltage = -AnalogIn(self.ads_voltage, ads.P0, ads.P1).voltage * 2.5
resistance = voltage / current resistance = voltage / current
print('I: {:>10.3f} mA, V: {:>10.3f} mV, R: {:>10.3f} Ohm'.format(
current*1000, voltage*1000, resistance))
# compute resistance measured (= contact resistance) # compute resistance measured (= contact resistance)
resist = abs(resistance / 1000) resist = abs(resistance / 1000)
msg = 'Contact resistance {:s}: {:.3f} kOhm'.format( msg = 'Contact resistance {:s}: {:.3f} kOhm'.format(
str(quad), resist) str(quad), resist)
print(msg) #print(msg)
self.exec_logger.debug(msg) self.exec_logger.debug(msg)
...@@ -729,6 +731,9 @@ print(current_time.strftime("%Y-%m-%d %H:%M:%S")) ...@@ -729,6 +731,9 @@ print(current_time.strftime("%Y-%m-%d %H:%M:%S"))
# for testing # for testing
if __name__ == "__main__": if __name__ == "__main__":
ohmpi = OhmPi(config='ohmpi_param.json') ohmpi = OhmPi(config='ohmpi_param.json')
#ohmpi.measure()
ohmpi.read_quad('breadboard.txt')
ohmpi.rs_check()
ohmpi.measure() ohmpi.measure()
time.sleep(4) time.sleep(4)
ohmpi.stop() ohmpi.stop()
#!bin/bash
source ./ohmpy/bin/activate source ./ohmpy/bin/activate
python webserver.py python webserver.py
echo "# start OhmPi web interface" >> $HOME/.bashrc
echo "(cd $HOME/OhmPi; ./run.sh)" >> $HOME/.bashrc
# to automatically start the webserver on start, you need to place the
# following line just before the line with 'exit 0' in the /etc/rc.local.
(cd /home/jkl/OhmPi; bash run.sh > startup.log) &
...@@ -7,9 +7,9 @@ import threading ...@@ -7,9 +7,9 @@ import threading
import pandas as pd import pandas as pd
import shutil import shutil
hostName = "raspberrypi.local" # works for AP-STA #hostName = "raspberrypi.local" # works for AP-STA
#hostName = "192.168.50.1" # fixed IP in AP-STA mode #hostName = "192.168.50.1" # fixed IP in AP-STA mode
#hostName = "0.0.0.0" # for AP mode (not AP-STA) hostName = "0.0.0.0" # for AP mode (not AP-STA)
serverPort = 8080 serverPort = 8080
# https://gist.github.com/MichaelCurrie/19394abc19abd0de4473b595c0e37a3a # https://gist.github.com/MichaelCurrie/19394abc19abd0de4473b595c0e37a3a
...@@ -17,7 +17,7 @@ serverPort = 8080 ...@@ -17,7 +17,7 @@ serverPort = 8080
with open('ohmpi_param.json') as json_file: with open('ohmpi_param.json') as json_file:
pardict = json.load(json_file) pardict = json.load(json_file)
ohmpi = OhmPi(pardict, sequence='breadboard.txt') ohmpi = OhmPi(pardict, sequence='dd.txt')
#ohmpi = OhmPi(pardict, sequence='dd16s0no8.txt') #ohmpi = OhmPi(pardict, sequence='dd16s0no8.txt')
......
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