log2frame 0.2.2__tar.gz → 0.2.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. {log2frame-0.2.2/src/log2frame.egg-info → log2frame-0.2.4}/PKG-INFO +7 -1
  2. {log2frame-0.2.2 → log2frame-0.2.4}/README.md +6 -0
  3. {log2frame-0.2.2 → log2frame-0.2.4}/pyproject.toml +1 -1
  4. {log2frame-0.2.2 → log2frame-0.2.4}/src/log2frame/__init__.py +77 -9
  5. log2frame-0.2.4/src/log2frame/dictionaries/units.py +69 -0
  6. {log2frame-0.2.2 → log2frame-0.2.4}/src/log2frame/dlis.py +16 -12
  7. {log2frame-0.2.2 → log2frame-0.2.4}/src/log2frame/las.py +13 -10
  8. {log2frame-0.2.2 → log2frame-0.2.4}/src/log2frame/lis.py +69 -10
  9. {log2frame-0.2.2 → log2frame-0.2.4}/src/log2frame/log.py +151 -5
  10. {log2frame-0.2.2 → log2frame-0.2.4}/src/log2frame/pack.py +218 -7
  11. {log2frame-0.2.2 → log2frame-0.2.4}/src/log2frame/rft.py +146 -2
  12. log2frame-0.2.4/src/log2frame/writer.py +192 -0
  13. {log2frame-0.2.2 → log2frame-0.2.4/src/log2frame.egg-info}/PKG-INFO +7 -1
  14. {log2frame-0.2.2 → log2frame-0.2.4}/src/log2frame.egg-info/SOURCES.txt +3 -2
  15. {log2frame-0.2.2 → log2frame-0.2.4}/test/test_readers.py +1 -2
  16. log2frame-0.2.4/test/test_writer.py +215 -0
  17. log2frame-0.2.2/src/log2frame/debug.py +0 -5
  18. log2frame-0.2.2/src/log2frame/dictionaries/units.py +0 -37
  19. {log2frame-0.2.2 → log2frame-0.2.4}/LICENSE +0 -0
  20. {log2frame-0.2.2 → log2frame-0.2.4}/setup.cfg +0 -0
  21. {log2frame-0.2.2 → log2frame-0.2.4}/src/log2frame/dictionaries/__init__.py +0 -0
  22. {log2frame-0.2.2 → log2frame-0.2.4}/src/log2frame/dictionaries/units_dictionary.json +0 -0
  23. {log2frame-0.2.2 → log2frame-0.2.4}/src/log2frame.egg-info/dependency_links.txt +0 -0
  24. {log2frame-0.2.2 → log2frame-0.2.4}/src/log2frame.egg-info/requires.txt +0 -0
  25. {log2frame-0.2.2 → log2frame-0.2.4}/src/log2frame.egg-info/top_level.txt +0 -0
  26. {log2frame-0.2.2 → log2frame-0.2.4}/test/test_log.py +0 -0
  27. {log2frame-0.2.2 → log2frame-0.2.4}/test/test_pack.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: log2frame
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: A function to facilitate loading well log data, in las or dlis format, as dataframe.
5
5
  Author-email: Martin Carlos Araya <martinaraya@gmail.com>
6
6
  License: MIT License
@@ -63,6 +63,12 @@ When `simpandas` is installed, `log2frame` can preserve curve units and index un
63
63
  # to read log files
64
64
  Simply call the function `read()` with the path or path pattern as argument:
65
65
 
66
+ # to export / write LAS files
67
+ Use `write_las()` to export a `Log` back to a LAS file:
68
+ - `log2frame.write_las( log, path_to_file )` — writes LAS 2.0 by default
69
+ - `log2frame.write_las( log, path_to_file, version=1.2 )` — LAS 1.2
70
+ - `log.to_las( path_to_file )` — equivalent convenience method on `Log`
71
+
66
72
  ## a single log file
67
73
  To load a single _.las_, _.lis_ or _.dlis_ file. The function will return a `Log` instance containing the data:
68
74
  - `log2frame.read( path_to_file )`
@@ -16,6 +16,12 @@ When `simpandas` is installed, `log2frame` can preserve curve units and index un
16
16
  # to read log files
17
17
  Simply call the function `read()` with the path or path pattern as argument:
18
18
 
