Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pozo/renderers/plotly.py
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ def get_traces(self, graph, yaxis='y1', xstart=1, **kwargs):
fillcolor)
# we will lock both axes completely but it seems like mutual zoom operations are ok
# notes above on how to do that
if themes['intervals'] == 'category':
if False:
pass
else:
all_traces.append(go.Scatter(
Expand Down
2 changes: 1 addition & 1 deletion pozo/renderers/tree_table.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import pozo.renderers as pzr
from IPython.core.display import HTML, display, Javascript
from IPython.display import HTML, display, Javascript
import html

def javascript():
Expand Down
35 changes: 21 additions & 14 deletions pozo/tracks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@
import pozo
import pozo.themes as pzt

class Track(ood.Item, pzt.Themeable):

class Track(ood.Item, pzt.Themeable):
def set_name(self, name):
return super().set_name(name)

def get_name(self):
return super().get_name()

_type="track"
_child_type="axis"
_type = "track"
_child_type = "axis"

def __init__(self, *args, **kwargs):
super().__init__(**kwargs)
self.note_dict = {}
Expand All @@ -26,20 +27,24 @@ def _check_types(self, *axes):
if isinstance(axis, (list)):
raw_return.extend(self._check_types(*axis))
elif not isinstance(axis, accepted_types):
raise TypeError(f"Axis.add_axes() only accepts axes, and traces: pozo objects, not {type(axis)}")
raise TypeError(
f"Axis.add_axes() only accepts axes, and traces: pozo objects, not {type(axis)}"
)
elif isinstance(axis, pozo.Trace):
raw_return.append(pozo.Axis(axis, name=axis.get_name()))
else:
raw_return.append(axis)
return raw_return

def replace_axes(self, *axes, **kwargs):
mnemonics = []
for axis in axes:
for trace in axis.get_traces():
mnemonics.append(trace.get_mnemonic())
self.pop_axes(*mnemonics, strict_index=False, exclude=kwargs.get('exclude', None))
self.add_axes(*axes, **kwargs)
mnemonics = []
for axis in axes:
for trace in axis.get_traces():
mnemonics.append(trace.get_mnemonic())
self.pop_axes(
*mnemonics, strict_index=False, exclude=kwargs.get("exclude", None)
)
self.add_axes(*axes, **kwargs)

# add_items
def add_axes(self, *axes, **kwargs):
Expand Down Expand Up @@ -84,11 +89,13 @@ def get_traces(self, *selectors, **kwargs):

def get_trace(self, selector=0, **kwargs):
ret = self.get_traces(selector, **kwargs)
if len(ret) == 0: return None
if len(ret) == 0:
return None
return ret[0]

def get_theme(self):
context = { "type":"track",
"name": self._name,
}
context = {
"type": "track",
"name": self._name,
}
return self._get_theme(context=context)
164 changes: 80 additions & 84 deletions pozo/units/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,63 +5,24 @@
from io import StringIO
import pandas as pd

from .units import MissingRangeError, LasMapEntry
from .units import LasRegistry, UnitException, MissingLasUnitWarning
import re
from .registry_config import registry_defines, registry_mapping

from .units import (
MissingRangeError,
UnitException,
MissingLasUnitWarning,
LasRegistry,
)
import re

registry = LasRegistry()
Quantity = Q = registry.Quantity # Overriding the registry and all this is a little weird

registry.define('gamma_API_unit = [Gamma_Ray_Tool_Response] = gAPI')
registry.define("porosity_unit = percent = pu")
registry.define("of_1 = 100 * percent = fraction")
registry.define("legacy_api_porosity_unit = [Legacy_API_Porosity_Unit] = puAPI")

PU = [
LasMapEntry((-50, 80), "pu", "decide by range - MEDIUM"),
LasMapEntry((-.5, .8), "of_1", "decide by range - MEDIUM"),
LasMapEntry((), "puAPI", "catch all, legacy unit - LOW"),
]
percent_general = [
LasMapEntry((-100, 100), "percent", "decide by range, verify - LOW"),
LasMapEntry((-1, 1), "of_1", "decide by range, verify - LOW"),
LasMapEntry((), "ppm", "catch all, ppm - LOW" ),
]

registry.add_las_map('-', 'MM' , 'millimeter' , "decided without mnemonic- MEDIUM")
registry.add_las_map('-', 'M' , 'meter' , "decided without mnemonic- MEDIUM")
registry.add_las_map('-', 'CM' , 'centimeter' , "decided without mnemonic- MEDIUM")
registry.add_las_map('-', 'GAPI', 'gAPI' , "decided without mnemonic- MEDIUM")
registry.add_las_map('-', 'DEG_C', 'celsius' , "decided without mnemonic- MEDIUM")
registry.add_las_map('-', 'DEG_F', 'fahrenheit' , "decided without mnemonic- MEDIUM")
registry.add_las_map('-', 'COUNTS/S', 'cps' , "decided without mnemonic- MEDIUM")
registry.add_las_map('-', 'CPS', 'cps' , "decided without mnemonic- MEDIUM")
registry.add_las_map('DEPT', 'M' , 'meter' , "HIGH")
registry.add_las_map('DEPT', 'FT' , 'feet' , "HIGH")
registry.add_las_map('DEPT', 'F' , 'feet' , "HIGH")
registry.add_las_map('GR' , 'GAPI', 'gAPI' , "HIGH")
registry.add_las_map('GR' , '', 'gAPI' , "HIGH")
registry.add_las_map('CGR' , 'GAPI', 'gAPI' , "HIGH")
registry.add_las_map('CALI', 'CM' , 'centimeter' , "HIGH")
registry.add_las_map('CALI', 'IN' , 'inch' , "HIGH")
registry.add_las_map('DRHO', 'G/C3', 'gram / centimeter ** 3' , "HIGH")
registry.add_las_map('RHOB', 'G/C3', 'gram / centimeter ** 3' , "HIGH")
registry.add_las_map('DT' , 'US/F', 'microsecond / foot' , "HIGH")
registry.add_las_map('ILD' , 'OHMM', 'ohm * meter' , "HIGH")
registry.add_las_map('LLS' , 'OHMM', 'ohm * meter' , "HIGH")
registry.add_las_map('ILM' , 'OHMM', 'ohm * meter' , "HIGH")
registry.add_las_map('LLD' , 'OHMM', 'ohm * meter' , "HIGH")
registry.add_las_map('SFL' , 'OHMM', 'ohm * meter' , "HIGH")
registry.add_las_map('SGR' , 'GAPI', 'gAPI' , "HIGH")
registry.add_las_map('SP' , 'MV' , 'millivolt' , "HIGH")
registry.add_las_map('MSFL', 'OHMM', 'ohm * meter' , "HIGH")
registry.add_las_map('NPHI', 'PU' , PU)
registry.add_las_map('NPHI', 'PU%' , 'pu' , "HIGH")
registry.add_las_map('PEF' , '' , percent_general)
registry.add_las_map('POTA', '' , percent_general)
registry.add_las_map('THOR', '' , percent_general)
registry.add_las_map('URAN', '' , percent_general)
Quantity = Q = (
registry.Quantity
) # Overriding the registry and all this is a little weird

registry_defines(registry)
registry_mapping(registry)


# TODO: Beginning of a database, has to go online
# mnemonics, synonyms (resolve- matching in theme,
Expand All @@ -71,13 +32,15 @@
# versioning, searching
# also want it to point to posts

desc_wo_num = re.compile(r'^(?:\s*\d+\s+)?(.*)$')
red_low = re.compile(r'<td>(.+)?(?:LOW|NONE)(.+)?</td>')
orange_medium = re.compile(r'<td>(.+)?MEDIUM(.+)?</td>')
desc_wo_num = re.compile(r"^(?:\s*\d+\s+)?(.*)$")
red_low = re.compile(r"<td>(.+)?(?:LOW|NONE)(.+)?</td>")
orange_medium = re.compile(r"<td>(.+)?MEDIUM(.+)?</td>")


def check_las(las, registry=registry, HTML_out=True, divid=""):
def n0(s): # If None, convert to ""
def n0(s): # If None, convert to ""
return "" if s is None else str(s)

# using the warnings like this kind sucks
# they do need to be surpressed becuase i'm building a better view into the warnings anyway
# with this function, but that resolved = on 87 w/ 91 = on 91 is really weird.
Expand All @@ -86,57 +49,90 @@ def n0(s): # If None, convert to ""
with warnings.catch_warnings():
warnings.simplefilter("default")
warnings.filterwarnings("error", category=MissingLasUnitWarning)

d = chr(0X1e) # delimiter
col_names = f"mnemonic{d}las unit{d}pozo mapping{d}confidence{d}parsed{d}description{d}min{d}med{d}max{d}#NaN"
result = [col_names] if HTML_out else []
col_names = [
"mnemonic", "las unit", "pozo mapping", "confidence",
"parsed", "description", "min", "med", "max", "#NaN"
]
result = [f"{d}".join(col_names)] if HTML_out else []
for curve in las.curves:
resolved = None
pozo_match = None
confidence = None
parsed = None
try:
resolved = registry.resolve_las_unit(curve.mnemonic, curve.unit, curve.data)
resolved = registry.resolve_las_unit(
curve.mnemonic, curve.unit, curve.data
)
if resolved is not None:
pozo_match = resolved.unit
confidence = resolved.confidence
parsed = registry.parse_unit_from_context(curve.mnemonic, curve.unit, curve.data)
if resolved is None: raise MissingLasUnitWarning("Parsed directly from LAS, probably wrong")
except (pint.UndefinedUnitError, MissingRangeError, UnitException, MissingLasUnitWarning) as e:
confidence = " - " + str(e) + " - NONE"
parsed = registry.parse_unit_from_context(
curve.mnemonic, curve.unit, curve.data
)
if resolved is None:
raise MissingLasUnitWarning(
"Parsed directly from LAS, probably wrong"
)
except (
pint.UndefinedUnitError,
MissingRangeError,
UnitException,
MissingLasUnitWarning,
) as e:
confidence = f" - {str(e)} - NONE"

find_desc = desc_wo_num.findall(curve.descr)
desc = find_desc[0] if len(find_desc) > 0 else curve.descr
[v_min, v_med, v_max] = [str(x) for x in np.nanquantile(curve.data, [0, .5, 1])]

v_min, v_med, v_max = map(str, np.nanquantile(curve.data, [0, 0.5, 1]))
n_nan = np.count_nonzero(np.isnan(curve.data))

curve_data = dict(
mnemonic = curve.mnemonic,
las_unit = curve.unit,
pozo_match = pozo_match,
confidence = confidence,
parsed_unit = parsed,
desc = desc,
v_min = v_min,
v_med = v_med,
v_max = v_max,
n_nan = np.count_nonzero(np.isnan(curve.data)))
if not HTML_out: result.append(curve_data)
else: result.append(d.join([n0(x) for x in curve_data.values()]))
if not HTML_out: return result
mnemonic=curve.mnemonic,
las_unit=curve.unit,
pozo_match=pozo_match,
confidence=confidence,
parsed_unit=parsed,
desc=desc,
v_min=v_min,
v_med=v_med,
v_max=v_max,
n_nan=n_nan,
)
if not HTML_out:
result.append(curve_data)
else:
result.append(d.join([n0(x) for x in curve_data.values()]))

if not HTML_out:
return result

try:
post_result = "\n".join(result)
output = pd.read_csv(StringIO(post_result), delimiter=d, na_filter=False).to_html()
output = pd.read_csv(
StringIO(post_result), delimiter=d, na_filter=False
).to_html()

for match in red_low.finditer(output):
current_match = match.group()
colored = "<td style=\"color:red\">" + current_match[4:]
colored = '<td style="color:red">' + current_match[4:]
output = output.replace(current_match, colored)

for match in orange_medium.finditer(output):
current_match = match.group()
colored = "<td style=\"color:#B95000\">" + current_match[4:]
colored = '<td style="color:#B95000">' + current_match[4:]
output = output.replace(current_match, colored)
display(HTML('<div id="'+divid+'">'+output+'</div>'))

display(HTML(f'<div id="{divid}">{output}</div>'))

except Exception as e:
display(str(e))
display(HTML("<br>".join(result)))

# Just a shorcut to make the API nice

# Just a shortcut to make the API nice
def parse_unit_from_curve(curve, registry=registry):
try:
return registry.parse_unit_from_context(curve.mnemonic, curve.unit, curve.data)
Expand Down
16 changes: 16 additions & 0 deletions pozo/units/errors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
class MissingLasUnitWarning(UserWarning):
"""Warning for unresolved LAS units."""

pass


class UnitException(Exception):
"""Raised when unit parsing fails."""

pass


class MissingRangeError(Exception):
"""Raised when no matching range is found for LAS data."""

pass
56 changes: 56 additions & 0 deletions pozo/units/registry_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from .units import LasMapEntry


PU = [
LasMapEntry((-50, 80), "pu", "decide by range - MEDIUM"),
LasMapEntry((-0.5, 0.8), "of_1", "decide by range - MEDIUM"),
LasMapEntry((), "puAPI", "catch all, legacy unit - LOW"),
]
percent_general = [
LasMapEntry((-100, 100), "percent", "decide by range, verify - LOW"),
LasMapEntry((-1, 1), "of_1", "decide by range, verify - LOW"),
LasMapEntry((), "ppm", "catch all, ppm - LOW"),
]


def registry_defines(registry):
registry.define("gamma_API_unit = [Gamma_Ray_Tool_Response] = gAPI")
registry.define("porosity_unit = percent = pu")
registry.define("of_1 = 100 * percent = fraction")
registry.define("legacy_api_porosity_unit = [Legacy_API_Porosity_Unit] = puAPI")


def registry_mapping(registry):
registry.add_las_map("-", "MM", "millimeter", "decided without mnemonic- MEDIUM")
registry.add_las_map("-", "M", "meter", "decided without mnemonic- MEDIUM")
registry.add_las_map("-", "CM", "centimeter", "decided without mnemonic- MEDIUM")
registry.add_las_map("-", "GAPI", "gAPI", "decided without mnemonic- MEDIUM")
registry.add_las_map("-", "DEG_C", "celsius", "decided without mnemonic- MEDIUM")
registry.add_las_map("-", "DEG_F", "fahrenheit", "decided without mnemonic- MEDIUM")
registry.add_las_map("-", "COUNTS/S", "cps", "decided without mnemonic- MEDIUM")
registry.add_las_map("-", "CPS", "cps", "decided without mnemonic- MEDIUM")
registry.add_las_map("DEPT", "M", "meter", "HIGH")
registry.add_las_map("DEPT", "FT", "feet", "HIGH")
registry.add_las_map("DEPT", "F", "feet", "HIGH")
registry.add_las_map("GR", "GAPI", "gAPI", "HIGH")
registry.add_las_map("GR", "", "gAPI", "HIGH")
registry.add_las_map("CGR", "GAPI", "gAPI", "HIGH")
registry.add_las_map("CALI", "CM", "centimeter", "HIGH")
registry.add_las_map("CALI", "IN", "inch", "HIGH")
registry.add_las_map("DRHO", "G/C3", "gram / centimeter ** 3", "HIGH")
registry.add_las_map("RHOB", "G/C3", "gram / centimeter ** 3", "HIGH")
registry.add_las_map("DT", "US/F", "microsecond / foot", "HIGH")
registry.add_las_map("ILD", "OHMM", "ohm * meter", "HIGH")
registry.add_las_map("LLS", "OHMM", "ohm * meter", "HIGH")
registry.add_las_map("ILM", "OHMM", "ohm * meter", "HIGH")
registry.add_las_map("LLD", "OHMM", "ohm * meter", "HIGH")
registry.add_las_map("SFL", "OHMM", "ohm * meter", "HIGH")
registry.add_las_map("SGR", "GAPI", "gAPI", "HIGH")
registry.add_las_map("SP", "MV", "millivolt", "HIGH")
registry.add_las_map("MSFL", "OHMM", "ohm * meter", "HIGH")
registry.add_las_map("NPHI", "PU", PU)
registry.add_las_map("NPHI", "PU%", "pu", "HIGH")
registry.add_las_map("PEF", "", percent_general)
registry.add_las_map("POTA", "", percent_general)
registry.add_las_map("THOR", "", percent_general)
registry.add_las_map("URAN", "", percent_general)
Loading
Loading