jeng


Namejeng JSON
Version 1.0.0 PyPI version JSON
download
home_pagehttps://github.com/nazebzurati/jeng
SummaryA simple WITSML client with utilities.
upload_time2023-07-16 06:42:12
maintainer
docs_urlNone
authorNazeb Zurati
requires_python
licenseMIT
keywords python witsml soap-client pandas
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Jeng

A simple WITSML client with utilities.

[![PyPI version](https://badge.fury.io/py/jeng.svg?kill_cache=1)](https://badge.fury.io/py/jeng) [![Unit test](https://github.com/nazebzurati/jeng/actions/workflows/unit-test.yml/badge.svg)](https://github.com/nazebzurati/jeng/actions/workflows/unit-test.yml)

If you encounter any issues, please report them promptly [here](https://github.com/nazebzurati/jeng/issues). Additionally, feel free to request any necessary features [here](https://github.com/nazebzurati/jeng/issues).

## Installation

```
pip install jeng
```

## Getting started

- Jeng should be compatible with Python 3.8 and higher.
- Jeng should work with WITSML data schema v1.3.1.1 and v1.4.1.1.
- Jeng should work the same for both TIME log type and DEPTH log type.
  - Log curve info list is not technically required for TIME log type. For DEPTH log type, the index log curve info is required. Thus, log curve info is set to required for `generate.generate_log_query()` to ensure the API stays consistent and not confusing.
- Incompatible package version update:
  - `0.0.6` to `0.0.7`: Change from `jeng.client.WitsmlClient` package to `jeng.jeng.WitsmlClient`

### Client

1. To create and connect to WITSML Server:

   ```python
   from jeng import jeng

   client = jeng.WitsmlClient()

   # return True if success, else False
   status = client.connect(
       url=CONNECTION_URL,
       username=CONNECTION_USERNAME,
       password=CONNECTION_PASSWORD,
   )
   ```

2. To call wrapper API (make sure to connect to WTISML Server first):

   ```python
   # send query to WMLS_AddToStore API
   with open(f"{QUERY_PATH}/query.xml", "r") as query:
       reply = client.add_to_store(
           wml_type_in="well",
           xml_in=query.read(),
       )

   # send query to WMLS_UpdateInStore API
   with open(f"{QUERY_PATH}/query.xml", "r") as query:
       reply = client.update_in_store(
           wml_type_in="well",
           xml_in=query.read(),
       )

   # send query to WMLS_GetFromStore API
   with open(f"{QUERY_PATH}/query.xml", "r") as query:
       reply = client.get_from_store(
           wml_type_in="well",
           xml_in=query.read(),
           return_element="all",
       )

   # send query to WMLS_DeleteFromStore API
   with open(f"{QUERY_PATH}/query.xml", "r") as query:
       reply = client.delete_from_store(
           wml_type_in="well",
           xml_in=query.read(),
       )

   # string is expected for xml_in and you can
   # pass string query to all the wrapper API
   client.add_to_store(
       wml_type_in="well",
       xml_in=query_xml_str,
   )
   ```

3. To call other WITSML APIs than provided wrapper APIs (make sure to connect to WTISML Server first):
   ```python
   # send WMLS_GetVersion directly from Jeng client service
   reply = client.service().WMLS_GetVersion()
   ```

### Log Query Generator

```python
from jeng import model, generate

# set log basic info
log_basic_info = model.LogBasicInfoModel(
    well_uid="WELL_001",
    well_name="WELL 001",
    wellbore_uid="WELLBORE_001",
    wellbore_name="WELLBORE 001",
    log_uid="LOG_001",
    log_name="LOG 001",
)

# set time log curve info
log_curve_info_list = [
    model.LogCurveInfoModel(
        uid="TIME",
        mnemonic="TIME",
        unit="s",
        curve_description="Time",
        type_log_data="date time",
        index_type="date time",
        is_index_curve=True,
    ),
    model.LogCurveInfoModel(
        uid="HKLA",
        mnemonic="HKLA",
        unit="klbf",
        curve_description="Average Hookload",
        type_log_data="double",
    ),
    ...
]

# set depth log curve info
log_curve_info_list = [
    model.LogCurveInfoModel(
        uid="DEPTH",
        mnemonic="DEPTH",
        unit="m",
        curve_description="Depth Index",
        type_log_data="double",
        index_type="measured depth",
        is_index_curve=True,
    ),
    model.LogCurveInfoModel(
        uid="HKLA",
        mnemonic="HKLA",
        unit="klbf",
        curve_description="Average Hookload",
        type_log_data="double",
    ),
    ...
]

...
# generate very basic query (log curve info list is optional)
query_xml = generate.generate_log_query(
    log_basic_info=log_basic_info,
)

# generate query (make sure to use mnemonic as column name)
query_xml = generate.generate_log_query(
    log_basic_info=log_basic_info,
    log_curve_info_list=log_curve_info_time_list,
    dataframe=dataframe,
)

# it's possible to generate WMLS_GetFromStore compatible
# query with specific time interval
query_xml = generate.generate_log_query(
    log_basic_info=log_basic_info,
    log_curve_info_list=log_curve_info_time_list,
    log_index=model.LogIndexModel(
        start="2020-06-30T17:44:00.000+08:00",
        end="2020-06-30T17:45:00.000+08:00",
    ),
)

# it's possible to generate WMLS_GetFromStore compatible
# query with specific non-time interval
query_xml = generate.generate_log_query(
    log_basic_info=log_basic_info,
    log_curve_info_list=log_curve_info_depth_list,
    log_index=model.LogIndexModel(
        start="2575.2",
        end="2575.5",
        type=model.LogIndexTypeEnum.NON_TIME,
    ),
)
```

### Log Reply Parser

```python
from jeng import parse

...

# parse WITSML XMLout reply data into dataframe
dataframe = parse.parse_log_into_dataframe(
    xml_out=reply["XMLout"],
)

# parse WITSML XMLout reply into model.LogCurveInfoModel
log_curve_info_list = parse.parse_log_into_curve_info(
    xml_out=reply["XMLout"],
)
```

## Test

Make sure to have a WITSML server running for the test.

1. Clone the project:

   ```bash
   git clone https://github.com/nazebzurati/jeng.git
   ```

2. Prepare environment:

   ```bash
   # create environment and activate
   virtualenv env
   .\env\Scripts\activate       # on Windows
   source .\env\bin\activate    # on Mac and Linux

   # install development dependencies
   pip install -e .[dev]        # bash
   pip install -e .\[dev\]      # zsh
   ```

3. Change the source code and test.

   ```bash
   # formatting
   isort . --skip env && black --line-length 120 .

   # run coverage and pytest
   coverage run -m pytest -v
   coverage run -m pytest -m integration -v    # test with WITSML server integration
   coverage run -m pytest -m unit -v           # test without WITSML server integration

   # run static code test
   coverage xml && sonar-scanner.bat -D"sonar.projectKey=<project-key>" -D"sonar.sources=." -D"sonar.host.url=<host-url>" -D"sonar.login=<project-token>"
   ```

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/nazebzurati/jeng",
    "name": "jeng",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "python,witsml,soap-client,pandas",
    "author": "Nazeb Zurati",
    "author_email": "nazeb04@gmail.com",
    "download_url": "",
    "platform": null,
    "description": "# Jeng\n\nA simple WITSML client with utilities.\n\n[![PyPI version](https://badge.fury.io/py/jeng.svg?kill_cache=1)](https://badge.fury.io/py/jeng) [![Unit test](https://github.com/nazebzurati/jeng/actions/workflows/unit-test.yml/badge.svg)](https://github.com/nazebzurati/jeng/actions/workflows/unit-test.yml)\n\nIf you encounter any issues, please report them promptly [here](https://github.com/nazebzurati/jeng/issues). Additionally, feel free to request any necessary features [here](https://github.com/nazebzurati/jeng/issues).\n\n## Installation\n\n```\npip install jeng\n```\n\n## Getting started\n\n- Jeng should be compatible with Python 3.8 and higher.\n- Jeng should work with WITSML data schema v1.3.1.1 and v1.4.1.1.\n- Jeng should work the same for both TIME log type and DEPTH log type.\n  - Log curve info list is not technically required for TIME log type. For DEPTH log type, the index log curve info is required. Thus, log curve info is set to required for `generate.generate_log_query()` to ensure the API stays consistent and not confusing.\n- Incompatible package version update:\n  - `0.0.6` to `0.0.7`: Change from `jeng.client.WitsmlClient` package to `jeng.jeng.WitsmlClient`\n\n### Client\n\n1. To create and connect to WITSML Server:\n\n   ```python\n   from jeng import jeng\n\n   client = jeng.WitsmlClient()\n\n   # return True if success, else False\n   status = client.connect(\n       url=CONNECTION_URL,\n       username=CONNECTION_USERNAME,\n       password=CONNECTION_PASSWORD,\n   )\n   ```\n\n2. To call wrapper API (make sure to connect to WTISML Server first):\n\n   ```python\n   # send query to WMLS_AddToStore API\n   with open(f\"{QUERY_PATH}/query.xml\", \"r\") as query:\n       reply = client.add_to_store(\n           wml_type_in=\"well\",\n           xml_in=query.read(),\n       )\n\n   # send query to WMLS_UpdateInStore API\n   with open(f\"{QUERY_PATH}/query.xml\", \"r\") as query:\n       reply = client.update_in_store(\n           wml_type_in=\"well\",\n           xml_in=query.read(),\n       )\n\n   # send query to WMLS_GetFromStore API\n   with open(f\"{QUERY_PATH}/query.xml\", \"r\") as query:\n       reply = client.get_from_store(\n           wml_type_in=\"well\",\n           xml_in=query.read(),\n           return_element=\"all\",\n       )\n\n   # send query to WMLS_DeleteFromStore API\n   with open(f\"{QUERY_PATH}/query.xml\", \"r\") as query:\n       reply = client.delete_from_store(\n           wml_type_in=\"well\",\n           xml_in=query.read(),\n       )\n\n   # string is expected for xml_in and you can\n   # pass string query to all the wrapper API\n   client.add_to_store(\n       wml_type_in=\"well\",\n       xml_in=query_xml_str,\n   )\n   ```\n\n3. To call other WITSML APIs than provided wrapper APIs (make sure to connect to WTISML Server first):\n   ```python\n   # send WMLS_GetVersion directly from Jeng client service\n   reply = client.service().WMLS_GetVersion()\n   ```\n\n### Log Query Generator\n\n```python\nfrom jeng import model, generate\n\n# set log basic info\nlog_basic_info = model.LogBasicInfoModel(\n    well_uid=\"WELL_001\",\n    well_name=\"WELL 001\",\n    wellbore_uid=\"WELLBORE_001\",\n    wellbore_name=\"WELLBORE 001\",\n    log_uid=\"LOG_001\",\n    log_name=\"LOG 001\",\n)\n\n# set time log curve info\nlog_curve_info_list = [\n    model.LogCurveInfoModel(\n        uid=\"TIME\",\n        mnemonic=\"TIME\",\n        unit=\"s\",\n        curve_description=\"Time\",\n        type_log_data=\"date time\",\n        index_type=\"date time\",\n        is_index_curve=True,\n    ),\n    model.LogCurveInfoModel(\n        uid=\"HKLA\",\n        mnemonic=\"HKLA\",\n        unit=\"klbf\",\n        curve_description=\"Average Hookload\",\n        type_log_data=\"double\",\n    ),\n    ...\n]\n\n# set depth log curve info\nlog_curve_info_list = [\n    model.LogCurveInfoModel(\n        uid=\"DEPTH\",\n        mnemonic=\"DEPTH\",\n        unit=\"m\",\n        curve_description=\"Depth Index\",\n        type_log_data=\"double\",\n        index_type=\"measured depth\",\n        is_index_curve=True,\n    ),\n    model.LogCurveInfoModel(\n        uid=\"HKLA\",\n        mnemonic=\"HKLA\",\n        unit=\"klbf\",\n        curve_description=\"Average Hookload\",\n        type_log_data=\"double\",\n    ),\n    ...\n]\n\n...\n# generate very basic query (log curve info list is optional)\nquery_xml = generate.generate_log_query(\n    log_basic_info=log_basic_info,\n)\n\n# generate query (make sure to use mnemonic as column name)\nquery_xml = generate.generate_log_query(\n    log_basic_info=log_basic_info,\n    log_curve_info_list=log_curve_info_time_list,\n    dataframe=dataframe,\n)\n\n# it's possible to generate WMLS_GetFromStore compatible\n# query with specific time interval\nquery_xml = generate.generate_log_query(\n    log_basic_info=log_basic_info,\n    log_curve_info_list=log_curve_info_time_list,\n    log_index=model.LogIndexModel(\n        start=\"2020-06-30T17:44:00.000+08:00\",\n        end=\"2020-06-30T17:45:00.000+08:00\",\n    ),\n)\n\n# it's possible to generate WMLS_GetFromStore compatible\n# query with specific non-time interval\nquery_xml = generate.generate_log_query(\n    log_basic_info=log_basic_info,\n    log_curve_info_list=log_curve_info_depth_list,\n    log_index=model.LogIndexModel(\n        start=\"2575.2\",\n        end=\"2575.5\",\n        type=model.LogIndexTypeEnum.NON_TIME,\n    ),\n)\n```\n\n### Log Reply Parser\n\n```python\nfrom jeng import parse\n\n...\n\n# parse WITSML XMLout reply data into dataframe\ndataframe = parse.parse_log_into_dataframe(\n    xml_out=reply[\"XMLout\"],\n)\n\n# parse WITSML XMLout reply into model.LogCurveInfoModel\nlog_curve_info_list = parse.parse_log_into_curve_info(\n    xml_out=reply[\"XMLout\"],\n)\n```\n\n## Test\n\nMake sure to have a WITSML server running for the test.\n\n1. Clone the project:\n\n   ```bash\n   git clone https://github.com/nazebzurati/jeng.git\n   ```\n\n2. Prepare environment:\n\n   ```bash\n   # create environment and activate\n   virtualenv env\n   .\\env\\Scripts\\activate       # on Windows\n   source .\\env\\bin\\activate    # on Mac and Linux\n\n   # install development dependencies\n   pip install -e .[dev]        # bash\n   pip install -e .\\[dev\\]      # zsh\n   ```\n\n3. Change the source code and test.\n\n   ```bash\n   # formatting\n   isort . --skip env && black --line-length 120 .\n\n   # run coverage and pytest\n   coverage run -m pytest -v\n   coverage run -m pytest -m integration -v    # test with WITSML server integration\n   coverage run -m pytest -m unit -v           # test without WITSML server integration\n\n   # run static code test\n   coverage xml && sonar-scanner.bat -D\"sonar.projectKey=<project-key>\" -D\"sonar.sources=.\" -D\"sonar.host.url=<host-url>\" -D\"sonar.login=<project-token>\"\n   ```\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A simple WITSML client with utilities.",
    "version": "1.0.0",
    "project_urls": {
        "Homepage": "https://github.com/nazebzurati/jeng"
    },
    "split_keywords": [
        "python",
        "witsml",
        "soap-client",
        "pandas"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "06d0efd0a6e15c793ad5ff6df91d691df77caa02ea53319eb771befc67a0addf",
                "md5": "e8a5e077d2a67727a19a2bbbaf409b92",
                "sha256": "1ce905f9e3212e3cd6257dbea627c37d9b6f5ffaa265987af55a5ed36a654553"
            },
            "downloads": -1,
            "filename": "jeng-1.0.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "e8a5e077d2a67727a19a2bbbaf409b92",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 10985,
            "upload_time": "2023-07-16T06:42:12",
            "upload_time_iso_8601": "2023-07-16T06:42:12.767611Z",
            "url": "https://files.pythonhosted.org/packages/06/d0/efd0a6e15c793ad5ff6df91d691df77caa02ea53319eb771befc67a0addf/jeng-1.0.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-07-16 06:42:12",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "nazebzurati",
    "github_project": "jeng",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "jeng"
}
        
Elapsed time: 0.17801s