Skip to content

Commit

Permalink
[ENH] Added interface with Liquid Earth
Browse files Browse the repository at this point in the history
  • Loading branch information
Leguark committed May 21, 2021
1 parent 4406527 commit 8d84e90
Show file tree
Hide file tree
Showing 5 changed files with 271 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,6 @@ venv.bak/
# Spyder project settings
.spyderproject
.spyproject


.local_settings.json
Empty file.
134 changes: 134 additions & 0 deletions subsurface/interfaces/liquid_earth/rest_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import json
import uuid
from enum import Enum, auto

import requests


class DataTypes(Enum):
static_mesh = "static_mesh"
collars = "wells/collars"
cylinder = "wells/cylinders"
volumes = "volumes"


class LiquidEarthClient():
token: str
user_id: str

# Move to local settings
host = "https://apim-liquidearth.azure-api.net/"

@property
def header(self):
header_dict = {
"Authorization": f"Bearer {self.token}"
}
return header_dict

def login(self, username: str, password: str):
end_point = "user/#_b2c"

data = {
"username": username,
"password": password,
"grant_type": "password",
"client_id": "685e08c0-0aac-42f6-80a9-c57440cd2962",
"scope": "openid 685e08c0-0aac-42f6-80a9-c57440cd2962 offline_access"
}

response = requests.post(self.host + end_point, data=data)
if response.status_code == 400:
raise Exception(f"Request failed: {response.text}")
elif response.status_code == 200:
_json = response.json()
self.token = _json["access_token"]
self.user_id = username

def get_available_projects(self):
end_point = "cosmos-le/v1/available_projects/"
response = requests.get(self.host + end_point, headers=self.header)

if response.status_code >= 400:
raise Exception(f"Request failed: {response.text}")
elif response.status_code >= 200:
print(response.json())
return response.json()

def add_new_project(self, project_name, extent, project_id=None):
if project_id is None:
project_id = str(uuid.uuid4())

available_projects: list = self.get_available_projects()

for project in available_projects:
if project["project_id"] == project_id:
raise ValueError("This Project already exists")

new_project = {
"project_name": project_name,
"project_id": project_id
}
available_projects.append(new_project)
self._post_available_projects(available_projects)

new_project_meta = {
"remote_name": project_name,
"id": project_id,
"owner": self.user_id,
"extent": extent,
"static_data_address": []
}
self._post_project_meta(new_project_meta)
return project_id

def add_data_to_project(self, project_id: str, data_name: str, data_type: DataTypes,
header: json, body: bytearray):

self._post_update_meta_data(project_id, data_name, data_type)
self._put_file_in_project(project_id, data_name + ".le", data_type, body)
self._put_file_in_project(project_id, data_name + ".json", data_type, json.dumps(header))

def _put_file_in_project(self, project_id: str, data_name, data_type: DataTypes, file):
blob_path = data_type.value + "/" + data_name

end_point = f"container/{project_id}/{blob_path}"
response = requests.put(self.host + end_point, data=file, headers=self.header)

if response.status_code >= 400:
raise Exception(f"Request failed: {response.text}")
elif response.status_code >= 200:
print(response.text)

def _post_update_meta_data(self, project_id: str, data_name: str, data_type: DataTypes):

query_param = f"?project_id={project_id}&data_id={data_name}&data_type={data_type.value}"
end_point = "http://localhost:7071/api/update_project_meta" + query_param

response = requests.post(end_point)

if response.status_code >= 400:
raise Exception(f"Request failed: {response.text}")
elif response.status_code >= 200:
print(response.text)

def _post_available_projects(self, available_projects: list):
end_point = "cosmos-le/v1/available_projects/"
response = requests.post(self.host + end_point, json=available_projects,
headers=self.header)

if response.status_code >= 400:
raise Exception(f"Request failed: {response.text}")
elif response.status_code >= 200:
print("Available Projects Posted")

def _post_project_meta(self, meta_data: dict):
project_id = meta_data["id"]

end_point = f"cosmos-le/v1/project_meta/?project_id={project_id}"
response = requests.post(self.host + end_point, json=meta_data, headers=self.header)

if response.status_code >= 400:
raise Exception(f"Request failed: {response.text}")
elif response.status_code >= 200:
print("Project Metadata Posted")
9 changes: 8 additions & 1 deletion subsurface/structs/base_structures/unstructured_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ def _validate(self):
raise AttributeError('points_attributes and vertex must have the same length.')

@property
def vertex(self):
def vertex(self) -> np.ndarray:
return self.data['vertex'].values

