From 0659b4f00f4c8f3512707d89fde0d8f4270437e9 Mon Sep 17 00:00:00 2001
From: jkl <sagitta1618@gmail.com>
Date: Tue, 17 Oct 2023 14:49:14 +0200
Subject: [PATCH] Add simple 2D inversion using ResIPy to OhmPi

---
 dev/test_inv.py      | 12 ++++++
 html/index-mqtt.html |  1 -
 ohmpi/ohmpi.py       | 98 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 110 insertions(+), 1 deletion(-)
 create mode 100644 dev/test_inv.py

diff --git a/dev/test_inv.py b/dev/test_inv.py
new file mode 100644
index 00000000..b212d585
--- /dev/null
+++ b/dev/test_inv.py
@@ -0,0 +1,12 @@
+
+#
+from ohmpi.utils import change_config
+change_config('../configs/config_mb_2023.py', verbose=False)
+
+from ohmpi.ohmpi import OhmPi
+k = OhmPi()
+k.run_inversion(['measurement_20220206T194552.csv'])
+
+
+# restore default config
+change_config('../configs/config_default.py', verbose=False)
diff --git a/html/index-mqtt.html b/html/index-mqtt.html
index 070d4fe1..7c121aea 100755
--- a/html/index-mqtt.html
+++ b/html/index-mqtt.html
@@ -59,7 +59,6 @@
         
         <!-- Additional buttons -->
         <button id="downloadBtn" type="button" class="btn btn-primary">Download data</button>
-        <!-- <button id="invertBtn" type="button" class="btn btn-primary">Invert</button> -->
         <a id="download"></a>
 
         <!-- Modal for configuration -->
diff --git a/ohmpi/ohmpi.py b/ohmpi/ohmpi.py
index 905acb8e..2035c81d 100644
--- a/ohmpi/ohmpi.py
+++ b/ohmpi/ohmpi.py
@@ -917,6 +917,104 @@ class OhmPi(object):
 
         return status
 
+    def run_inversion(self, survey_names=[], elec_spacing=1, **kwargs):
+        """Run a simple 2D inversion using ResIPy.
+        
+        Parameters
+        ----------
+        survey_names : list of string, optional
+            Filenames of the survey to be inverted (including extension).
+        elec_spacing : float (optional)
+            Electrode spacing in meters. We assume same electrode spacing everywhere.
+        kwargs : optional
+            Additiona keyword arguments passed to `resipy.Project.invert()`. For instance
+            `reg_mode` == 0 for batch inversion, `reg_mode == 2` for time-lapse inversion.
+            See ResIPy document for more information on options available
+            (https://hkex.gitlab.io/resipy/).
+
+        Returns
+        -------
+        xzv : list of dict
+            Each dictionnary with key 'x' and 'z' for the centroid of the elements and 'v'
+            for the values in resistivity of the elements.
+        """
+        # check if we have any files to be inverted
+        if len(survey_names) == 0:
+            self.exec_logger('No file to invert')
+            return []
+        
+        # check if user didn't provide a single string instead of a list
+        if isinstance(survey_names, str):
+            survey_names = [survey_names]
+
+        # check kwargs for reg_mode
+        if 'reg_mode' in kwargs:
+            reg_mode = kwargs['reg_mode']
+        else:
+            reg_mode = 0
+            kwargs['reg_mode'] = 0
+
+        pdir = os.path.dirname(__file__)
+        # import resipy if available
+        try:
+            import pandas as pd
+            import sys
+            sys.path.append(os.path.join(pdir, '../../resipy/src/'))
+            from resipy import Project
+        except Exception as e:
+            self.exec_logger.error('Cannot import ResIPy or Pandas, error: ' + str(e))
+            return []
+
+        # get absolule filename
+        fnames = []
+        for survey_name in survey_names:
+            fname = os.path.join(pdir, '../data', survey_name)
+            if os.path.exists(fname):
+                fnames.append(fname)
+            else:
+                self.exec_logger.warning(fname + ' not found')
+        
+        # define a parser for the "ohmpi" format
+        def ohmpiParser(fname):
+            df = pd.read_csv(fname)
+            df = df.rename(columns={'A':'a', 'B':'b', 'M':'m', 'N':'n'})
+            df['vp'] = df['Vmn [mV]']
+            df['i'] = df['I [mA]']
+            df['resist'] = df['vp']/df['i']
+            df['ip'] = np.nan
+            emax = np.max(df[['a', 'b', 'm', 'n']].values)
+            elec = np.zeros((emax, 3))
+            elec[:, 0] = np.arange(emax) * elec_spacing
+            return elec, df[['a','b','m','n','vp','i','resist','ip']]
+                
+        # run inversion
+        self.exec_logger.info('ResIPy: import surveys')
+        k = Project(typ='R2')  # invert in a temporary directory that will be erased afterwards
+        if len(survey_names) == 1:
+            k.createSurvey(fnames[0], parser=ohmpiParser)
+        elif len(survey_names) > 0 and reg_mode == 0:
+            k.createBatchSurvey(fnames, parser=ohmpiParser)
+        elif len(survey_names) > 0 and reg_mode > 0:
+            k.createTimeLapseSurvey(fnames, parser=ohmpiParser)
+        self.exec_logger.info('ResIPy: generate mesh')
+        k.createMesh('trian')
+        self.exec_logger.info('ResIPy: invert survey')
+        k.invert(param=kwargs)
+
+        # read data
+        self.exec_logger.info('Reading inverted surveys')
+        k.getResults()
+        xzv = []
+        for m in k.meshResults:
+            df = m.df
+            xzv.append({
+                'x': df['X'].values.tolist(),
+                'z': df['Z'].values.tolist(),
+                'rho': df['Resistivity(ohm.m)'].values.tolist(),
+            })
+        
+        return xzv
+
     # Properties
     @property
     def sequence(self):
-- 
GitLab