19
+ # to export / write LAS files
20
+ Use `write_las()` to export a `Log` back to a LAS file:
21
+ - `log2frame.write_las( log, path_to_file )` — writes LAS 2.0 by default
22
+ - `log2frame.write_las( log, path_to_file, version=1.2 )` — LAS 1.2
23
+ - `log.to_las( path_to_file )` — equivalent convenience method on `Log`
24
+
19
25
  ## a single log file
20
26
  To load a single _.las_, _.lis_ or _.dlis_ file. The function will return a `Log` instance containing the data:
21
27
  - `log2frame.read( path_to_file )`
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "log2frame"
7
- version = "0.2.2"
7
+ version = "0.2.4"
8
8
  authors = [
9
9
  { name="Martin Carlos Araya", email="martinaraya@gmail.com" },
10
10
  ]
@@ -1,14 +1,29 @@
1
1
  # -*- coding: utf-8 -*-
2
- """
3
- Created on Thu Jan 19 19:01:21 2023
2
+ """log2frame — well-log data reader and writer.
3
+
4
+ This package reads well-log files in LAS, DLIS, and LIS formats and
5
+ returns the curve data as unit-aware :class:`Log` (single file) or
6
+ :class:`Pack` (multiple files) containers built on top of
7
+ :class:`pandas.DataFrame` (or :class:`simpandas.SimDataFrame` when the
8
+ optional ``simpandas`` package is installed).
4
9
 
5
- @author: Martín Carlos Araya <martinaraya@gmail.com>
10
+ The package also provides :func:`write_las` to export any :class:`Log`
11
+ back to a LAS 1.2 / 2.0 file.
12
+
13
+ Public API
14
+ ----------
15
+ read(path, ...) Read one or many log files.
16
+ write_las(log, path) Write a Log to a LAS file.
17
+ concat(logs) Concatenate a list of Log objects into a single DataFrame.
6
18
  """
19
+ # Created on Thu Jan 19 19:01:21 2023
20
+ # @author: Martín Carlos Araya <martinaraya@gmail.com>
7
21
  from .las import las2frame
8
22
  from .dlis import dlis2frame
9
23
  from .lis import lis2frame
10
24
  from .pack import Pack, concat
11
25
  from .log import Log
26
+ from .writer import write_las
12
27
  import glob
13
28
  import os.path
14
29
  import logging
@@ -17,12 +32,26 @@ from .rft import *
17
32
  for name in ("lasio", "lasio.reader", "lasio.las", "unyts"):
18
33
  logging.getLogger(name).setLevel(logging.WARNING)
19
34
 
20
- __version__ = '0.2.2'
21
- __release__ = 20260427
22
- __all__ = ['read', 'concat']
35
+ __version__ = '0.2.4'
36
+ __release__ = 20261015
37
+ __all__ = ['read', 'concat', 'write_las']
23
38
 
24
39
 
25
40
  class _Log2FrameParams(object):
41
+ """Package-level singleton holding runtime configuration flags.
42
+
43
+ Attributes
44
+ ----------
45
+ simpandas_ : bool
46
+ ``True`` when the optional ``simpandas`` package is importable.
47
+ Used by all readers to decide whether to return a
48
+ :class:`simpandas.SimDataFrame` or a plain
49
+ :class:`pandas.DataFrame`.
50
+ raise_error_ : bool
51
+ Default value for the *raise_error* parameter of :func:`read`.
52
+ Set to ``True`` to propagate parse errors; ``False`` silently
53
+ skips unreadable files.
54
+ """
26
55
  def __init__(self):
27
56
  try:
28
57
  import simpandas as spd
@@ -36,6 +65,23 @@ _params_ = _Log2FrameParams()
36
65
 
37
66
 
38
67
  def _read_one(path: str, raise_error=True, use_simpandas=None, correct_units=True):
68
+ """Dispatch a single file path to the appropriate format reader.
69
+
70
+ Parameters
71
+ ----------
72
+ path : str
73
+ Path to a ``.las``, ``.dlis``, or ``.lis`` / ``.lti`` file.
74
+ raise_error : bool, default True
75
+ Whether to propagate parse errors or return ``None``.
76
+ use_simpandas : bool | None, default None
77
+ Passed through to the format-specific reader.
78
+ correct_units : bool, default True
79
+ Passed through to the format-specific reader.
80
+
81
+ Returns
82
+ -------
83
+ Log | None
84
+ """
39
85
  if use_simpandas is not None and use_simpandas is True and not _params_.simpandas_:
40
86
  raise ModuleNotFoundError("SimPandas is not installed, please install it or set parameter `use_simpandas` to False.")
41
87
  use_simpandas = _params_.simpandas_ if use_simpandas is None else bool(use_simpandas)
@@ -66,14 +112,36 @@ def read(path: str, recursive=True, raise_error=False, squeeze=True, use_simpand
66
112
  Parameters
67
113
  ----------
68
114
  path : str | list[str]
69
- Path to the ``.las``, ``.dlis``, or ``.lis`` file(s). Glob expressions and directory paths are supported.
115
+ Path to the ``.las``, ``.dlis``, or ``.lis`` file(s). Glob
116
+ expressions (``**/*.*``) and bare directory paths are supported.
70
117
  recursive : bool, default True
71
- If reading a path pattern with globs, controls whether directories are searched recursively.
118
+ Whether ``**`` glob patterns recurse into subdirectories.
72
119
  squeeze : bool, default True
73
- If True and only one log is inside a resulting pack, return that single Log object instead of the Pack.
120
+ Return a single :class:`Log` directly when the result would be a
121
+ one-entry :class:`Pack`.
74
122
  use_simpandas : bool | None, default None
123
+ Use :class:`simpandas.SimDataFrame` for curve storage when
124
+ ``True``; plain :class:`pandas.DataFrame` when ``False``;
125
+ auto-detect when ``None`` (default).
75
126
  raise_error : bool, default False
127
+ Raise exceptions for unreadable files. When ``False`` (default)
128
+ unreadable files are silently skipped.
76
129
  correct_units : bool, default True
130
+ Normalise unit strings using the built-in correction dictionary
131
+ (e.g. ``GAPI`` → ``gAPI``).
132
+
133
+ Returns
134
+ -------
135
+ Log | Pack
136
+ A :class:`Log` if a single file was resolved; a :class:`Pack`
137
+ otherwise (unless *squeeze* collapses a one-entry Pack).
138
+
139
+ Examples
140
+ --------
141
+ >>> import log2frame
142
+ >>> log = log2frame.read('well.las')
143
+ >>> pack = log2frame.read('data/**/*.las')
144
+ >>> log = log2frame.read(['run1.las', 'run2.las'], squeeze=False)
77
145
  """
