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

Composite Log Display #169

Open
Pinkmei opened this issue Oct 2, 2021 · 14 comments
Open

Composite Log Display #169

Pinkmei opened this issue Oct 2, 2021 · 14 comments

Comments

@Pinkmei
Copy link

Pinkmei commented Oct 2, 2021

Thank you very much for sharing the comprehensive geoscience python codes. I wonder if it is possible to display GR, Density, Sonic in linear scale, RT (resistivity in log scale) and Vsh calculated from logs with shadings together in a composite log in python. Any update and reply would be much appreciated. Thank you in advance.

The display sample is similar to the linked plot https://www.researchgate.net/profile/Guochang_Wang/publication/301912413/figure/download/fig5/AS:669075327967234@1536531397331/Conventional-well-logs-and-computed-organic-richness-of-the-Utica-Point-Pleasant-interval.ppm

@Pinkmei
Copy link
Author

Pinkmei commented Oct 2, 2021

image

Please be aware, As the plot link seems not working, try to paste the image here for your reference. copyright of the image belongs to the original author as address above.

@Zabamund
Copy link
Collaborator

Zabamund commented Oct 3, 2021

Hello @Pinkmei and thank you for your interest and question.
I have written some code that allows me to make a comp log that can look like the attached figure:
comp_log_example
I made PR #153 not so long ago but it was not accepted as it didn't match Welly's API, I am still planning to update my code to include such functionality in future.
You are welcome to use the code in that PR if you like, although of course it's not optimized and future such comp logs in welly will likely have a different API.

