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 uuid
from pathlib import Path
import numpy as np
from geoh5py.objects import CurrentElectrode, PotentialElectrode
from geoh5py.workspace import Workspace
# 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.0, 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, b'Unknown') ( 1, b'1') ( 2, b'2') ( 3, b'3') ( 4, b'4') ( 5, b'5')
( 6, b'6') ( 7, b'7') ( 8, b'8') ( 9, b'9') (10, b'10') (11, b'11')
(12, b'12') (13, b'13') (14, b'14') (15, b'15') (16, b'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. We must also define the receiver dipoles. The following routine generates a maximum of six (6) receivers dipoles per injection currents along line.
[3]:
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 > (len(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 = PotentialElectrode.create(
workspace, vertices=vertices, 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.
[4]:
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:
[5]:
potentials.current_electrodes = currents
or equivalently by setting potential_electrodes
to the currents
[6]:
currents.potential_electrodes = potentials
In both cases, the link between the two objects gets encoded automatically to their respective metadata
.
[7]:
print(potentials.metadata == currents.metadata)
currents.metadata
True
[7]:
{'Current Electrodes': UUID('8d933913-4efe-46e4-971a-4f738d2f5a83'),
'Potential Electrodes': UUID('6f52952b-c7f8-43d7-902f-7f477d7eefdd')}
Note: The ab_cell_id
property of the CurrentElectrode
and PotentialElectrode
are two different ReferenceData
entities:
[8]:
print(potentials.ab_cell_id == currents.ab_cell_id)
False
but share the same DataType
that holds the map of unique source dipoles.
[9]:
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
[10]:
workspace.close()