78
146
  if use_simpandas is not None and use_simpandas is True and not _params_.simpandas_:
79
147
  raise ModuleNotFoundError("SimPandas is not installed, please install it or set parameter `use_simpandas` to False.")
@@ -0,0 +1,69 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Unit-name correction mapping for LAS/DLIS/LIS mnemonics.
3
+
4
+ Loads ``units_dictionary.json`` (stored alongside this file) and
5
+ exposes :func:`correct_units` to normalise non-standard unit strings to
6
+ their canonical forms (e.g. ``'GAPI'`` → ``'gAPI'``,
7
+ ``'OHMM'`` → ``'ohm.m'``).
8
+
9
+ Module-level attributes
10
+ -----------------------
11
+ units_correction_dict_ : dict
12
+ The raw ``{non_canonical: canonical}`` mapping loaded from the JSON
13
+ dictionary. An empty dict is used as a safe fallback when the file
14
+ is missing or malformed (a :class:`UserWarning` is emitted).
15
+ """
16
+
17
+ import json
18
+ from os.path import dirname
19
+ from pathlib import Path
20
+
21
+ this_path_ = Path(__file__).with_name('units_dictionary.json').absolute()
22
+ this_path_ = dirname(this_path_) + '/'
23
+
24
+ try:
25
+ with open(this_path_ + 'units_dictionary.json', 'r') as f:
26
+ units_correction_dict_ = json.load(f)
27
+ except (FileNotFoundError, json.JSONDecodeError) as e:
28
+ import warnings
29
+ warnings.warn(
30
+ f"log2frame: units-correction dictionary not found "
31
+ f"({type(e).__name__}: {e}); proceeding with unit-correction disabled.",
32
+ UserWarning,
33
+ )
34
+ units_correction_dict_ = {}
35
+
36
+
37
+ def correct_units(units):
38
+ """Normalise unit strings using the built-in correction dictionary.
39
+
40
+ Parameters
41
+ ----------
42
+ units : str | dict
43
+ A single unit string, or a ``{mnemonic: unit}`` dict whose
44
+ values are corrected. Any other type is returned unchanged.
45
+
46
+ Returns
47
+ -------
48
+ str | dict
49
+ The corrected unit string (when *units* is a ``str``) or a new
50
+ dict with corrected values (when *units* is a ``dict``). Returns
51
+ the input unchanged when *units* is neither.
52
+
53
+ Examples
54
+ --------
55
+ >>> from log2frame.dictionaries.units import correct_units
56
+ >>> correct_units('GAPI')
57
+ 'gAPI'
58
+ >>> correct_units({'GR': 'GAPI', 'RHOB': 'G/C3'})
59
+ {'GR': 'gAPI', 'RHOB': 'g/c3'}
60
+ """
61
+ if type(units) is dict:
62
+ return {k: (units_correction_dict_[u]
63
+ if u in units_correction_dict_
64
+ else u)
65
+ for k, u in units.items()}
66
+ elif type(units) is str and units in units_correction_dict_:
67
+ return units_correction_dict_[units]
68
+ else:
69
+ return units
@@ -1,8 +1,13 @@
1
1
  # -*- coding: utf-8 -*-
2
- """
3
- Created on Thu Jan 19 20:07:16 2023
2
+ """DLIS reader — parse DLIS files into :class:`Log` or :class:`Pack` containers.
3
+
4
+ This module wraps ``dlisio`` to provide curve data and metadata as
5
+ unit-aware :class:`Log` objects. When a DLIS file contains multiple
6
+ logical files or frames, a :class:`Pack` grouping all frames is returned.
4
7
 
5
- @author: Martín Carlos Araya <martinaraya@gmail.com>
8
+ Public API
9
+ ----------
10
+ dlis2frame(path, ...) Read a ``.dlis`` file.
6
11
  """
