Direct Current and Induced Polarization (DC-IP)¶
This survey type is meant to handle direct-current resistivity data. The survey object is made up of two curve entities defining the transmitter (current) and receiver (potential) electrodes.
The following example shows how to generate a DC-IP survey with associated data stored in geoh5
format and accessible from Geoscience ANALYST.
Current Electrode (transmitters)¶
The CurrentElectrode entity defines the A-B dipole pairs used to inject current into the ground. It is a sub-class of the PotentialElectrode object defined by vertices (poles) and cells (dipoles). Here we generate four (4) parallel EW lines with eight dipoles per line.
[1]:
import numpy as np
import uuid
from geoh5py.workspace import Workspace
from geoh5py.objects import CurrentElectrode, PotentialElectrode
# Create a new project
workspace = Workspace("my_project.geoh5")
# Define the pole locations
n_poles = 9
n_lines = 2
x_loc, y_loc = np.meshgrid(np.linspace(0, 60, n_poles), np.linspace(-20, 20., n_lines))
vertices = np.c_[x_loc.ravel(), y_loc.ravel(), np.zeros_like(x_loc).ravel()]
# Assign a line ID to the poles (vertices)
parts = np.kron(np.arange(n_lines), np.ones(n_poles)).astype('int')
# Create the CurrentElectrode object
currents = CurrentElectrode.create(workspace, vertices=vertices, parts=parts)
At this stage the CurrentElectrode
object has segments (cells
) connecting all poles in series along line.
AB Cell ID¶
A key element of the DCIP survey objects is the ab_cell_id
property. This ReferenceData
contains the map referencing each cell of the CurrentElectrode
object to a unique A-B source identifier with name.
The utility function add_default_ab_cell_id can help generate this map with a simple name string incrementor.
[2]:
currents.add_default_ab_cell_id()
print(currents.ab_cell_id.value_map.map)
{0: 'Unknown', 1: '1', 2: '2', 3: '3', 4: '4', 5: '5', 6: '6', 7: '7', 8: '8', 9: '9', 10: '10', 11: '11', 12: '12', 13: '13', 14: '14', 15: '15', 16: '16'}
In this specific case, every cell
on the curve corresponds to a unique dipole source current. For more complex survey configurations, users can edit the cell
property in order to define different combinations of connections between poles.
Note: The first entry {0:Unknown}
is a reserved field used by Geoscience ANALYST to flag unknown data entries.
Potential Electrode (receivers)¶
The PotentialElectrode object defines the M-N dipole pairs used to measure the electric potential (receivers). It is a sub-class of the Curve object defined by vertices
(poles) and cells
(dipoles).
Although poles could be set independently on the CurrentElectrode
and PotentialElectrode
objects, here we re-uses the same locations for simplicity:
[3]:
potentials = PotentialElectrode.create(workspace, vertices=vertices)
Next, we must define the receiver dipoles. The following routine generates a maximum of six (6) receivers dipoles per injection currents along line.
[4]:
N = 6
dipoles = []
current_id = []
for val in currents.ab_cell_id.values: # For each source dipole
if val == 0: # Skip the unknown
continue
cell_id = val - 1 # Python 0 indexing
line = currents.parts[currents.cells[cell_id, 0]]
for m_n in range(N):
dipole_ids = (currents.cells[cell_id, :] + 2 + m_n).astype("uint32") # Skip two poles
# Shorten the array as we get to the end of the line
if (
any(dipole_ids > (potentials.n_vertices - 1))
or any(currents.parts[dipole_ids] != line)
):
continue
dipoles += [dipole_ids] # Save the receiver id
current_id += [val] # Save the source id
potentials.cells = np.vstack(dipoles)
Finally, users need to create an association between each receiver dipole (M-N) to a dipole current (A-B). The mapping is done through the ab_cell_id
property of the PotentialElectrode
. An integer (ID) value must be assigned to each cell, corresponding to the AB Cell ID
pairs stored on the associated CurrentElectrode
object.
[5]:
potentials.ab_cell_id = np.asarray(current_id, dtype="int32")
Metadata¶
The link between the sources CurrentElectrode and the receivers PotentialElectrode is established by the metadata
, shared by both entities. The connection can be made by assigning current_electrodes
to the receivers:
[6]:
potentials.current_electrodes = currents
or equivalently by setting potential_electrodes
to the currents
[7]:
currents.potential_electrodes = potentials
In both cases, the link between the two objects gets encoded automatically to their respective metadata
.
[8]:
print(potentials.metadata == currents.metadata)
currents.metadata
True
[8]:
{'Current Electrodes': UUID('da517a89-5f4c-4439-a954-228baca0a48a'),
'Potential Electrodes': UUID('66c04609-161e-41b3-b38e-3bf1da14c9d4')}
Note: The ab_cell_id
property of the CurrentElectrode
and PotentialElectrode
are two different ReferenceData
entities:
[9]:
print(potentials.ab_cell_id == currents.ab_cell_id)
False
but share the same DataType
that holds the map of unique source dipoles.
[10]:
print(potentials.ab_cell_id.entity_type == currents.ab_cell_id.entity_type)
True
This link between DataType
allows users to query the data by dipole sources and display the values as pseudo-section in Geoscience ANALYST