To break down how I'd written that code:

  • the function initially takes in a Well object
  • a tracklist can be passed to select which curves to plot
  • a depth interval can be specified to display only that depth range
  • a curve_kwargs dict was the guts of the display and while large and rather heavy, it allowed for changing labels, units, colors, lims, ticks, scale, and choose a fill function (which I'd also written to allow the different fill types you see here).
    One thing I was hoping to do in a future PR is to have some set defaults, for example Triple Combo for clastics or standard Carbonate logs.

If you would like to take this code and refactor it to make a PR, one thing that was pointed out to me was that the plotting should be attached to a Curve object, and not the Well object.

I have not yet figured out a nice way to achieve this.

I hope while this is not a solution right now, it can perhaps give you a starting point.

@Pinkmei
Copy link
Author

Pinkmei commented Oct 5, 2021

Hi, Zabamund (Rob),

Thank you so much for sharing your nice work and comprehensive codes and explanation. I really like to try them but I encountered the following two problems when practice.

  1. I have tried to incorporate the log_utils.py by adding it to the welly folder and updated well.py to plot the graph that you demonstrate above. When running the program, it gave me that ModuleNotFoundError: 'welly.log_utils' was not found, see attachment 1 for your reference.
    log_utils_error
    Not sure how to fix it... Then I had to work around adding your functions like fill_between_curves, fill_const_to_curve, fill_curve_vals_to_curve directly in the program. They worked well.

  2. However When run _=w.com_log(tracklist=tracklist, depth_range=(8000,8500), curve_kwargs=curve_kwargs) , I got AttributeError, as shown in the attachment 2. I double-checked well.py, the comp_log() function was in it. Don't know what I am missing and how to fix it.
    comp_log_error

Would you please help me or share your smart solution to fix the problems? Thank you very much in advance.

@Zabamund
Copy link
Collaborator

Zabamund commented Oct 5, 2021

If you would like to use the code from the PR #153 , you can check all the files I changed here: https://github.com/agile-geoscience/welly/pull/153/files
you'll see that I added the comp_log function to the Well object, you're likely getting that AttributeError if you didn't use that updated file.
So you could either just clone the repo from PR #153 or fork welly and add those same changes to your copy, but once again beware that these changes did not fit the Welly API and are really just me hacking away to try to make a nice comp log.

@Pinkmei
Copy link
Author

Pinkmei commented Oct 5, 2021

Hi @Zabamund

Cool, Thank you very much for the guide. I add all functions to the program and it turns out a nice view. I have learned a lot from this practice and will keep on...
Nice_Composite_LogView

Best Regards and Have a nice day,

@Zabamund
Copy link
Collaborator

Zabamund commented Oct 5, 2021

That's great, really happy to have been of assistance. If you're not a member yet I'd suggest you join the software underground community as there are loads of people of love rocks and computers!
you can find it here: https://swu.ng/slack

@Pinkmei
Copy link
Author

Pinkmei commented Oct 13, 2021

Hi @Zabamund,

Thank you. I wonder how to set the cutoffs to the calculated curve in welly. For instance, using your sample well to calculate VSH and limit it within 0,1.

def vsh(gr,grmin,grmax): vsh = max(min((gr-grmin)/(grmax-grmin),1),0) return vsh
gr = w.data['GRD'] w.data['VSH'] = vsh(gr,15,110)

I used the above code trying to estimate VSH, however, it gives me a Value Error
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Don't know how to solve it. Is there an efficient solution to fix it especially for curve objects? Thank you in advance.

@Zabamund
Copy link
Collaborator

Hi @Pinkmei,

the issue you're having is not related to welly but rather to your use of np.arrays, you might solve it using np.nanmin() and np.nanmax() functions to handle the nan values in your array, but then it seems your vsh function simply returns a single value, and not an array.
When you do w.data['VSH'] I think you're trying to add a new Curve object, but here you only have one value.

So for example if you do this:

def vsh(gr,grmin,grmax):
    vsh = max(min((np.nanmin(gr.values)-grmin)/(grmax-grmin),1),0)
    return vsh

and then:

gr = w.data['GRD']
w.data['VSH'] = vsh(gr,15,110)

you get back 0 for w.data['VSH']

I'm not sure if this is what you want, but you could do something like this:

image

def vsh_lgi(gr, gr_clean, gr_shale):
    """Calculate VSH linear index (IGR).
    Function:
        $ IGR = \frac{GR_{LogSignal} - GR_{CleanRock}}{GR_{Shale} - GR_{CleanRock}} $
    Args:
        gr: (np.array), GR log curve
        gr_clean: (float), clean gamma ray cutoff
        gr_shale: (float), shale cutoff
    Returns:
        igr: (np.array), calculated VSH linear
    """
    return (gr - gr_clean) / (gr_shale - gr_clean)

and then:

gr_clean, gr_shale = 110, 15
w.data['VSH'] = vsh_lgi(gr, gr_clean=gr_clean, gr_shale=gr_shale)
w.data['VSH']

image

@Pinkmei
Copy link
Author

Pinkmei commented Oct 14, 2021

Hi @Zabamund,

Thank you for the prompt explanation and well-decripted code for vsh_lgi estimation. Yes, I got vsh calculated like your vsh_lgi as a curve before using any constraints. As I am unfamiliar with Curve objects in python. I have 3 questions in calculating properties from curves.

  1. How would we constrain vsh_lgi within the range of 0 and 1 given some spikes beyond clean sand and shales?

  2. How to remove/trim "nan" data in curve objects?

  3. How would we generate a new Curve (Array data) when using a conditional if-else statement for curve objects.

Thank you in advance.

@Zabamund
Copy link
Collaborator

Zabamund commented Oct 14, 2021

Hey @Pinkmei,

  1. There might be a way to do this with welly.Curve.despike but otherwise you can do it with numpy (here's just one way to do it):
def vsh_lgi(gr, gr_clean, gr_shale, norm=False):
    """Calculate VSH linear index (IGR).
    Function:
        $ IGR = \frac{GR_{LogSignal} - GR_{CleanRock}}{GR_{Shale} - GR_{CleanRock}} $
    Args:
        gr: (np.array), GR log curve
        gr_clean: (float), clean gamma ray cutoff
        gr_shale: (float), shale cutoff
    Returns:
        igr: (np.array), calculated VSH linear
    """
    vsh_lgi = (gr - gr_clean) / (gr_shale - gr_clean)
    if norm:
        vsh_lgi = np.where(vsh_lgi < 0, 0, vsh_lgi)
        vsh_lgi = np.where(vsh_lgi > 1, 1, vsh_lgi)
        vsh_lgi = welly.Curve(vsh_lgi)
    return vsh_lgi

and then:

gr_clean, gr_shale = 110, 15
w.data['VSH'] = vsh_lgi(gr, gr_clean=gr_clean, gr_shale=gr_shale, norm=True)
w.data['VSH_clean'] = w.data['VSH'][~np.isnan(w.data['VSH'])]
assert np.isnan(w.data['VSH_clean'].values).any() == False
  1. To trim the nans you can do this, as I used just above:
w.data['GRD_clean'] = w.data['GRD'][~np.isnan(w.data['GRD'])]
  1. I show a way to do this in the function in 1. by using np.where and then recreating a welly.Curve object.

Please bear in mind, these are all just hacky solutions and there may be a more elegant way to achieve this in welly itself.

I hope this is of assistance.

@Pinkmei
Copy link
Author

Pinkmei commented Oct 19, 2021

Hi @Zabamund,

Looks cool. Thank you for the wonderful solution. I will give it a try.

Best Regards,

@Zabamund
Copy link
Collaborator

In fact rather than using np.where twice as I did, you could use np.clip https://numpy.org/doc/stable/reference/generated/numpy.clip.html

@ThomasMGeo
Copy link
Contributor

Thanks @Zabamund , this is going to save me a ton of time. Let me know if I can help/test/spitball on next steps for this. Would love this to be an option for welly.

@Zabamund
Copy link
Collaborator

Hey @ThomasMGeo, if you mean my plotting code, you're most welcome, but I'm not sure it's going to keep working with the changes coming to welly, also it was never merged as it didn't match welly's API, so my hope is that such functionality will be developed in a future version of welly as I think that being able to make such plots would be an awesome new feature.

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

3 participants