Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError 0 is not a string (plotting well imported from welly-generated LAS) #126

Closed
awgeo opened this issue Apr 17, 2020 · 7 comments
Closed

Comments

@awgeo
Copy link

awgeo commented Apr 17, 2020

Problem:
When trying to plot a well, imported from a Welly-generated .LAS file, I get "TypeError 0 is not a string" which is raised against "axes[0].set_ylim([lower, upper])".

Follow the steps below to import > export > import the LAS file.
LAS file (from the Volve data set) and full error message attached.

Welly bug report.zip

To reproduce:
w = Well.from_las('STAT1990__30-1__15-9-19_SR__COMPOSITE__1.LAS')
w.plot()
w.to_las('out.las')
z = Well.from_las('out.las')
z.plot()

Expected:
Welly can plot the original LAS file, so should be expected to plot after running .to_las() then .from_las().

@dcslagel
Copy link
Contributor

dcslagel commented May 8, 2020

Triage findings:

The break occurs between v0.4.1 and v0.4.2.

It looks like the error is triggered by the following change in welly/fields.py
from
'td': ('params', 'TDD'),
to
'td': ('params', 'TD'),

This seems to be revealing the problem rather than triggering the problem:

  • If a las-file has a TD entry with value of None likeTD . None : , then when a las-file (out.las) is read in with Well.from_las('out.las') a self.location.td value is created as the string 'None' (Not a python None type!) and used if the code goes to well.py line 595 elif extends == 'td':. Thus incorrectly setting lower = 'None' (the string 'None' not the python None type).

  • However if TD wasn't in the las-file (out.las) then when the out.las is read in with Well.from_las('out.las'), self.location.td is created with the python None value: <class 'NoneType'> with well.py line 595 elif extents == 'td': setting lower to None causing the code-flow to go into the is not lower: code and setting lower with lower = basis[-1] which then seems to work.

At the level of Lasio.read() a las file containing TD . None : will create a las.param['TD'].value with the string 'None'

Some possible solutions are:

  • Change Well.from_las() to translate TD . None : to self.location.td = None (the python None class type)
  • Change Lasio.read() to do the same
  • There are probably other options too

DC

@dcslagel
Copy link
Contributor

work around

Using the built-in funcs parameter we can work around this issue.
The following code will run without the type error.

w = Well.from_las('STAT1990__30-1__15-9-19_SR__COMPOSITE__1.LAS')
w.plot()
w.to_las('out.las')

# Add transform function(s) -----------------
def str_none_to_none(value):
    if value == 'None':
        return None

transform_functions = {
    'TD': str_none_to_none,
}
# z = Well.from_las('out.las')
z = Well.from_las('myout.las', funcs=transform_functions)
# -------------------------------------------
z.plot()

@kinverarity1
Copy link
Contributor

Would the underlying problem here be that lasio/welly is writing the python object None to out.las as the string 'None'? I haven't tested this, just genuinely curious. If so we should fix that.

@dcslagel
Copy link
Contributor

Thats a good point!

I'll look at that today. Step one it to see whether the internal value is the same between Lasio and Welly just before writing. Also it will be useful to see if there is a difference between Lasio and Welly about what gets written. If it is a fundamental read/write issue, then design-wise it would be nice to handle it in Lasio.

There is also a question of whether this should be kept specific to the 'TD' mnemonic, or be configurable for a set of mnemonics, or be handled in a general way.

It does feel like Lasio and Welly should each have a match of their original las object data after a cycle of read(las), write(new.las), read(new.las).

@dcslagel
Copy link
Contributor

dcslagel commented Jul 28, 2020

Yes, Lasio is writing the python None object to the string 'None' when writing to a file. If we write nothing, lasio.read(...) will interpret that as a empty string "". That would be more correct than 'None' because an empty string is a more common and standard object than a 'None' string. Potentially lasio.read() could be changed to transform all HeaderItem empty string values to NoneType objects. That seems to make sense. However, it could have an impact on current apps that use Lasio. I'll make Lasio Issue to continue this..

@dcslagel
Copy link
Contributor

dcslagel commented Jul 28, 2020

Related Lasio Issue:
kinverarity1/lasio#377

Related Laisio Pull-Request (Merged to master 2c5b7ba)
kinverarity1/lasio#378

@kwinkunks
Copy link
Member

I believe this is fixed in lasio now, so I'm closing it here. Thanks DC and Alan! (And Kent of course!)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants