wellio

Wellio.js is a JavaScript library for converting a LAS 2.0 well log file into a wellio style JSON.

Reason for Existing:

Why would you want to do this? You can think of both LAS 2.0 and JSON as file formats that hold strings. The difference is JSON is a very common data format widely used across a variety of computer languages. It is used extensively on the web to hold data. LAS 2.0 is not. LAS 2.0 is specifically for well logs. Well logs are measurements along a well bore that meausure changes in subsurface properties. By converting LAS 2.0 to JSON, we get data into a format that is much easier to work with on the web. Wellio's companion library wellioviz takes the JSON that results from Wellio and visualizes it by leveraging D3.js v5. However, you could visualize the same wellio JSON with a wide variety of other visualization tools too, because nearly all of them can consume JSON.

https://github.com/JustinGOSSES/wellio.js

The README.md has additional information to the README, including sections:

  • Demos
  • Contributing
  • Contributors
  • Road Map
  • Wellio.js & Wellioviz.js
  • Where To Get Open-Source Well Logs in .LAS format?
  • Example of LAS format and JSON formated well log data

Usage

In the wellio documentation, we have split out "How to Install & Get Ready to Use" and "How to Use Once Installed", because installation varies depending on whether wellio is being used as front-end JavaScript code on a website, in an Observable JavaScript Notebook, or server-side via a command line or node.js script.

Once installed and ready to use, however, how to use wellio is identical no matter where used.

How to Install

Wellio.js is packaged as npm module as seen here. The code that you pull when you install the npm module is found in the dist folder of the wellio repository on GitHub.

It can be run from the back-end or front-end. Frontend being from a webpage running HTML, CSS, and JavaScript. Backend meaning on a server or in your terminal. Most people will probably be interested in running it on the frontend, but we'll start by explaining how to run it on the backend or server side as that's a bit easier to explain.

Server-side

  1. If you haven't already, install node.js and npm. Node.js is server-side JavaScript. NPM is the package manager for node.js.

When you install Node.js, you should also get npm as described here. 2. Navigate in your terminal to where you want to work. 3. To install wellio run:

npm install wellio

  1. Move a LAS 2.0 well log file into the same directory if not already there.
  2. Enter node, but typing in the termianl

node

  1. Once in command line node environment, to start with wellio, you'll have to run

wellio = require('wellio')

  1. At this point we can now jump to how to use wellio as described in the HOW TO USE ONCE INSTALLED section.

Observable Notebooks

The process for installing wellio in an Observable notebook is very easy as it is a npm module. It is literally as easy as:

wellio = require(wellio)

As seen in the example notebook here. Once wellio is imported using require, you can call any wellio function like:

well_as_wellio_style_json_in_memory = wellio.las2json(las_file_read_in_as_string)

Front-end side

Due to wellio being a npm module, we'll need to use require to pull it into front-end code. Require can be confusing and I've not found their documentation to be super clear. That's less a problem of documentation as it is that there's multiple ways for npm modules to work and therefore differences in how require can end up working, which gets confusing.

I'll try to explain one way to bring in wellio that is used to make the demo page that lives as a github pages page in the main wellio repository.

The demo page that lets you try out wellio.js is here.

The code for that demo page is at the top level of the wellio repository as seen here. Go have a look.

If you look at code that makes up the index.html page that builds the demo page, you'll see in the header section that multiple CSS and JS libraries are pulled into index.html.

There 3 we care about the most for explaining how to pull wellio into the front-end demo page are:

1. <script src="https://requirejs.org/docs/release/2.3.5/minified/require.js"></script>

This imports the requirejs JavaScript library that we'll use to import the wellio npm module into our code such that we can call it.

2. <script src="./dist/index.js"></script>

This pulls in the JavaScript at that location. It is a relative location, meaning relative to the index.html page that calls it and makes up the demo. It is the same code that makes up wellio and is sent to the npm (node package manager).

