diff --git a/dev/start_mqtt_html.py b/dev/start_mqtt_html.py index 5c846e5fe08e5e44c17a0c378b4c02b28572f3eb..4c88810bbadc1b2f9fcf73a9f079bf7d6345b38b 100644 --- a/dev/start_mqtt_html.py +++ b/dev/start_mqtt_html.py @@ -2,12 +2,10 @@ # we need to start the OhmPi instance so that it listens # to message from the MQTT broker -import subprocess -# launch webserver - from ohmpi.utils import change_config -#change_config('../configs/config_mb_2023.py', verbose=False) -change_config('../configs/config_mb_2024_0_2__4_mux_2023_dps5005.py', verbose=False) +change_config('../configs/config_mb_2023.py', verbose=False) +#change_config('../configs/config_mb_2023_4_mux_2023.py', verbose=False) +#change_config('../configs/config_mb_2024_0_2__4_mux_2023_dps5005.py', verbose=False) from ohmpi.ohmpi import OhmPi from ohmpi.config import OHMPI_CONFIG diff --git a/dev/test_inv.py b/dev/test_inv.py index 40a5791e541d8e8a1412ed8c53209de23f4297bb..2b9d9cef0570b5dc52ac3e5b8b306f531191eefe 100644 --- a/dev/test_inv.py +++ b/dev/test_inv.py @@ -14,8 +14,7 @@ k = OhmPi() # batch inversion xzv = k.run_inversion([ - 'measurement_20220206T194752.csv', - 'measurement_20220206T194852.csv', + 'measurement_20231014T133508.csv' ], reg_mode=0) # make a contour figure with the output @@ -24,8 +23,8 @@ axs = [axs] if len(xzv) == 1 else axs for i, dic in enumerate(xzv): ax = axs[i] x, z = np.meshgrid(dic['x'], dic['z']) - cax = ax.contourf(x, z, dic['rho']) - fig.colorbar(cax, ax=ax, label=r'$\rho$ [$\Omega$.m]') + cax = ax.contourf(x, z, np.log10(dic['rho'])) + fig.colorbar(cax, ax=ax, label=r'$\log_{10}(\rho)$ [$\Omega$.m]') plt.show(block=True) # restore default config diff --git a/env.sh b/env.sh index c32402b17072a3840f8da8da28be101a3695717b..395285f96200717649905de2c45829d2085431cd 100755 --- a/env.sh +++ b/env.sh @@ -1,3 +1,3 @@ # execute this file with "source env.sh" -PYTHONPATH=`pwd` -source ./ohmpy/bin/activate +export PYTHONPATH=`pwd` +source ohmpy/bin/activate diff --git a/index.html b/index.html index 2d8c4eb18c74556192c743c7c11acc60a58d8f20..88914ca66ea3ce37f1ac43f43d8eb224504ba276 100755 --- a/index.html +++ b/index.html @@ -135,9 +135,9 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl </div> </div> <div class="form-group row"> - <label for="elecSpacing" class="col-sm-2 col-form-label">Electrode spacing [m]</label> + <label for="elec_spacing" class="col-sm-2 col-form-label">Electrode spacing [m]</label> <div class="col-sm-10"> - <input type="number" class="form-control" id="elecSpacing", value="1"> + <input type="number" class="form-control" id="elec_spacing", value="1"> </div> </div> </form> @@ -181,7 +181,7 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl let topic_exec = topic + '/exec' let topic_data = topic + '/data' let hostname = location.hostname - let port = 9001 + let port = 9001 // corresponding listener for the broker let clientId = 'ohmpi_0001_html' let message = null let msg = '' @@ -209,6 +209,8 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl function onConnectionLost(responseObject) { if (responseObject.errorCode !== 0) console.log("onConnectionLost:" + responseObject.errorMessage) + console.log("trying to reconnect...") + client.connect({onSuccess: onConnect}) } function onMessageArrived(message) { @@ -403,7 +405,8 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl size: 40, color: [], colorbar: { - title: 'App. res. [Ohm.m]', + title: 'Apparent resistivity [Ohm.m]', + titleside: 'right', cmin: 0, cmax: 100, } @@ -413,7 +416,6 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl title: 'Pseudo-section', yaxis: { title: 'Pseudo-depth', - autorange: 'reversed' }, xaxis: { title: 'X' @@ -462,7 +464,7 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl // callback function to draw the plot function surveySelectFunc(el) { - let elecSpacing = parseFloat(document.getElementById('elecSpacing').value) + let elec_spacing = parseFloat(document.getElementById('elec_spacing').value) let surveyName = el['target'].value let df = data[surveyName] if (df != undefined) { @@ -478,15 +480,15 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl let app = [] for (let i = 0; i < a.length; i++) { - let emin = Math.min(...[a[i], b[i], m[i], n[i]]) - let emax = Math.max(...[a[i], b[i], m[i], n[i]]) + let emin = Math.min(...[a[i], b[i], m[i], n[i]]) * elec_spacing + let emax = Math.max(...[a[i], b[i], m[i], n[i]]) * elec_spacing let dist = Math.abs(emax - emin) xpos.push(emin + dist/2) - ypos.push(Math.sqrt(2)/2 * dist) - let am = Math.abs(a[i] - m[i]) - let bm = Math.abs(b[i] - m[i]) - let an = Math.abs(a[i] - n[i]) - let bn = Math.abs(a[i] - n[i]) + ypos.push(- Math.sqrt(2)/2 * dist) + let am = Math.abs(a[i] - m[i]) * elec_spacing + let bm = Math.abs(b[i] - m[i]) * elec_spacing + let an = Math.abs(a[i] - n[i]) * elec_spacing + let bn = Math.abs(a[i] - n[i]) * elec_spacing let K = (2*Math.PI)/((1/am)-(1/an)-(1/an)+(1/bn)) app.push(df['rho'][i]*K) @@ -496,10 +498,10 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl // 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 am = Math.abs(a - m)*elec_spacing + // let bm = Math.abs(b - m)*elec_spacing + // let an = Math.abs(a - n)*elec_spacing + // let bn = Math.abs(b - n)*elec_spacing // 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 @@ -511,8 +513,8 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl // let ab = (abmn[0] + abmn[1])/2 // let mn = (abmn[2] + abmn[3])/2 // let dist = Math.abs(ab - mn) - // xpos.push((Math.min(ab, mn) + dist/2)*elecSpacing) - // ypos.push((Math.sqrt(2)/2*dist)*elecSpacing) + // xpos.push((Math.min(ab, mn) + dist/2)*elec_spacing) + // ypos.push(- (Math.sqrt(2)/2*dist)*elec_spacing) } console.log('========', app, xpos, ypos) // update the trace and redraw the figure @@ -718,21 +720,44 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl // plot inverted data function showInvFunc() { - let cmin = document.getElementById('cminInv').value - let cmax = document.getElementById('cmaxInv').value - + let cmin = parseFloat(document.getElementById('cminInv').value) + let cmax = parseFloat(document.getElementById('cmaxInv').value) + let autocontour = false + if (isNaN(cmin) | isNaN(cmax)) { + autocontour = true + } + + // convert rho to log10(rho) + let log10rho = [] + for (let i = 0; i < invertedData[0]['rho'].length; i++) { + let row = invertedData[0]['rho'][i] + var arr = [] + for (let j = 0; j < row.length; j++) { + arr.push(Math.log10(row[j])) + } + log10rho.push(arr) + } + var invData = [{ - z: invertedData[0]['rho'], + z: log10rho, x: invertedData[0]['x'], y: invertedData[0]['z'], type: 'contour', colorscale: 'Viridis', - autocontour: true, // set to false if cmin is given + autocontour: autocontour, contours: { start: cmin, end: cmax, - size: 10 + size: 10, }, + colorbar:{ + title: 'Resistivity (log10) [Ohm.m]', + titleside: 'right', + titlefont: { + size: 14, + family: 'Arial, sans-serif' + } + } }] var invLayout = { @@ -742,7 +767,7 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl }, xaxis: { title: 'X [m]' - } + }, } Plotly.newPlot('inv', invData, invLayout, {responsive: true}) @@ -759,10 +784,15 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl var btn = document.getElementById('invertBtn') btn.innerText = 'Inverting...' btn.className = 'btn btn-warning' + var elec_spacing = parseFloat(document.getElementById('elec_spacing').value) + if (isNaN(elec_spacing)) { + elec_spacing = 1 + } sendCommand(JSON.stringify({ 'cmd': 'run_inversion', 'kwargs': { - 'survey_names': [survey_name + '.csv'] + 'survey_names': [survey_name + '.csv'], + 'elec_spacing': elec_spacing, } }), function(x) { console.log('inversion results', x) diff --git a/install.sh b/install.sh index f9835d0c3d4352a0a901b10d71c25b34e76904b2..b63860c8553c9903be2aa8f88bc02f0adc1e05fa 100755 --- a/install.sh +++ b/install.sh @@ -32,9 +32,11 @@ sudo systemctl enable mosquitto.service echo -e "\n${txtgrn}>>> Broker is installed. Starting now...${txtdef}" mosquitto -v -echo -e "\n${txtgrn}>>> Updating configuration to allow anonymous remote connections...${txtdef}" +echo -e "\n${txtgrn}>>> Updating configuration to allow anonymous remote connections and websockets...${txtdef}" +echo "listener 9001" | sudo tee -a /etc/mosquitto/mosquitto.conf echo "listener 1883" | sudo tee -a /etc/mosquitto/mosquitto.conf +echo "protocol websockets" | sudo tee -a /etc/mosquitto/mosquitto.conf +echo "socket_domain ipv4" | sudo tee -a /etc/mosquitto/mosquitto.conf echo "allow_anonymous true" | sudo tee -a /etc/mosquitto/mosquitto.conf echo -e "\n${txtgrn}>>> Current configuration stored in /etc/mosquitto/mosquitto.conf is displayed below${txtdef}" cat /etc/mosquitto/mosquitto.conf -echo -e "\n${txtylw}>>> Adapt it according to your needs!${txtdef}\n" diff --git a/ohmpi/config.py b/ohmpi/config.py index abba800afd622de78efddc9ff8fb62855863ab22..f3f566ba70a9fb3bf7797821b95578b28d48a232 100644 --- a/ohmpi/config.py +++ b/ohmpi/config.py @@ -1,5 +1,6 @@ import logging from ohmpi.utils import get_platform + from paho.mqtt.client import MQTTv31 # noqa _, on_pi = get_platform() @@ -19,55 +20,33 @@ OHMPI_CONFIG = { r_shunt = 2. HARDWARE_CONFIG = { 'ctl': {'model': 'raspberry_pi'}, - 'pwr': {'model': 'pwr_dps5005', 'voltage': 3., 'interface_name': 'modbus'}, - 'tx': {'model': 'mb_2024_0_2', + 'pwr': {'model': 'pwr_batt', 'voltage': 12., 'interface_name': 'none'}, + 'tx': {'model': 'mb_2023_0_X', 'voltage_max': 50., # Maximum voltage supported by the TX board [V] 'current_max': 4.80/(50*r_shunt), # Maximum voltage read by the current ADC on the TX board [A] 'r_shunt': r_shunt, # Shunt resistance in Ohms 'interface_name': 'i2c' }, - 'rx': {'model': 'mb_2024_0_2', - 'coef_p2': 1.00, # slope for conversion for ADS, measurement in V/V - 'latency': 0.010, # latency in seconds in continuous mode - 'sampling_rate': 50, # number of samples per second - 'interface_name': 'i2c' + 'rx': {'model': 'mb_2023_0_X', + 'coef_p2': 2.50, # slope for conversion for ADS, measurement in V/V + 'sampling_rate': 50., # number of samples per second + 'interface_name': 'i2c', }, - 'mux': {'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_ext', + 'mux': # default properties given in config are system properties that will be + # 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 + # omitted properties in config will be set to board specs default values if they exist + {'boards': {}, + 'default': {'interface_name': 'i2c', 'voltage_max': 100., 'current_max': 3.} - } - } + } +} # SET THE LOGGING LEVELS, MQTT BROKERS AND MQTT OPTIONS ACCORDING TO YOUR NEEDS # Execution logging configuration EXEC_LOGGING_CONFIG = { - 'logging_level': logging.INFO, + 'logging_level': logging.DEBUG, # TODO: set logging level back to INFO 'log_file_logging_level': logging.DEBUG, 'logging_to_console': True, 'file_name': f'exec{logging_suffix}.log', diff --git a/ohmpi/ohmpi.py b/ohmpi/ohmpi.py index f3b73220a86e18f5a09aa098f21cac544b808464..dd3c97c308b3d84d062a510b4673366ecdb9d309 100644 --- a/ohmpi/ohmpi.py +++ b/ohmpi/ohmpi.py @@ -1061,7 +1061,7 @@ class OhmPi(object): elif len(survey_names) > 0 and reg_mode > 0: k.createTimeLapseSurvey(fnames, parser=ohmpiParser) self.exec_logger.info('ResIPy: generate mesh') - k.createMesh('trian') + k.createMesh('trian', cl=elec_spacing/5) self.exec_logger.info('ResIPy: invert survey') k.invert(param=kwargs) @@ -1074,20 +1074,20 @@ class OhmPi(object): x = np.linspace(df['X'].min(), df['X'].max(), 20) z = np.linspace(df['Z'].min(), df['Z'].max(), 20) grid_x, grid_z = np.meshgrid(x, z) - grid_z = griddata(df[['X', 'Z']].values, df['Resistivity(ohm.m)'].values, - (grid_x, grid_z), method='linear') + grid_v = griddata(df[['X', 'Z']].values, df['Resistivity(ohm.m)'].values, + (grid_x, grid_z), method='nearest') # set nan to -1 - inan = np.isnan(grid_z) - grid_z[inan] = -1 + inan = np.isnan(grid_v) + grid_v[inan] = -1 xzv.append({ 'x': x.tolist(), 'z': z.tolist(), - 'rho': grid_z.tolist(), + 'rho': grid_v.tolist(), }) - self.data_logger.info(json.dumps(xzv)) # limited to one survey + self.data_logger.info(json.dumps(xzv)) return xzv # Properties diff --git a/run_http_interface.sh b/run_http_interface.sh index f98f082f9b176adf1a1a0afa429146ab9fb33c16..faa4924d61a7f83f76439c26130c3bdcd560a416 100755 --- a/run_http_interface.sh +++ b/run_http_interface.sh @@ -1,7 +1,5 @@ -#!bin/bash -export PYTHONPATH=/home/$USER/OhmPi -cd /home/$USER/OhmPi -source /home/$USER/OhmPi/ohmpy/bin/activate +export PYTHONPATH=`pwd` +source $PYTHONPATH/ohmpy/bin/activate python dev/start_mqtt_html.py & # run ohmpi.py to capture the commands -python3 -m http.server # run web GUI +python -m http.server # run web GUI