7
12
 
8
13
  import logging
@@ -19,16 +24,14 @@ try:
19
24
  except ModuleNotFoundError:
20
25
  pass
21
26
 
22
- __version__ = '0.2.2'
23
- __release__ = 20260427
27
+ __version__ = '0.2.3'
28
+ __release__ = 20260503
24
29
 
25
30
  logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO)
26
31
 
27
32
 
28
33
  class DLISIOError(Exception):
29
- """
30
- Error raised while reading LAS file.
31
- """
34
+ """Raised when ``dlisio`` fails to parse a DLIS file."""
32
35
  def __init__(self, message='raised by dlisio.'):
33
36
  self.message = 'ERROR: reading DLIS file ' + message
34
37
 
@@ -61,6 +64,7 @@ def dlis2frame(path: str, use_simpandas=None, raise_error=True, correct_units=Tr
61
64
  """
62
65
  if not os.path.isfile(path):
63
66
  raise FileNotFoundError("The provided path can't be found:\n" + str(path))
67
+ original_path = path
64
68
  if type(path) is str:
65
69
  path = path.replace('\\', '/')
66
70
 
@@ -154,10 +158,10 @@ def dlis2frame(path: str, use_simpandas=None, raise_error=True, correct_units=Tr
154
158
  data=data[0] if not use_simpandas else spd.SimDataFrame(data=data[0], units=data[2].to_dict(),
155
159
  name=data[3],
156
160
  meta=data[1],
157
- source=str(path)),
161
+ source=str(original_path)),
158
162
  header=data[1],
159
163
  units=data[2],
160
- source=str(path),
164
+ source=str(original_path),
161
165
  well=data[3]) for name, data in frames.items()}
162
166
  return frames[list(frames.keys())[0]]
163
167
  else:
@@ -167,11 +171,11 @@ def dlis2frame(path: str, use_simpandas=None, raise_error=True, correct_units=Tr
167
171
  meta=data[1],
168
172
  source='logical file ' + str(name[0]) +
169
173
  ', frame ' + str(name[1]) +
170
- ' in: ' + path),
174
+ ' in: ' + str(original_path)),
171
175
  header=data[1],
172
176
  units=data[2],
173
177
  source='logical file ' + str(name[0]) +
174
178
  ', frame ' + str(name[1]) +
175
- ' in: ' + path,
179
+ ' in: ' + str(original_path),
176
180
  well=data[3]) for name, data in frames.items()}
177
181
  return Pack(frames)
@@ -1,8 +1,12 @@
1
1
  # -*- coding: utf-8 -*-
2
- """
3
- Created on Thu Jan 19 19:02:12 2023
2
+ """LAS reader — parse LAS 1.2, 2.0, and 3.0 files into :class:`Log` containers.
3
+
4
+ This module wraps ``lasio`` to provide curve data and metadata as
5
+ unit-aware :class:`Log` objects.
4
6
 
5
- @author: Martín Carlos Araya <martinaraya@gmail.com>
7
+ Public API
8
+ ----------
9
+ las2frame(path, ...) Read a ``.las`` file.
6
10
  """
7
11
  import logging
8
12
  import lasio
@@ -18,16 +22,14 @@ try:
18
22
  except ModuleNotFoundError:
19
23
  pass
20
24
 
21
- __version__ = '0.2.2'
22
- __release__ = 20260427
25
+ __version__ = '0.2.3'
26
+ __release__ = 20260503
23
27
 
24
28
  logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO)