If you're not working with the demo page that is in the same folder location as the main wellio code, there's a couple other ways to go. If you're familar with node modules, you probably already know how to work with them and aren't reading this demo. If you're confused, you can simply use an absolute url rather than a relative one. For example, <script src="https://raw.githubusercontent.com/JustinGOSSES/wellio.js/master/dist/index.js"></script> will pull in the code you need from the current master branch of wellio.

3. <script src="./js/main.js"></script>

Main.js is the JavaScript file that pulls in wellio and uses it in the demo page. If you look at the code, you'll see starting on line 13...

wellio = require(['./dist/index.js'],function(wellio_obj){console.log("wellio test",wellio) wellio = wellio_obj})

This is where require pulls in wellio and makes a wellio object to call all the wellio functions as described in the "How to Use Once Installed" section.

Other files that help make the demo page worth mentioning are...

  • CSS files are in the CSS folder.
  • Several example well logs are in the ASSETS folder.
  • G3.js is used to draw a plot of the well log curves. It leverages d3.js but version 2. There is some functionality that makes it much easier to draw vertical curves in d3.js v5, which led to the creation of wellioviz after an initial effort to develop on G3.
  • VKbeautify.js is a script for adding spaces and such to JSON to make them prettier when printed.
  • run_prettify.js does something similar but is focused on making it print nicely into HTML DOM elements.

How to Use Once Installed

No matter how you use wellio, you'll eventually get to the point where you'll start using it in your code by bringin it in via require, like this:

wellio = require('wellio')

Now we have wellio installed and imported, so it is ready for use. We can load a well log saved as a .las file with:

file_loaded_as_string = wellio.loadLAS("path_to_file")

We can convert that string into wellio style JSON in memory with:

wellio_style_json = wellio.las2json(file_loaded_as_string)

We can now use the wellio_style_json object that is in memory! Getting to this point is the main reason for wellio.

We can manipulate it with other JavaScript code or use wellioviz to visualize it. The wellioviz README has several links to various tutorials and demos for how to use wellioviz.

Other Things You Might Want to Do with Wellio

Saving the JSON as a file

We can also save it to as a JSON file to our local computer, which follows the commands below. You'll have to stringify it first and then write it to a file. In this case, the resulting JSON file is named "UWI_of_Well.json".s

well_json_string = JSON.stringify(well_json)

fs.writeFile("UWI_of_Well.json", well_json_string, 'utf8', function (err) {console.log("error")})

The help and returnThing functions

These are mostly in wellio for easy ways to test if it was installed and imported successfully. They don't require any inputs to work. They can simply be called.

wellio.help()

wellio.returnThing("This is a test string that should be returned exactly as shown")

Getting specific pieces of information out of the wellio-style JSON

Although getting information out of the wellio-style JSON is as straight forward as navigating a python dict, there are a few helper functions built-in. Clicking on each will bring you to the documenation for that function.

  • wellio.CurveNames() will return all the curve names in a wellio-style JSON.
  • wellio.VER_block() will return version information that was in the original LAS file now in the wellio-style JSON.
  • wellio.UWI() wellio.UWI will return the UWI if it exists. If you use this, wrap it in a function that fails as you intend it to.
  • wellio.getCurve() will return all the curve data for a given curve name in a wellio-style JSON.

Working with well logs in JSONs other than wellio-style JSON

These two functions are for converting Lasio-style JSON to wellio-style JSON. They are defined in the "functions section". Clicking on them will take you directly to their documentation. Why they exist is explained in the section directly below.

wellio.read_lasio_json_file

and

wellio.lasio_obj_2_wellio_obj.

Wellio-style JSON vs Others

As mentioned above in the upper most section, JSON is a format for storing data. It is based on keys and values and can store a huge variety of different types of data and informaion.

As such, it shouldn't be surprising that there is more than one way to store well log data that was originally in LAS 2.0 file format in JSON format. As of writing this, there are 3 that the author knows about.

  • wellio-style JSON
  • lasio-style JSON
  • json-style JSON

JSON-style JSON

If you're confused about what's a json-style JSON, that's okay. I'll try to explain. Another group, not involved with wellio, made an attempt at a standardized way to store well log data in JSON. They named it "JSON Well Log Format". This causes confusion as you start talking about JSON JSON and whether wellio JSON is compliant with JSON JSON.

At the time of writing, there are not any functions to convert between the json-style JSON and wellio-style JSON. However, that could be added in the future.

Lasio-style JSON

To quote from their docs, "lasio is a Python 3 package to read and write Log ASCII Standard (LAS) files, used for borehole data such as geophysical, geological, or petrophysical logs. It’s compatible with versions 1.2 and 2.0 of the LAS file specification, published by the Canadian Well Logging Society. In principle it is designed to read as many types of LAS files as possible, including ones containing s common errors or non-compliant formatting."

Lasio is the most common way to read well logs in Python. Sometimes it is used directly and other times people use welly, which wraps Lasio and provides a Pandas-like interface. Lasio has the ability to export data loaded from a LAS 2.0 well log file into JSON format and save it as a JSON file.

There are two functions in wellio for converting these lasio-style JSON files into wellio-style JSON.

A sequence of using them to load a lasio-style JSON file and convert it into wellio-style JSON is below:

let wellio = require('wellio')

let lasio_json_str = wellio.read_lasio_json_file('lasio.json');

let lasio_obj = JSON.parse(lasio_json_str);

let wellio_obj = wellio.lasio_obj_2_wellio_obj(lasio_obj);

What a Wellio-Style JSON Looks Like:

To give you an idea what the wellio-style JSON structure is like, here's a blank well log in the wellio-style JSON format.

How to Edit Documentation

  • Make changes to documentation in the index.js file.
  • Alternatively, make change to the documentation.yml file in the docs folder.
  • Go to the top level folder.
  • If documentation.js is not already installed, check out the instructions on http://documentation.js.org/.
  • run: documentation build -c docs/documentation.yml dist/* -f html -o docs
  • run: cp css/style.css docs/assets/. This is an extra step to overwrite the default styling of documentation.js to code elements show up a little more.
  • Now CD to docs folder.
  • Run python3 -m http.server. Alternatively, you could use any local server tooling.
  • You should be able to go to your browser at http://0.0.0.0:8000/ and see the docs.
  • Go to docs/assets/style.css and under the code element around line 91 add the lines color: rgb(0, 6, 35);background-color: rgb(227, 230, 239);. This will provide some styling to the code lines.

How to Make Contributions to Wellio.js

  • Clone the repository locally by running in a terminal git clone https://github.com/JustinGOSSES/wellio.js.git
  • Change into the directory you just cloned by running cd wellio.js.
  • Run npm install to install all the node module dependencies. You may want to check what version of node.js you're running first. I know I often end up thinking I'm running latest version but I'm not. NVM or node version manager is good for that.
  • Create a new branch for your work git checkout -b YourDevelopmentBranchName
  • Make changes to the code.
  • Use tests described below to run tests after changes.
  • If tests all past, then commit those changes by running git add * then git commit -m "message here".
  • Push changes to remote git push origin main, then go to GitHub and start a pull request.

Tests

  • There are test functions used for testing wellio used in the dist/test/ folder.
  • They should all run when you are in the top directory and run npm run test.

Functions

help

A helper function that takes no input arugments and returns a string with some basic information about wellio.

help(): string
Returns
string: A predetermined string message to the user about wellio.
Example
wellio.help() >>> Wellio has the following functions: 'help',
'returnThing', 'loadLAS', 'las2json', 'read_lasio_json_file', and 'lasio_obj_2_wellio_obj'.
You'll probably want to do well_string = wellio.loadLAS and then
well_as_json = las2json(well_string)."

returnThing

A helper function that proves wellio,js was installed correctly. It merely returns the argument provided to it. For example, "test" as input would return "test".

returnThing(aTestString: string): string
Parameters
aTestString (string) Any string
Returns
string: Returns the input that was given as an argument. This is just for testing that wellio was installed correctly.
Example
wellio.returnThing("test") >>> "test"

loadLAS

Loads a LAS 2.0 file from local files. Takes one argument wellLog and returns a string representation of the contents of the well log file.

loadLAS(wellLog: string): string
Parameters
wellLog (string) A string reprepresentatiion of filename of well log to be loaded into memory
Returns
string: A string representation of the contents of that well log file. It is a single string.

las2json

las2json function converts a LAS 2.0 file already loaded into memory as a string into a wellio-style JSON object

las2json(onelas: string, print: boolean): Object
Parameters
onelas (string) A string representation of a LAS 2.0 well log file. Typically from the result of the loadLAS function.
print (boolean = true) A true or false boolean. If true, intermediate products are sent to console.warn() to help withe debugging.
Returns
Object: A JSON object that represents the information that was in the LAS 2.0 well log file but in JSON wellio style format.

CurveNames

Given a well already converted into wellio-style json in memory, the CurveNames function returns the available curves in that well.

CurveNames(well_json: object): Array
Parameters
well_json (object) A wellio-style json in memory, typically resulting from the wellio.las2json() function.
Returns
Array: An array of strings representing the curve names in the well.

VER_block

Given a well already converted into wellio-style json in memory, the VER_block function returns the entire version block of the original LAS file as a string.

VER_block(well_json: object): string
Parameters
well_json (object) A wellio-style json in memory, typically resulting from the wellio.las2json() function.
Returns
string: An array of strings representing the entire version block of the original LAS file as a string.

UWI

Given a well already converted into wellio-style json in memory, the UWI function attempts to return the UWI field of the original LAS file as a string. Pleaes note that this doesn't exist in every well log and will therefore fail sometimes!

UWI(well_json: object): string
Parameters
well_json (object) A wellio-style json in memory, typically resulting from the wellio.las2json() function.
Returns
string: An a string representing the UWI field of the original LAS file.

getCurve

Given a well already converted into wellio-style json in memory, the wellio.getCurve() function attempts to return the curve data of a given well log. If it doesn't exist, the message "that curve does not exist! see console.warn" is outputted to console.warn and returned by the function.

getCurve(well_json: object, curve: string): array
Parameters
well_json (object) A wellio-style json in memory, typically resulting from the wellio.las2json() function.
curve (string) A string representation of a particular curve name.
Returns
array: An array of integers or floats representing the data for a particular curve in a given well log.

read_lasio_json_file

File reading utility function for a JSON file that contains what was a LAS 2.0 well log already converted into JSON by the Python package Lasio. Lasio is also used by Welly. This function will read the file and keep it in memory. After running this function, You'll likely want to use the lasio_obj_2_wellio_obj function to convert the lasio-style JSON in memory to wellio-style JSON in memory.

read_lasio_json_file(file_to_read: string): string
Parameters
file_to_read (string) : file_to_read - The file to open.s
Returns
string: : The file's contents as a string.

lasio_obj_2_wellio_obj

The lasio_obj_2_wellio_obj function transforms lasio-style JSON strings into wellio-style JSON data format in memory and returns it. If you're working with a JSON file created by lasio, you'll want to load it into memory first using the read_lasio_json_file function.

lasio_obj_2_wellio_obj(lasio_obj: any, lasio_json: object): object
Parameters
lasio_obj (any)
lasio_json (object) A JavaScript object representation of lasio well log format
Returns
object: A wellio style JSON object
Example
This is an example of a full sequence of calls that also uses this function.
let wellio = require('wellio')
let lasio_json_str = wellio.read_lasio_json_file('lasio.json');
let lasio_obj = JSON.parse(lasio_json_str);
let wellio_obj = wellio.lasio_obj_2_wellio_obj(lasio_obj);