Skip to content

Commit

Permalink
Move the net_force tool from EnSight to PyEnSight (#353)
Browse files Browse the repository at this point in the history
  • Loading branch information
mariostieriansys authored Mar 7, 2024
1 parent 82709c6 commit d03902b
Show file tree
Hide file tree
Showing 5 changed files with 2,196 additions and 17 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ classifiers = [

dependencies = [
"importlib-metadata>=4.0; python_version<='3.8'",
"ansys-api-pyensight==0.3.4",
"ansys-api-pyensight==0.3.6",
"requests>=2.28.2",
"docker>=6.1.0",
"urllib3<2",
Expand Down
57 changes: 44 additions & 13 deletions src/ansys/pyensight/core/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -1203,7 +1203,11 @@ def load_data(
raise RuntimeError("Unable to load the dataset.")

def download_pyansys_example(
self, filename: str, directory: Optional[str] = None, root: Optional[str] = None
self,
filename: str,
directory: Optional[str] = None,
root: Optional[str] = None,
folder: Optional[bool] = None,
) -> str:
"""Download an example dataset from the ansys/example-data repository.
The dataset is downloaded local to the EnSight server location, so that it can
Expand All @@ -1217,11 +1221,16 @@ def download_pyansys_example(
The directory to download the filename from
root: str
If set, the download will happen from another location
folder: bool
If set to True, it marks the filename to be a directory rather
than a single file
Returns
-------
pathname: str
The download location, local to the EnSight server directory
The download location, local to the EnSight server directory.
If folder is set to True, the download location will be a folder containing
all the items available in the repository location under that folder.
Examples
--------
Expand All @@ -1234,21 +1243,43 @@ def download_pyansys_example(
>>> remote.browser()
"""
base_uri = "https://github.com/ansys/example-data/raw/master"
if root is not None:
base_uri = root
base_api_uri = "https://api.github.com/repos/ansys/example-data/contents"
if not folder:
if root is not None:
base_uri = root
else:
base_uri = base_api_uri
uri = f"{base_uri}/{filename}"
if directory:
uri = f"{base_uri}/{directory}/{filename}"
pathname = f"{self.launcher.session_directory}/{filename}"
script = "import requests\n"
script += "import shutil\n"
script += "import os\n"
script += f'url = "{uri}"\n'
script += f'outpath = r"""{pathname}"""\n'
script += "with requests.get(url, stream=True) as r:\n"
script += " with open(outpath, 'wb') as f:\n"
script += " shutil.copyfileobj(r.raw, f)\n"
self.cmd(script, do_eval=False)
if not folder:
script = "import requests\n"
script += "import shutil\n"
script += "import os\n"
script += f'url = "{uri}"\n'
script += f'outpath = r"""{pathname}"""\n'
script += "with requests.get(url, stream=True) as r:\n"
script += " with open(outpath, 'wb') as f:\n"
script += " shutil.copyfileobj(r.raw, f)\n"
self.cmd(script, do_eval=False)
else:
script = "import requests\n"
script += "import shutil\n"
script += "import os\n"
script += f'url = "{uri}"\n'
script += "with requests.get(url) as r:\n"
script += " data = r.json()\n"
script += f' output_directory = r"""{pathname}"""\n'
script += " os.makedirs(output_directory, exist_ok=True)\n"
script += " for item in data:\n"
script += " if item['type'] == 'file':\n"
script += " file_url = item['download_url']\n"
script += " filename = os.path.join(output_directory, item['name'])\n"
script += " r = requests.get(file_url, stream=True)\n"
script += " with open(filename, 'wb') as f:\n"
script += " f.write(r.content)\n"
self.cmd(script, do_eval=False)
return pathname

def load_example(
Expand Down
144 changes: 141 additions & 3 deletions src/ansys/pyensight/core/utils/parts.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,14 @@ def convert_part(

def convert_variable(
_ensight: Union["ensight_api.ensight", "ensight"], var: Union[str, int, "ENS_VAR"]
):
) -> Optional[int]:
if isinstance(var, str):
return _ensight.objs.core.VARIABLES[var][0].ID
return int(_ensight.objs.core.VARIABLES[var][0].ID)
elif isinstance(var, int):
return var
elif hasattr(var, "ID"):
return var.ID
return int(var.ID)
return None


class Parts:
Expand Down Expand Up @@ -1043,3 +1044,140 @@ def add_emitter_parts_to_particle_trace_part(
num_points=num_points,
)
return self._add_emitters_to_particle_trace_part(particle_trace_part, new_emitters)

def select_parts(
self,
p_list: Optional[List[Union[str, int, "ENS_PART"]]] = None,
rec_flag: Optional[bool] = True,
) -> Optional[List["ENS_PART"]]:
"""
Select the parts string, or int, or ensight.objs.ENS_PART, or list
and record the selection (by default) honoring the
EnSight preference to record command language by part id or by name.
It creates a list of part objects and selects the parts, and records the
selection by default.
Parameters
----------
p_list: list
The list of part objects to compute the forces on. It can either be a list of names
a list of IDs (integers or strings) or directly a list of ENS_PART objects
rec_flag: bool
True if the selection needs to be recorded
Returns
-------
list
list of part objects selected or None if error.
NOTE: If you do not want a measured part in your
selection, then don't include it in the list
e.g. if
core.PARTS[0].PARTTYPE == ensight.objs.enums.PART_DISCRETE_PARTICLE == 3
then it is a measured part
"""
#
pobj_list = self.get_part_id_obj_name(p_list, "obj")

if not pobj_list:
raise RuntimeError("Error, select_parts: part list is empty")
else:
# This was formerly used to record command lang 10.1.6(c)
# using part ids:
# ensight.part.select_begin(pid_list,record=1)
# Now records selection, honoring the the preference
# part selection of by part id or by name (2024R1)
record = 1 if rec_flag else 0
self.ensight.objs.core.selection(name="ENS_PART").addchild(
pobj_list, replace=1, record=record
)
# This is essential to synchronize cmd lang with the GUI, C++
self.ensight.part.get_mainpartlist_select()

return pobj_list

def get_part_id_obj_name(
self,
plist: Optional[Union[str, int, "ENS_PART", List[str], List[int], List["ENS_PART"]]] = None,
ret_flag="id",
) -> Union[Optional[List[int]], Optional[List[str]], Optional[List["ENS_PART"]]]:
"""
input a part or a list of parts and return an id, object, or name
or a list of ids, objects, or names.
Parameters
----------
p_list: list
The list of part objects to compute the forces on. It can either be a list of names
a list of IDs (integers or strings) or directly a list of ENS_PART objects
ret_flag: string
a string that determines what is returned
Returns
-------
list
either a list of part IDs, or a list of names or a list of ENS_PART objects
depending on the requested ret_flag value
"""
# To not change the interface I didn't move ret_flag to be a required argument,
# so I need to check its value now
if not ret_flag:
return None
if not plist:
plist = [p for p in self.ensight.objs.core.PARTS]
pobj_list: List["ENS_PART"] = []
#
# Basically figure out what plist is, then convert it to a list of ENS_PARTs
#
if (
isinstance(plist, self.ensight.objs.ENS_PART)
or isinstance(plist, int)
or isinstance(plist, str)
):
p_list = [plist]
elif isinstance(plist, list) or isinstance(plist, ensobjlist):
p_list = [p for p in plist]
else:
raise RuntimeError("Unknown type of input var plist {}".format(type(plist)))
#
# p_list must now be a list
#

if not p_list:
return None
if not isinstance(p_list[0], (str, int, self.ensight.objs.ENS_PART)):
error = "First member is neither ENS_PART, int, nor string"
error += f"{p_list[0]} type = {type(p_list[0])}; aborting"
raise RuntimeError(error)
pobjs: List["ENS_PART"]
if isinstance(p_list[0], int): # list of ints must be part ids
for pid in p_list:
pobjs = [p for p in self.ensight.objs.core.PARTS if p.PARTNUMBER == pid]
for prt in pobjs:
pobj_list.append(prt)
elif isinstance(p_list[0], str):
if not p_list[0].isdigit():
for pname in p_list:
pobjs = [p for p in self.ensight.objs.core.PARTS if p.DESCRIPTION == pname]
for prt in pobjs:
pobj_list.append(prt)
else: # digits, must be a string list of part ids?
for pid_str in p_list:
pobjs = [
p for p in self.ensight.objs.core.PARTS if p.PARTNUMBER == int(pid_str)
]
for prt in pobjs:
pobj_list.append(prt)
else:
for prt in p_list:
pobj_list.append(prt)
if ret_flag == "name":
val_strings = [str(p.DESCRIPTION) for p in pobj_list]
return val_strings
if ret_flag == "obj":
val_objs = [p for p in pobj_list]
return val_objs
val_ints = [int(p.ID) for p in pobj_list]
return val_ints
Loading

0 comments on commit d03902b

Please sign in to comment.