25
29
 
26
30
 
27
31
  class LASIOError(Exception):
28
- """
29
- Error raised while reading LAS file.
30
- """
32
+ """Raised when ``lasio`` fails to parse a LAS file."""
31
33
  def __init__(self, message='raised by lasio.'):
32
34
  self.message = 'ERROR: reading LAS file ' + message
33
35
 
@@ -68,6 +70,7 @@ def las2frame(path: str, use_simpandas=None, raise_error=True, correct_units=Tru
68
70
  """
69
71
  if not os.path.isfile(path):
70
72
  raise FileNotFoundError("The provided path can't be found:\n" + str(path))
73
+ original_path = path
71
74
  if type(path) is str:
72
75
  path = path.replace('\\', '/')
73
76
 
@@ -125,10 +128,10 @@ def las2frame(path: str, use_simpandas=None, raise_error=True, correct_units=Tru
125
128
  units=las_units,
126
129
  name=well_name,
127
130
  meta=las_header,
128
- source=path)
131
+ source=original_path)
129
132
 
130
133
  return Log(data=data,
131
134
  header=las_header,
132
135
  units=pd.Series(las_units, name='curves_units'),
133
- source=path,
136
+ source=original_path,
134
137
  well=well_name)
@@ -1,8 +1,15 @@
1
1
  # -*- coding: utf-8 -*-
2
- """
3
- Created on Thu Jan 19 20:07:16 2023
2
+ """LIS reader — parse LIS files into :class:`Log` or :class:`Pack` containers.
3
+
4
+ This module wraps ``dlisio.lis`` to provide curve data and metadata as
5
+ unit-aware :class:`Log` objects. When a LIS file contains multiple
6
+ logical files or format specs with different sample rates, each
7
+ combination is returned as a separate :class:`Log` grouped in a
8
+ :class:`Pack`.
4
9
 
5
- @author: Martín Carlos Araya <martinaraya@gmail.com>
10
+ Public API
11
+ ----------
12
+ lis2frame(path, ...) Read a ``.lis`` or ``.lti`` file.
6
13
  """
7
14
 
8
15
  import logging
@@ -18,16 +25,14 @@ try:
18
25
  except ModuleNotFoundError:
19
26
  pass
20
27
 
21
- __version__ = '0.2.2'
22
- __release__ = 20260427
28
+ __version__ = '0.2.3'
29
+ __release__ = 20260503
23
30
 
24
31
  logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO)
25
32
 
26
33
 
27
34
  class DLISIOError(Exception):
28
- """
29
- Error raised while reading LAS file.
30
- """
35
+ """Raised when ``dlisio`` fails to parse a LIS file."""
31
36
  def __init__(self, message='raised by dlisio.'):
32
37
  self.message = 'ERROR: reading LIS file ' + message
33
38
 
