Source code for reda.importers.res2dinv

"""Importer for RES2DINV files

Please note that this importer is very rudimentary at the moment. We need test
data and real usage to improve upon this.

"""
from io import StringIO
import logging

import pandas as pd

from reda.utils.electrode_manager import electrode_manager

logger = logging.getLogger(__name__)


[docs] def import_res2dinv(filename, **kwargs): """ Read a RES2DINV-style Parameters ---------- Returns ------- data : :py:class:`pandas.DataFrame` Contains the measurement data elec_mgr : :py:class:`reda.utils.electrode_manager.electrode_manager` Electrode manager that manages the electrode positions topography : None No topography information is contained in the text files, so we always return None """ # each type is read by a different function importers = { # general array type 11: _read_general_type, } file_type, content = _read_file(filename) if file_type not in importers: raise Exception( 'type of RES2DINV data file not recognized: {0}'.format(file_type) ) header, data, elec_mgr = importers[file_type](content) topography = None return data, elec_mgr, topography
def _read_file(filename): """ Read a res2dinv-file and return the header Parameters ---------- filename : str Data filename Returns ------ type : int type of array extracted from header file_data : :py:class:`StringIO.StringIO` content of file in a StringIO object """ # read data from file with open(filename, 'r') as fid2: abem_data_orig = fid2.read() # for easy access, store the data in a StringIO container fid = StringIO() fid.write(abem_data_orig) fid.seek(0) # determine type of array fid.readline() fid.readline() file_type = int(fid.readline().strip()) # reset file pointer fid.seek(0) return file_type, fid def _read_general_type(content): """Read a type 11 (general type) RES2DINV data block Parameters ---------- content : :py:class:`StringIO.StringIO` Content of data file Returns ------- """ header_raw = [] index = 0 while index < 9: line = content.readline() # filter comments if line.startswith('//'): continue else: header_raw.append(line.strip()) index += 1 # parse header header = { 'name': header_raw[0], # unit is meters? 'unit_spacing': float(header_raw[1]), 'array_type': int(header_raw[2]), 'type2': int(header_raw[3]), 'type_of_measurements': int(header_raw[5]), 'nr_measurements': int(header_raw[6]), 'type_of_x_location': int(header_raw[7]), 'ip_data': int(header_raw[8]), } if header['type_of_measurements'] == 0: raise Exception('Reading in app. resistivity not supported yet') df = pd.read_csv( content, delim_whitespace=True, header=None, names=( 'nr_elecs', 'x1', 'z1', 'x2', 'z2', 'x3', 'z3', 'x4', 'z4', 'value', ), nrows=header['nr_measurements'], ) # type of x-location # 0: true horizontal distance # 1: true horizontal distance # 2: surface distance elec_mgr = electrode_manager() # for now ignore the z coordinates and compute simple electrode denotations df['a'] = df['x1'] / header['unit_spacing'] + 1 df['b'] = df['x2'] / header['unit_spacing'] + 1 df['m'] = df['x3'] / header['unit_spacing'] + 1 df['n'] = df['x4'] / header['unit_spacing'] + 1 # for now assume value in resistances df['r'] = df['value'] # ABMN are integers df['a'] = df['a'].astype(int) df['b'] = df['b'].astype(int) df['m'] = df['m'].astype(int) df['n'] = df['n'].astype(int) # remove any nan values df.dropna(axis=0, subset=['a', 'b', 'm', 'n', 'r'], inplace=True) # drop unused columns df.drop( [ 'nr_elecs', 'x1', 'z1', 'x2', 'z2', 'x3', 'z3', 'x4', 'z4', 'value', ], axis=1, inplace=True ) return header, df, elec_mgr