@property
Expand Down Expand Up @@ -252,6 +252,13 @@ def attributes_to_dict(self, orient='list'):
def points_attributes_to_dict(self, orient='list'):
return self.points_attributes.to_dict(orient)

@property
def extent(self):
max = self.vertex.max(axis=0)
min = self.vertex.min(axis=0)
extent = np.stack((min, max), axis = 1).ravel()
return extent

def to_xarray(self):
a = xr.DataArray(self.vertex, dims=['points', 'XYZ'])
b = xr.DataArray(self.cells, dims=['cells', 'node'])
Expand Down
126 changes: 126 additions & 0 deletions tests/test_interfaces/test_liquid_earth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import pytest

import subsurface
from subsurface.interfaces.liquid_earth.rest_client import LiquidEarthClient, DataTypes
from subsurface.reader.read_netcdf import read_unstruct, read_struct

from subsurface.reader.mesh.surface_reader import dxf_to_mesh
import trimesh
import numpy as np
import pandas


@pytest.mark.skip(reason="This functionality is under development and it is supposed to be trigger"
"only manually.")
class TestLiquidEarthClient:

@pytest.fixture(scope="module")
def liquid_earth_client(self):
c = LiquidEarthClient()
c.login(
"yourUser", # TODO: Add your LiquidEarth Credentials here!
"yourPassword"
)
return c

def test_upload_data_to_new_project(self, liquid_earth_client, data_path):
liquid_earth_client.add_new_project(
"Shafts",
project_id="museum",
extent=[5.87907467e+05, 5.88328512e+05, 6.64175515e+06, 6.64232280e+06, -2.45600098e+02,
7.30000000e+01]
)

unstruc = self.test_dataset2(data_path)

body, header = unstruc.to_binary()

liquid_earth_client.add_data_to_project(
project_id="museum",
data_name="shafts_meshes",
data_type=DataTypes.static_mesh,
header=header,
body=body
)

def test_get_valid_token(self):
client = LiquidEarthClient()
client.login("miguel@terranigma-solutions.com", "demoaccount")

def test_get_available_projects(self, liquid_earth_client):
liquid_earth_client.get_available_projects()

def test_add_new_project(self, liquid_earth_client):
liquid_earth_client.add_new_project(
"subsurface_project",
project_id="52f88baa-c84c-4082-bbba-869ef3819004",
extent=[0, 10, -10, 0, 0, 10]
)

def test_add_data_to_project(self, liquid_earth_client, data_path):
us = read_unstruct(data_path + '/interpolator_meshes.nc')
print(us.extent)
body, header = us.to_binary()

liquid_earth_client.add_data_to_project(
project_id="52f88baa-c84c-4082-bbba-869ef3819004",
data_name="data_from_subsurface",
data_type=DataTypes.static_mesh,
header=header,
body=body
)

def test_update_meta_data(self, liquid_earth_client):
liquid_earth_client._post_update_meta_data(
project_id="52f88baa-c84c-4082-bbba-869ef3819004",
data_name="data_from_subsurface.le",
data_type=DataTypes.static_mesh
)

return

def test_dataset1(self, data_path):
us = read_unstruct(data_path + '/interpolator_meshes.nc')

def test_dataset2(self, data_path):
path = data_path + '/surfaces/shafts.dxf'

vertex, cells, cell_attr_int, cell_attr_map = dxf_to_mesh(path)

tri = trimesh.Trimesh(vertex, faces=cells)

unstruct = subsurface.UnstructuredData.from_array(
np.array(tri.vertices),
np.array(tri.faces),
cells_attr=pandas.DataFrame(cell_attr_int, columns=["Shaft id"]),
xarray_attributes={"bounds": tri.bounds.tolist(),
"cell_attr_map": cell_attr_map
},
)

print(unstruct.extent)
if True:
trisurf = subsurface.TriSurf(unstruct)
s = subsurface.visualization.to_pyvista_mesh(trisurf)
subsurface.visualization.pv_plot([s], image_2d=True)

return unstruct

def test_put_file_in_project(self, liquid_earth_client, data_path):
us = read_unstruct(data_path + '/interpolator_meshes.nc')
print(us.extent)
body, header = us.to_binary()

liquid_earth_client._put_file_in_project(
project_id="52f88baa-c84c-4082-bbba-869ef3819004",
data_name="data_from_subsurface.le",
data_type=DataTypes.static_mesh,
file=body
)

liquid_earth_client._put_file_in_project(
project_id="52f88baa-c84c-4082-bbba-869ef3819004",
data_name="data_from_subsurface.json",
data_type=DataTypes.static_mesh,
file=header
)

0 comments on commit 8d84e90

Please # to comment.