@@ -59,6 +64,7 @@ def lis2frame(path: str, use_simpandas=None, raise_error=True, correct_units=Tru
59
64
  """
60
65
  if not os.path.isfile(path):
61
66
  raise FileNotFoundError("The provided path can't be found:\n" + str(path))
67
+ original_path = path
62
68
  if type(path) is str:
63
69
  path = path.replace('\\', '/')
64
70
 
@@ -69,6 +75,28 @@ def lis2frame(path: str, use_simpandas=None, raise_error=True, correct_units=Tru
69
75
  raise ModuleNotFoundError("SimPandas is not installed, please install it or set parameter `use_simpandas` to False.")
70
76
 
71
77
  def _get_frame(data, l_count, i, sr):
78
+ """Return the curve data for one format spec and sample rate.
79
+
80
+ When *use_simpandas* is ``True``, wraps the raw structured array
81
+ in a :class:`simpandas.SimDataFrame` with units and index
82
+ settings applied. Otherwise returns a plain
83
+ :class:`pandas.DataFrame` with the index set to the depth column.
84
+
85
+ Parameters
86
+ ----------
87
+ data : pandas.DataFrame
88
+ Raw DataFrame produced from :func:`dlisio.lis.curves`.
89
+ l_count : int
90
+ Logical-file counter key into ``frames``.
91
+ i : int
92
+ Format-spec index within the logical file.
93
+ sr : int | float
94
+ Sample-rate key within the format spec.
95
+
96
+ Returns
97
+ -------
98
+ pandas.DataFrame | simpandas.SimDataFrame
99
+ """
72
100
  if frames[l_count][i]['index_name'] in data:
73
101
  index_name = frames[l_count][i]['index_name']
74
102
  elif len([c for c in data.columns if c.startswith(frames[l_count][i]['index_name'])]) > 0:
@@ -90,12 +118,31 @@ def lis2frame(path: str, use_simpandas=None, raise_error=True, correct_units=Tru
90
118
  if frames[l_count]['header']['name'] is not None
91
119
  and len(frames[l_count]['header']['name']) > 0 else None),
92
120
  meta=_make_header(l_count=l_count, i=i, sr=sr),
93
- source='logical file ' + str(l_count) + ', frame ' + str(i) + ', sample rate ' + str(sr) + ' in: ' + str(path))
121
+ source='logical file ' + str(l_count) + ', frame ' + str(i) + ', sample rate ' + str(sr) + ' in: ' + str(original_path))
94
122
  else:
95
123
  return data.set_index(index_name)
96
124
 
97
125
 
98
126
  def _make_header(l_count, i, sr):
127
+ """Build a merged header DataFrame for one logical file / frame / sample rate.
128
+
129
+ Concatenates curve units, wellsite data, and LIS file/reel header
130
+ into a single :class:`pandas.DataFrame` indexed by mnemonic.
131
+
132
+ Parameters
133
+ ----------
134
+ l_count : int
135
+ Logical-file index.
136
+ i : int
137
+ Format-spec index within the logical file.
138
+ sr : int | float
139
+ Sample-rate key.
140
+
141
+ Returns
142
+ -------
143
+ pandas.DataFrame
144
+ Combined header table; empty cells are replaced with ``''``.
145
+ """
99
146
  to_concat = []
100
147
  if 'curves_units' in frames[l_count][i] and sr in frames[l_count][i]['curves_units']:
101
148
  to_concat.append(pd.DataFrame(frames[l_count][i]['curves_units'][sr],
@@ -110,6 +157,18 @@ def lis2frame(path: str, use_simpandas=None, raise_error=True, correct_units=Tru
110
157
  return pd.concat(to_concat, axis=0).fillna(value='')
111
158
 
112
159
  def _try_frame(data):
160
+ """Attempt to wrap *data* in a :class:`pandas.DataFrame`.
161
+
162
+ Parameters
163
+ ----------
164
+ data : structured numpy array or similar
165
+ Raw curve data returned by :func:`dlisio.lis.curves`.
166
+
167
+ Returns
168
+ -------
169
+ pandas.DataFrame | None
170
+ ``None`` when the conversion raises any exception.
171
+ """
113
172
  try:
114
173
  return pd.DataFrame(data)
115
174
  except:
@@ -186,7 +245,7 @@ def lis2frame(path: str, use_simpandas=None, raise_error=True, correct_units=Tru
186
245
  source='logical file ' + str(l_count) +
187
246
  ', frame ' + str(i) +
188
247
  ', sample rate ' + str(sr) +
189
- ' in: ' + str(path),
248
+ ' in: ' + str(original_path),
190
249
  well=(
191
250
  frames[l_count]['header']['service_name'] if frames[l_count]['header']['service_name'] is not None and len(
192
251
  frames[l_count]['header']['service_name']) > 0 else