diff --git a/.gitignore b/.gitignore
index 3bfaed36..01219acf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,4 +5,4 @@ env*
*.pyc
.vscode
docs/_build/
-docs/_autosummary/
\ No newline at end of file
+docs/_autosummary/
diff --git a/LICENSE b/LICENSE
index 561977c3..e1697828 100644
--- a/LICENSE
+++ b/LICENSE
@@ -657,4 +657,4 @@ the specific requirements.
You should also get your employer (if you work as a programmer) or
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. For more information on this, and how to apply and follow
-the GNU AGPL, see .
\ No newline at end of file
+the GNU AGPL, see .
diff --git a/README.rst b/README.rst
index 43634ddb..d746ec12 100644
--- a/README.rst
+++ b/README.rst
@@ -1,26 +1,50 @@
-****
Home
-****
+========
-Open-pyFUS is a toolbox for planning and controlling focused ultrasound treatments. It generally replicates the functionality developed in the MATLAB `open-TFUS toolbox `_.
+``openlifu`` is a toolbox for planning and controlling focused
+ultrasound treatments. It generally replicates the functionality
+developed in the MATLAB `open-TFUS
+toolbox `__.
Installation
------------
Requirements
-^^^^^^^^^^^^
+~~~~~~~~~~~~
+
Python 3.11
Create Virtual Environment
-^^^^^^^^^^^^^^^^^^^^^^^^^^
-``cd open_pyfus``
-``C:\Users\\AppData\Local\Programs\Python\Python311\python.exe -m venv env``
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Windows:
+
+.. code:: sh
+
+ C:\Users\\AppData\Local\Programs\Python\Python311\python.exe -m venv env
+ .\env\Scripts\activate
+
+Linux:
+
+.. code:: sh
+
+ python3.11 -m venv env
Install project (editable)
-^^^^^^^^^^^^^^^^^^^^^^^^^^
-``.\env\Scripts\activate``
-``pip install -e .``
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+With this repo as the working directory:
+
+.. code:: sh
+
+ pip install -e .
Disclaimer
----------
-CAUTION - Investigational device. Limited by Federal (or United States) law to investigational use. The system described here has *not* been evaluated by the FDA and is not designed for the treatment or diagnosis of any disease. It is provided AS-IS, with no warranties. User assumes all liability and responsibility for identifying and mitigating risks associated with using this software.
+
+CAUTION - Investigational device. Limited by Federal (or United States)
+law to investigational use. The system described here has *not* been
+evaluated by the FDA and is not designed for the treatment or diagnosis
+of any disease. It is provided AS-IS, with no warranties. User assumes
+all liability and responsibility for identifying and mitigating risks
+associated with using this software.
diff --git a/__init__.py b/__init__.py
deleted file mode 100644
index 8132b411..00000000
--- a/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from . import pyfus
\ No newline at end of file
diff --git a/docs/_static/.gitkeep b/docs/_static/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/docs/_templates/custom-class-template.rst b/docs/_templates/custom-class-template.rst
index b8a16d85..f2905254 100644
--- a/docs/_templates/custom-class-template.rst
+++ b/docs/_templates/custom-class-template.rst
@@ -3,5 +3,5 @@
.. currentmodule:: {{ module }}
.. autoclass:: {{ objname }}
- :members:
- :show-inheritance:
\ No newline at end of file
+ :members:
+ :show-inheritance:
diff --git a/docs/_templates/custom-module-template.rst b/docs/_templates/custom-module-template.rst
index ef2c09a5..6adfe405 100644
--- a/docs/_templates/custom-module-template.rst
+++ b/docs/_templates/custom-module-template.rst
@@ -1,7 +1,7 @@
{{ fullname | escape | underline}}
.. automodule:: {{ fullname }}
-
+
{% block attributes %}
{% if attributes %}
.. rubric:: Module Attributes
@@ -63,4 +63,4 @@
{{ item }}
{%- endfor %}
{% endif %}
-{% endblock %}
\ No newline at end of file
+{% endblock %}
diff --git a/docs/api.rst b/docs/api.rst
index c5020eb8..c361f365 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -1,12 +1,11 @@
API Reference
=============
-The top-level module containing most of the code is `pyfus`
+The top-level module containing most of the code is ``openlifu``
-.. autosummary::
+.. autosummary::
:toctree: _autosummary
:template: custom-module-template.rst
:recursive:
- pyfus
-
+ openlifu
diff --git a/docs/conf.py b/docs/conf.py
index 63bfee90..5fffd216 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -6,7 +6,7 @@
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
-project = 'Open-pyFUS'
+project = 'OpenLIFU-Python'
copyright = '2023, Openwater'
author = 'Openwater'
release = '0.1'
diff --git a/docs/includeme.rst b/docs/includeme.rst
index 6b2b3ec6..72a33558 100644
--- a/docs/includeme.rst
+++ b/docs/includeme.rst
@@ -1 +1 @@
-.. include:: ../README.rst
\ No newline at end of file
+.. include:: ../README.rst
diff --git a/docs/index.rst b/docs/index.rst
index 0281f922..7032bfbd 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -1,10 +1,10 @@
-Welcome to open-PYFUS's documentation!
-=========================================
+Welcome to openlifu's documentation!
+=========================================
.. toctree::
:maxdepth: 2
:caption: Contents:
-
+
includeme
api
diff --git a/test_notebooks/foo.nii.gz b/notebooks/foo.nii.gz
similarity index 100%
rename from test_notebooks/foo.nii.gz
rename to notebooks/foo.nii.gz
diff --git a/test_notebooks/gridweights.nii.gz b/notebooks/gridweights.nii.gz
similarity index 100%
rename from test_notebooks/gridweights.nii.gz
rename to notebooks/gridweights.nii.gz
diff --git a/test_notebooks/intensity.nii.gz b/notebooks/intensity.nii.gz
similarity index 100%
rename from test_notebooks/intensity.nii.gz
rename to notebooks/intensity.nii.gz
diff --git a/test_notebooks/test_first.ipynb b/notebooks/test_first.ipynb
similarity index 88%
rename from test_notebooks/test_first.ipynb
rename to notebooks/test_first.ipynb
index f817cc55..e95e5103 100644
--- a/test_notebooks/test_first.ipynb
+++ b/notebooks/test_first.ipynb
@@ -8,7 +8,7 @@
"\n",
"If you have my modified version of k-wave-python, install it with `pip install -e .` from the `k-wave-python` directory. If you don't have my modified version, you can install the original version with `pip install k-wave-python`. If you are using the original version, be sure to set `USE_GRIDWEIGHTS` to `False` in order to prevent `open_pyfus` from trying to use a nonexistent interface for loading the gridweights. \n",
"\n",
- "Also, if you are using the original version, import `pyfus` takes _way_ longer (45s on my PC), presumably hanging on `import kwave`. For some reason, it wants to re-download the binaries every time, even though they are already present in the the installation directory. I've opened an issue on this: https://github.com/waltsims/k-wave-python/issues/366."
+ "Also, if you are using the original version, import `openlifu` takes _way_ longer (45s on my PC), presumably hanging on `import kwave`. For some reason, it wants to re-download the binaries every time, even though they are already present in the the installation directory. I've opened an issue on this: https://github.com/waltsims/k-wave-python/issues/366."
]
},
{
@@ -28,7 +28,7 @@
"formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')\n",
"handler.setFormatter(formatter)\n",
"root.addHandler(handler)\n",
- "import pyfus\n",
+ "import openlifu\n",
"import numpy as np"
]
},
@@ -55,7 +55,7 @@
"metadata": {},
"outputs": [],
"source": [
- "arr = pyfus.Transducer.gen_matrix_array(nx=8, ny=8, pitch=4, kerf=.5, units=\"mm\", impulse_response=1e5)\n",
+ "arr = openlifu.Transducer.gen_matrix_array(nx=8, ny=8, pitch=4, kerf=.5, units=\"mm\", impulse_response=1e5)\n",
"arr.draw()"
]
},
@@ -72,11 +72,11 @@
"metadata": {},
"outputs": [],
"source": [
- "pulse = pyfus.Pulse(frequency=400e3, duration=3/400e3)\n",
- "sequence = pyfus.Sequence()\n",
- "focal_pattern = pyfus.focal_patterns.Wheel(center=True, spoke_radius=5, num_spokes=5)\n",
- "sim_setup = pyfus.SimSetup(dt=2e-7, t_end=100e-6)\n",
- "protocol = pyfus.Protocol(\n",
+ "pulse = openlifu.Pulse(frequency=400e3, duration=3/400e3)\n",
+ "sequence = openlifu.Sequence()\n",
+ "focal_pattern = openlifu.focal_patterns.Wheel(center=True, spoke_radius=5, num_spokes=5)\n",
+ "sim_setup = openlifu.SimSetup(dt=2e-7, t_end=100e-6)\n",
+ "protocol = openlifu.Protocol(\n",
" pulse=pulse,\n",
" sequence=sequence,\n",
" focal_pattern=focal_pattern,\n",
@@ -96,7 +96,7 @@
"metadata": {},
"outputs": [],
"source": [
- "pt = pyfus.Point(position=(0,0,30), units=\"mm\", radius=2)\n",
+ "pt = openlifu.Point(position=(0,0,30), units=\"mm\", radius=2)\n",
"pts = protocol.focal_pattern.get_targets(pt)\n",
"coords = protocol.sim_setup.get_coords()\n",
"params = protocol.seg_method.ref_params(coords)\n",
@@ -116,7 +116,7 @@
"metadata": {},
"outputs": [],
"source": [
- "ds = pyfus.sim.run_simulation(arr=arr, \n",
+ "ds = openlifu.sim.run_simulation(arr=arr, \n",
" params=params, \n",
" delays=delays,\n",
" apod= apod,\n",
diff --git a/test_notebooks/test_gridweights.ipynb b/notebooks/test_gridweights.ipynb
similarity index 99%
rename from test_notebooks/test_gridweights.ipynb
rename to notebooks/test_gridweights.ipynb
index 516ce949..3fbe3ad3 100644
--- a/test_notebooks/test_gridweights.ipynb
+++ b/notebooks/test_gridweights.ipynb
@@ -8,7 +8,7 @@
"source": [
"import sys\n",
"sys.path.append(R'C:\\Users\\pjh7\\git\\k-wave-python')\n",
- "import pyfus\n",
+ "import openlifu\n",
"from typing import List, Dict, Any, Tuple\n",
"import logging\n",
"import matplotlib.pyplot as plt\n",
@@ -40,7 +40,7 @@
],
"source": [
"\n",
- "db = pyfus.database.Database(path=R'C:/Users/pjh7/Documents/dom/')\n",
+ "db = openlifu.database.Database(path=R'C:/Users/pjh7/Documents/dom/')\n",
"arr = db.load_transducer('vermon')\n",
"trans_matrix = np.array(\n",
" [[-1, 0, 0, 0],\n",
@@ -49,7 +49,7 @@
" [0, 0, 0, 1]])\n",
"arr.rescale(\"mm\")\n",
"arr.matrix = trans_matrix\n",
- "pt = pyfus.geo.Point(position=(5,-60,-8), units=\"mm\", radius=2)\n",
+ "pt = openlifu.geo.Point(position=(5,-60,-8), units=\"mm\", radius=2)\n",
"plan = db.load_plan('example_plan')\n",
"plan.sim_grid.dt = 2e-7\n",
"plan.sim_grid.t_end = 100e-6\n",
@@ -107,7 +107,7 @@
}
],
"source": [
- "ds, output = pyfus.sim.run_simulation(arr=arr, \n",
+ "ds, output = openlifu.sim.run_simulation(arr=arr, \n",
" params=params, \n",
" delays=delays,\n",
" apod= apod,\n",
@@ -411,12 +411,12 @@
"outputs": [],
"source": [
"\n",
- "focal_pattern = pyfus.bf.RadialPattern(center=True, spoke_radius=5, num_spokes=5)\n",
- "sim_grid = pyfus.bf.SimulationGrid(dt=2e-7, t_end=100e-6)\n",
- "pulse = pyfus.bf.Pulse(frequency=400e3, duration=3/400e3)\n",
- "sequence = pyfus.bf.Sequence()\n",
- "bfp = pyfus.bf.BeamformingPlan()\n",
- "plan = pyfus.plan.Plan(pulse=pulse,\n",
+ "focal_pattern = openlifu.bf.RadialPattern(center=True, spoke_radius=5, num_spokes=5)\n",
+ "sim_grid = openlifu.bf.SimulationGrid(dt=2e-7, t_end=100e-6)\n",
+ "pulse = openlifu.bf.Pulse(frequency=400e3, duration=3/400e3)\n",
+ "sequence = openlifu.bf.Sequence()\n",
+ "bfp = openlifu.bf.BeamformingPlan()\n",
+ "plan = openlifu.plan.Plan(pulse=pulse,\n",
" sequence=sequence,\n",
" focal_pattern=focal_pattern,\n",
" sim_grid=sim_grid,\n",
diff --git a/test_notebooks/test_nifti.ipynb b/notebooks/test_nifti.ipynb
similarity index 98%
rename from test_notebooks/test_nifti.ipynb
rename to notebooks/test_nifti.ipynb
index 589d8225..bbb69779 100644
--- a/test_notebooks/test_nifti.ipynb
+++ b/notebooks/test_nifti.ipynb
@@ -10,7 +10,7 @@
"slicer_exe = R\"C:\\Users\\pjh7\\AppData\\Local\\NA-MIC\\Slicer 5.2.2\\Slicer.exe\"\n",
"import sys\n",
"sys.path.append(modified_kwave_path)\n",
- "import pyfus\n",
+ "import openlifu\n",
"from typing import List, Dict, Any, Tuple\n",
"import logging\n",
"root = logging.getLogger()\n",
@@ -39,7 +39,7 @@
],
"source": [
"\n",
- "arr = pyfus.Transducer.gen_matrix_array(nx=8, ny=8, pitch=4, kerf=.5, units=\"mm\", impulse_response=1e5)\n",
+ "arr = openlifu.Transducer.gen_matrix_array(nx=8, ny=8, pitch=4, kerf=.5, units=\"mm\", impulse_response=1e5)\n",
"trans_matrix = np.array(\n",
" [[-1, 0, 0, 0],\n",
" [0, .05, np.sqrt(1-.05**2), -105],\n",
@@ -47,7 +47,7 @@
" [0, 0, 0, 1]])\n",
"arr.rescale(\"mm\")\n",
"arr.matrix = trans_matrix\n",
- "pt = pyfus.Point(position=(5,-60,-8), units=\"mm\", radius=2)"
+ "pt = openlifu.Point(position=(5,-60,-8), units=\"mm\", radius=2)"
]
},
{
@@ -56,11 +56,11 @@
"metadata": {},
"outputs": [],
"source": [
- "pulse = pyfus.Pulse(frequency=400e3, duration=3/400e3)\n",
- "sequence = pyfus.Sequence()\n",
- "focal_pattern = pyfus.focal_patterns.Wheel(center=True, spoke_radius=5, num_spokes=5)\n",
- "sim_setup = pyfus.SimSetup(dt=2e-7, t_end=100e-6)\n",
- "protocol = pyfus.Protocol(\n",
+ "pulse = openlifu.Pulse(frequency=400e3, duration=3/400e3)\n",
+ "sequence = openlifu.Sequence()\n",
+ "focal_pattern = openlifu.focal_patterns.Wheel(center=True, spoke_radius=5, num_spokes=5)\n",
+ "sim_setup = openlifu.SimSetup(dt=2e-7, t_end=100e-6)\n",
+ "protocol = openlifu.Protocol(\n",
" pulse=pulse,\n",
" sequence=sequence,\n",
" focal_pattern=focal_pattern,\n",
@@ -112,7 +112,7 @@
}
],
"source": [
- "ds = pyfus.sim.run_simulation(arr=arr, \n",
+ "ds = openlifu.sim.run_simulation(arr=arr, \n",
" params=params, \n",
" delays=delays,\n",
" apod= apod,\n",
diff --git a/test_notebooks/test_registers.ipynb b/notebooks/test_registers.ipynb
similarity index 99%
rename from test_notebooks/test_registers.ipynb
rename to notebooks/test_registers.ipynb
index 5e39c543..ea983a46 100644
--- a/test_notebooks/test_registers.ipynb
+++ b/notebooks/test_registers.ipynb
@@ -6,7 +6,7 @@
"metadata": {},
"outputs": [],
"source": [
- "from pyfus.io.ustx import PulseProfile, DelayProfile, TxModule, Tx7332Registers, print_regs, TxArray, swap_byte_order\n",
+ "from openlifu.io.ustx import PulseProfile, DelayProfile, TxModule, Tx7332Registers, print_regs, TxArray, swap_byte_order\n",
"import numpy as np"
]
},
diff --git a/pyfus/seg/seg_methods/tissue.py b/pyfus/seg/seg_methods/tissue.py
deleted file mode 100644
index 13f16aab..00000000
--- a/pyfus/seg/seg_methods/tissue.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from dataclasses import dataclass
-from pyfus.seg.seg_methods.seg_method import UniformSegmentation
-
-@dataclass
-class Tissue(UniformSegmentation):
- ref_material: str = "tissue"
\ No newline at end of file
diff --git a/pyfus/seg/seg_methods/water.py b/pyfus/seg/seg_methods/water.py
deleted file mode 100644
index 3c935c06..00000000
--- a/pyfus/seg/seg_methods/water.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from dataclasses import dataclass
-from pyfus.seg.seg_methods.seg_method import UniformSegmentation
-
-@dataclass
-class Water(UniformSegmentation):
- ref_material: str = "water"
\ No newline at end of file
diff --git a/pyproject.toml b/pyproject.toml
index db516893..e4821e92 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,5 +1,5 @@
[project]
-name = "open_pyfus"
+name = "openlifu"
version = "0.1.0"
description = "Openwater Focused Ultrasound Toolkit"
dependencies = [
@@ -19,7 +19,3 @@ dependencies = [
[tool.setuptools]
include-package-data = false
-
-[tool.setuptools.packages.find]
-include = ["pyfus*"]
-exclude = ["test*", "env*"]
\ No newline at end of file
diff --git a/pyfus/__init__.py b/src/openlifu/__init__.py
similarity index 62%
rename from pyfus/__init__.py
rename to src/openlifu/__init__.py
index 725a4437..aa745df0 100644
--- a/pyfus/__init__.py
+++ b/src/openlifu/__init__.py
@@ -1,27 +1,27 @@
"""
-pyFUS: Python Focused Ultrasound
+openlifu: Python Focused Ultrasound
================================
-This package contains the modules for pyFUS.
+This package contains the modules for openlifu.
"""
#from . import bf, db, io, plan, seg, sim, xdc, geo
-from pyfus.geo import (
+from openlifu.geo import (
Point
)
-from pyfus.xdc import (
+from openlifu.xdc import (
Transducer
)
-from pyfus.plan import (
+from openlifu.plan import (
Protocol,
Solution
)
-from pyfus.seg import (
+from openlifu.seg import (
Material,
SegmentationMethod,
seg_methods,
@@ -33,7 +33,7 @@
STANDOFF
)
-from pyfus.bf import (
+from openlifu.bf import (
DelayMethod,
ApodizationMethod,
Pulse,
@@ -44,10 +44,10 @@
apod_methods
)
-from pyfus.sim import (
+from openlifu.sim import (
SimSetup
)
-from pyfus.db import (
+from openlifu.db import (
Database
-)
\ No newline at end of file
+)
diff --git a/pyfus/bf/__init__.py b/src/openlifu/bf/__init__.py
similarity index 100%
rename from pyfus/bf/__init__.py
rename to src/openlifu/bf/__init__.py
diff --git a/pyfus/bf/apod_methods/__init__.py b/src/openlifu/bf/apod_methods/__init__.py
similarity index 100%
rename from pyfus/bf/apod_methods/__init__.py
rename to src/openlifu/bf/apod_methods/__init__.py
diff --git a/pyfus/bf/apod_methods/apodmethod.py b/src/openlifu/bf/apod_methods/apodmethod.py
similarity index 80%
rename from pyfus/bf/apod_methods/apodmethod.py
rename to src/openlifu/bf/apod_methods/apodmethod.py
index d46d689b..43716e74 100644
--- a/pyfus/bf/apod_methods/apodmethod.py
+++ b/src/openlifu/bf/apod_methods/apodmethod.py
@@ -1,9 +1,9 @@
from dataclasses import dataclass, field
from abc import ABC, abstractmethod
import xarray as xa
-from pyfus.xdc import Transducer
-from pyfus.geo import Point
-from pyfus.bf import apod_methods
+from openlifu.xdc import Transducer
+from openlifu.geo import Point
+from openlifu.bf import apod_methods
@dataclass
class ApodizationMethod(ABC):
@@ -15,11 +15,11 @@ def to_dict(self):
d = self.__dict__.copy()
d['class'] = self.__class__.__name__
return d
-
+
@staticmethod
def from_dict(d):
d = d.copy()
short_classname = d.pop("class")
module_dict = apod_methods.__dict__
class_constructor = module_dict[short_classname]
- return class_constructor(**d)
\ No newline at end of file
+ return class_constructor(**d)
diff --git a/pyfus/bf/apod_methods/maxangle.py b/src/openlifu/bf/apod_methods/maxangle.py
similarity index 81%
rename from pyfus/bf/apod_methods/maxangle.py
rename to src/openlifu/bf/apod_methods/maxangle.py
index 25270cfd..f5362b92 100644
--- a/pyfus/bf/apod_methods/maxangle.py
+++ b/src/openlifu/bf/apod_methods/maxangle.py
@@ -1,9 +1,9 @@
from dataclasses import dataclass
import xarray as xa
import numpy as np
-from pyfus.xdc import Transducer
-from pyfus.geo import Point
-from pyfus.bf.apod_methods import ApodizationMethod
+from openlifu.xdc import Transducer
+from openlifu.geo import Point
+from openlifu.bf.apod_methods import ApodizationMethod
@dataclass
class MaxAngle(ApodizationMethod):
@@ -15,4 +15,4 @@ def calc_apodization(self, arr: Transducer, target: Point, params: xa.Dataset, t
angles = np.array([el.angle_to_point(target_pos, units="m", matrix=matrix, return_as=self.units) for el in arr.elements])
apod = np.zeros(arr.numelements())
apod[angles <= self.max_angle] = 1
- return apod
\ No newline at end of file
+ return apod
diff --git a/pyfus/bf/apod_methods/piecewiselinear.py b/src/openlifu/bf/apod_methods/piecewiselinear.py
similarity index 83%
rename from pyfus/bf/apod_methods/piecewiselinear.py
rename to src/openlifu/bf/apod_methods/piecewiselinear.py
index 5918fbd6..f5985ed9 100644
--- a/pyfus/bf/apod_methods/piecewiselinear.py
+++ b/src/openlifu/bf/apod_methods/piecewiselinear.py
@@ -1,9 +1,9 @@
from dataclasses import dataclass
import xarray as xa
import numpy as np
-from pyfus.xdc import Transducer
-from pyfus.geo import Point
-from pyfus.bf.apod_methods import ApodizationMethod
+from openlifu.xdc import Transducer
+from openlifu.geo import Point
+from openlifu.bf.apod_methods import ApodizationMethod
@dataclass
class PiecewiseLinear(ApodizationMethod):
@@ -17,4 +17,4 @@ def calc_apodization(self, arr: Transducer, target: Point, params: xa.Dataset, t
apod = np.zeros(arr.numelements())
f = ((self.zero_angle - angles) / (self.zero_angle - self.rolloff_angle))
apod = np.maximum(0, np.minimum(1, f))
- return apod
\ No newline at end of file
+ return apod
diff --git a/pyfus/bf/apod_methods/uniform.py b/src/openlifu/bf/apod_methods/uniform.py
similarity index 57%
rename from pyfus/bf/apod_methods/uniform.py
rename to src/openlifu/bf/apod_methods/uniform.py
index c2756581..bb3b343b 100644
--- a/pyfus/bf/apod_methods/uniform.py
+++ b/src/openlifu/bf/apod_methods/uniform.py
@@ -1,12 +1,12 @@
from dataclasses import dataclass
import xarray as xa
import numpy as np
-from pyfus.xdc import Transducer
-from pyfus.geo import Point
-from pyfus.bf.apod_methods import ApodizationMethod
+from openlifu.xdc import Transducer
+from openlifu.geo import Point
+from openlifu.bf.apod_methods import ApodizationMethod
@dataclass
class Uniform(ApodizationMethod):
value = 1
def calc_apodization(self, arr: Transducer, target: Point, params: xa.Dataset, transform: bool = True):
- return np.full(arr.numelements(), self.value)
\ No newline at end of file
+ return np.full(arr.numelements(), self.value)
diff --git a/pyfus/bf/delay_methods/__init__.py b/src/openlifu/bf/delay_methods/__init__.py
similarity index 57%
rename from pyfus/bf/delay_methods/__init__.py
rename to src/openlifu/bf/delay_methods/__init__.py
index 69d2fe87..04477f3d 100644
--- a/pyfus/bf/delay_methods/__init__.py
+++ b/src/openlifu/bf/delay_methods/__init__.py
@@ -1,2 +1,2 @@
from .delaymethod import DelayMethod
-from .direct import Direct
\ No newline at end of file
+from .direct import Direct
diff --git a/pyfus/bf/delay_methods/delaymethod.py b/src/openlifu/bf/delay_methods/delaymethod.py
similarity index 80%
rename from pyfus/bf/delay_methods/delaymethod.py
rename to src/openlifu/bf/delay_methods/delaymethod.py
index 1ac94bec..486954e9 100644
--- a/pyfus/bf/delay_methods/delaymethod.py
+++ b/src/openlifu/bf/delay_methods/delaymethod.py
@@ -1,9 +1,9 @@
from dataclasses import dataclass, field
from abc import ABC, abstractmethod
import xarray as xa
-from pyfus.xdc import Transducer
-from pyfus.geo import Point
-from pyfus.bf import delay_methods
+from openlifu.xdc import Transducer
+from openlifu.geo import Point
+from openlifu.bf import delay_methods
@dataclass
class DelayMethod(ABC):
@@ -15,11 +15,11 @@ def to_dict(self):
d = self.__dict__.copy()
d['class'] = self.__class__.__name__
return d
-
+
@staticmethod
def from_dict(d):
d = d.copy()
short_classname = d.pop("class")
module_dict = delay_methods.__dict__
class_constructor = module_dict[short_classname]
- return class_constructor(**d)
\ No newline at end of file
+ return class_constructor(**d)
diff --git a/pyfus/bf/delay_methods/direct.py b/src/openlifu/bf/delay_methods/direct.py
similarity index 86%
rename from pyfus/bf/delay_methods/direct.py
rename to src/openlifu/bf/delay_methods/direct.py
index c1bc4204..7a3619d8 100644
--- a/pyfus/bf/delay_methods/direct.py
+++ b/src/openlifu/bf/delay_methods/direct.py
@@ -1,9 +1,9 @@
from dataclasses import dataclass
import xarray as xa
import numpy as np
-from pyfus.xdc import Transducer
-from pyfus.geo import Point
-from pyfus.bf.delay_methods import DelayMethod
+from openlifu.xdc import Transducer
+from openlifu.geo import Point
+from openlifu.bf.delay_methods import DelayMethod
from typing import ClassVar, Optional
@dataclass
diff --git a/pyfus/bf/focal_patterns/__init__.py b/src/openlifu/bf/focal_patterns/__init__.py
similarity index 74%
rename from pyfus/bf/focal_patterns/__init__.py
rename to src/openlifu/bf/focal_patterns/__init__.py
index e9ad037a..edb0d9a6 100644
--- a/pyfus/bf/focal_patterns/__init__.py
+++ b/src/openlifu/bf/focal_patterns/__init__.py
@@ -1,3 +1,3 @@
from .focal_pattern import FocalPattern
from .single import SinglePoint
-from .wheel import Wheel
\ No newline at end of file
+from .wheel import Wheel
diff --git a/pyfus/bf/focal_patterns/focal_pattern.py b/src/openlifu/bf/focal_patterns/focal_pattern.py
similarity index 89%
rename from pyfus/bf/focal_patterns/focal_pattern.py
rename to src/openlifu/bf/focal_patterns/focal_pattern.py
index d959149b..d712e71f 100644
--- a/pyfus/bf/focal_patterns/focal_pattern.py
+++ b/src/openlifu/bf/focal_patterns/focal_pattern.py
@@ -1,7 +1,7 @@
from abc import ABC, abstractmethod
from dataclasses import dataclass
-from pyfus.geo import Point
-from pyfus.bf import focal_patterns
+from openlifu.geo import Point
+from openlifu.bf import focal_patterns
@dataclass
class FocalPattern(ABC):
@@ -16,7 +16,7 @@ class FocalPattern(ABC):
def get_targets(self, target: Point):
"""
Get the targets of the focal pattern
-
+
:param target: Target point of the focal pattern
:returns: List of target points
"""
@@ -45,12 +45,12 @@ def to_dict(self):
def from_dict(d):
"""
Create a focal pattern from a dictionary
-
+
:param d: Dictionary of the focal pattern parameters
:returns: FocalPattern object
"""
- d = d.copy()
+ d = d.copy()
short_classname = d.pop("class")
module_dict = focal_patterns.__dict__
class_constructor = module_dict[short_classname]
- return class_constructor(**d)
\ No newline at end of file
+ return class_constructor(**d)
diff --git a/pyfus/bf/focal_patterns/single.py b/src/openlifu/bf/focal_patterns/single.py
similarity index 85%
rename from pyfus/bf/focal_patterns/single.py
rename to src/openlifu/bf/focal_patterns/single.py
index 48c4036b..e7c65eb6 100644
--- a/pyfus/bf/focal_patterns/single.py
+++ b/src/openlifu/bf/focal_patterns/single.py
@@ -1,6 +1,6 @@
from dataclasses import dataclass
-from pyfus.bf.focal_patterns import FocalPattern
-from pyfus.geo import Point
+from openlifu.bf.focal_patterns import FocalPattern
+from openlifu.geo import Point
@dataclass
class SinglePoint(FocalPattern):
@@ -12,7 +12,7 @@ class SinglePoint(FocalPattern):
def get_targets(self, target: Point):
"""
Get the targets of the focal pattern
-
+
:param target: Target point of the focal pattern
:returns: List of target points
"""
@@ -24,4 +24,4 @@ def num_foci(self):
:returns: Number of foci (1)
"""
- return 1
\ No newline at end of file
+ return 1
diff --git a/pyfus/bf/focal_patterns/wheel.py b/src/openlifu/bf/focal_patterns/wheel.py
similarity index 92%
rename from pyfus/bf/focal_patterns/wheel.py
rename to src/openlifu/bf/focal_patterns/wheel.py
index afb7cd82..d993e26f 100644
--- a/pyfus/bf/focal_patterns/wheel.py
+++ b/src/openlifu/bf/focal_patterns/wheel.py
@@ -1,6 +1,6 @@
from dataclasses import dataclass
-from pyfus.bf.focal_patterns import FocalPattern
-from pyfus.geo import Point
+from openlifu.bf.focal_patterns import FocalPattern
+from openlifu.geo import Point
import numpy as np
@dataclass
@@ -16,7 +16,7 @@ class Wheel(FocalPattern):
"""
center: bool = True
num_spokes: int = 4
- spoke_radius: float = 1.0 # mm
+ spoke_radius: float = 1.0 # mm
units: str = "mm"
def get_targets(self, target: Point):
@@ -30,7 +30,7 @@ def get_targets(self, target: Point):
targets = [target.copy()]
targets[0].id = f"{target.id}_center"
targets[0].id = f"{target.id} (Center)"
- else:
+ else:
targets = []
m = target.get_matrix(center_on_point=True)
for i in range(self.num_spokes):
@@ -44,11 +44,11 @@ def get_targets(self, target: Point):
radius=target.radius)
targets.append(spoke)
return targets
-
+
def num_foci(self):
"""
Get the number of foci in the focal pattern
-
+
:returns: Number of foci
"""
return int(self.center) + self.num_spokes
diff --git a/pyfus/bf/pulse.py b/src/openlifu/bf/pulse.py
similarity index 97%
rename from pyfus/bf/pulse.py
rename to src/openlifu/bf/pulse.py
index 04382a02..31bdd667 100644
--- a/pyfus/bf/pulse.py
+++ b/src/openlifu/bf/pulse.py
@@ -6,7 +6,7 @@
class Pulse:
"""
Class for representing a sinusoidal pulse
-
+
:ivar frequency: Frequency of the pulse in Hz
:ivar amplitude: Amplitude of the pulse in Pa
:ivar duration: Duration of the pulse in s
@@ -19,12 +19,12 @@ class Pulse:
def calc_pulse(self, t: np.array):
"""
Calculate the pulse at the given times
-
+
:param t: Array of times to calculate the pulse at (s)
:returns: Array of pulse values at the given times
"""
return self.amplitude * np.sin(2*np.pi*self.frequency*t)
-
+
def calc_time(self, dt: float):
"""
Calculate the time array for the pulse for a particular timestep
@@ -33,18 +33,18 @@ def calc_time(self, dt: float):
:returns: Array of times for the pulse (s)
"""
return np.arange(0, self.duration, dt)
-
+
def get_table(self):
"""
Get a table of the pulse parameters
-
+
:returns: Pandas DataFrame of the pulse parameters
"""
records = [{"Name": "Frequency", "Value": self.frequency, "Unit": "Hz"},
{"Name": "Amplitude", "Value": self.amplitude, "Unit": "Pa"},
{"Name": "Duration", "Value": self.duration, "Unit": "s"}]
return pd.DataFrame.from_records(records)
-
+
def to_dict(self):
"""
Convert the pulse to a dictionary
@@ -55,7 +55,7 @@ def to_dict(self):
"amplitude": self.amplitude,
"duration": self.duration,
"class": "Pulse"}
-
+
@staticmethod
def from_dict(d):
"""
@@ -65,4 +65,3 @@ def from_dict(d):
:returns: Pulse object
"""
return Pulse(frequency=d["frequency"], amplitude=d["amplitude"], duration=d["duration"])
-
\ No newline at end of file
diff --git a/pyfus/bf/sequence.py b/src/openlifu/bf/sequence.py
similarity index 89%
rename from pyfus/bf/sequence.py
rename to src/openlifu/bf/sequence.py
index 8bd1f254..ab41fa47 100644
--- a/pyfus/bf/sequence.py
+++ b/src/openlifu/bf/sequence.py
@@ -27,7 +27,7 @@ def get_table(self):
{"Name": "Pulse Train Interval", "Value": self.pulse_train_interval, "Unit": "s"},
{"Name": "Pulse Train Count", "Value": self.pulse_train_count, "Unit": ""}]
return pd.DataFrame.from_records(records)
-
+
@staticmethod
def from_dict(d):
"""
@@ -36,18 +36,18 @@ def from_dict(d):
:param d: Dictionary of the sequence parameters
:returns: Sequence object
"""
- return Sequence(pulse_interval=d["pulse_interval"],
+ return Sequence(pulse_interval=d["pulse_interval"],
pulse_count=d["pulse_count"],
- pulse_train_interval=d["pulse_train_interval"],
+ pulse_train_interval=d["pulse_train_interval"],
pulse_train_count=d["pulse_train_count"])
-
+
def to_dict(self):
"""
Convert the sequence to a dictionary
:returns: Dictionary of the sequence parameters
"""
- return {"pulse_interval": self.pulse_interval,
+ return {"pulse_interval": self.pulse_interval,
"pulse_count": self.pulse_count,
- "pulse_train_interval": self.pulse_train_interval,
- "pulse_train_count": self.pulse_train_count}
\ No newline at end of file
+ "pulse_train_interval": self.pulse_train_interval,
+ "pulse_train_count": self.pulse_train_count}
diff --git a/pyfus/db/__init__.py b/src/openlifu/db/__init__.py
similarity index 100%
rename from pyfus/db/__init__.py
rename to src/openlifu/db/__init__.py
diff --git a/pyfus/db/database.py b/src/openlifu/db/database.py
similarity index 99%
rename from pyfus/db/database.py
rename to src/openlifu/db/database.py
index 788e2363..cee86aa4 100644
--- a/pyfus/db/database.py
+++ b/src/openlifu/db/database.py
@@ -8,8 +8,8 @@
import h5py
import glob
from typing import Literal, Optional
-from pyfus.plan import Protocol, Solution
-from pyfus.db import Subject
+from openlifu.plan import Protocol, Solution
+from openlifu.db import Subject
OnConflictOpts = Literal['error', 'overwrite', 'skip']
@@ -40,7 +40,7 @@ def add_protocol(self, protocol: Protocol, on_conflict: OnConflictOpts = "error"
# Check if the sonication protocol ID already exists in the database
protocol_id = protocol.id
protocol_ids = self.get_protocol_ids()
-
+
if protocol_id in protocol_ids:
if on_conflict == "error":
raise ValueError(f"Protocol with ID {protocol_id} already exists in the database.")
@@ -342,12 +342,12 @@ def get_transducer_ids(self):
self.logger.warning("Transducers file not found.")
return []
- def load_gridweights(self, transducer_id, grid_hash):
+ def load_gridweights(self, transducer_id, grid_hash):
gridweight_filename = self.get_gridweights_filename(transducer_id, grid_hash)
with h5py.File(gridweight_filename, "r") as f:
grid_weights = f["grid_weights"][:]
return grid_weights
-
+
def load_subject(self, subject_id, options=None):
subject_filename = self.get_subject_filename(subject_id)
subject = Subject.from_file(subject_filename)
@@ -380,7 +380,7 @@ def load_system(self, sys_id=None):
return sys
def load_transducer(self, transducer_id):
- from pyfus.xdc import Transducer
+ from openlifu.xdc import Transducer
transducer_filename = self.get_transducer_filename(transducer_id)
transducer = Transducer.from_file(transducer_filename)
return transducer
@@ -564,7 +564,7 @@ def write_transducer_ids(self, transducer_ids):
def get_default_user_dir():
"""
Get the default user directory for the database
-
+
:returns: Default user directory
"""
return os.path.expanduser("~")
@@ -573,7 +573,7 @@ def get_default_user_dir():
def get_default_path(options=None):
"""
Get the default path for the database
-
+
:returns: Default path for the database
"""
return os.path.join(Database.get_default_user_dir(), "Documents", "db")
diff --git a/pyfus/db/session.py b/src/openlifu/db/session.py
similarity index 94%
rename from pyfus/db/session.py
rename to src/openlifu/db/session.py
index 1b7d164d..9877b236 100644
--- a/pyfus/db/session.py
+++ b/src/openlifu/db/session.py
@@ -1,9 +1,9 @@
from dataclasses import dataclass, field
from typing import Optional, List
from datetime import datetime
-from pyfus.geo import Point
-from pyfus.xdc import Transducer
-from pyfus.util.strings import sanitize
+from openlifu.geo import Point
+from openlifu.xdc import Transducer
+from openlifu.util.strings import sanitize
import xarray
@dataclass
@@ -53,7 +53,7 @@ def __post_init__(self):
def from_dict(d):
"""
Create a session from a dictionary
-
+
:param d: Dictionary of session parameters
:returns: Session object
"""
@@ -82,11 +82,11 @@ def from_dict(d):
elif isinstance(d['markers'], Point):
d['markers'] = [d['markers']]
return Session(**d)
-
+
def to_dict(self):
"""
Convert the session to a dictionary
-
+
:returns: Dictionary of session parameters
"""
d = self.__dict__.copy()
@@ -97,12 +97,12 @@ def to_dict(self):
d['targets'] = [p.to_dict() for p in d['targets']]
d['markers'] = [p.to_dict() for p in d['markers']]
return d
-
+
def to_file(self, filename):
"""
Save the session to a file
-
+
:param filename: Name of the file
"""
- from pyfus.util.json import to_json
- to_json(self.to_dict(), filename)
\ No newline at end of file
+ from openlifu.util.json import to_json
+ to_json(self.to_dict(), filename)
diff --git a/pyfus/db/subject.py b/src/openlifu/db/subject.py
similarity index 90%
rename from pyfus/db/subject.py
rename to src/openlifu/db/subject.py
index 36284087..1fe64b0e 100644
--- a/pyfus/db/subject.py
+++ b/src/openlifu/db/subject.py
@@ -1,6 +1,6 @@
from dataclasses import dataclass, field
from typing import List, Optional
-from pyfus.util.strings import sanitize
+from openlifu.util.strings import sanitize
import json
@dataclass
@@ -34,12 +34,12 @@ def __post_init__(self):
def from_dict(d):
"""
Create a subject from a dictionary
-
+
:param d: Dictionary of subject parameters
:returns: Subject object
"""
return Subject(**d)
-
+
@staticmethod
def from_file(filename):
"""
@@ -50,21 +50,21 @@ def from_file(filename):
"""
with open(filename, 'r') as f:
return Subject.from_dict(json.load(f))
-
+
def to_dict(self):
"""
Convert the subject to a dictionary
-
+
:returns: Dictionary of subject parameters
"""
return self.__dict__.copy()
-
+
def to_file(self, filename):
"""
Write the subject to a file
-
+
:param filename: Name of the file to write
"""
- from pyfus.util.json import to_json
+ from openlifu.util.json import to_json
with open(filename, 'w') as f:
- json.dump(self.to_dict(), f, indent=4)
\ No newline at end of file
+ json.dump(self.to_dict(), f, indent=4)
diff --git a/pyfus/geo.py b/src/openlifu/geo.py
similarity index 95%
rename from pyfus/geo.py
rename to src/openlifu/geo.py
index ee8146b8..df52e2b5 100644
--- a/pyfus/geo.py
+++ b/src/openlifu/geo.py
@@ -1,7 +1,7 @@
from typing import Any, Tuple, Optional
import numpy as np
from dataclasses import dataclass, field
-from pyfus.util.units import getunitconversion
+from openlifu.util.units import getunitconversion
import copy
import vtk
@@ -19,7 +19,7 @@ def __post_init__(self):
if len(self.position) != len(self.dims):
raise ValueError("Position and dims must have same length.")
self.position = np.array(self.position).reshape(3)
-
+
def copy(self):
return copy.deepcopy(self)
@@ -48,7 +48,7 @@ def get_matrix(self, origin: np.ndarray = np.eye(4), center_on_point: bool = Fal
if not local:
m = np.dot(origin, m)
return m
-
+
def get_polydata(self, transform: np.ndarray = np.eye(4), units=None):
units = self.units if units is None else units
colors = vtk.vtkNamedColors()
@@ -77,9 +77,9 @@ def rescale(self, units: str):
self.radius = self.radius * scl
self.units = units
- def transform(self,
- matrix: np.ndarray,
- units: Optional[str] = None,
+ def transform(self,
+ matrix: np.ndarray,
+ units: Optional[str] = None,
new_dims: Optional[Tuple[str, str, str]]=None):
if units is not None:
self.rescale(units)
diff --git a/pyfus/io/__init__.py b/src/openlifu/io/__init__.py
similarity index 58%
rename from pyfus/io/__init__.py
rename to src/openlifu/io/__init__.py
index ba0a6c28..536178af 100644
--- a/pyfus/io/__init__.py
+++ b/src/openlifu/io/__init__.py
@@ -1 +1 @@
-from .ustx import PulseProfile, DelayProfile, Tx7332Registers, TxModule, TxArray, print_regs, swap_byte_order
\ No newline at end of file
+from .ustx import PulseProfile, DelayProfile, Tx7332Registers, TxModule, TxArray, print_regs, swap_byte_order
diff --git a/pyfus/io/ustx.py b/src/openlifu/io/ustx.py
similarity index 97%
rename from pyfus/io/ustx.py
rename to src/openlifu/io/ustx.py
index 60c85c96..42d32232 100644
--- a/pyfus/io/ustx.py
+++ b/src/openlifu/io/ustx.py
@@ -1,6 +1,6 @@
from dataclasses import dataclass, field
from typing import Tuple, Optional, List, Dict, Literal
-from pyfus.util.units import getunitconversion
+from openlifu.util.units import getunitconversion
import numpy as np
import logging
@@ -28,8 +28,8 @@
ADDRESS_DYNPWR_1,
ADDRESS_LDO_PWR_2,
ADDRESS_TRSW_TURNON,
- ADDRESS_DELAY_SEL,
- ADDRESS_PATTERN_MODE,
+ ADDRESS_DELAY_SEL,
+ ADDRESS_PATTERN_MODE,
ADDRESS_PATTERN_REPEAT,
ADDRESS_PATTERN_SEL_G1,
ADDRESS_PATTERN_SEL_G2,
@@ -91,7 +91,7 @@
def get_delay_location(channel:int, profile:int=1):
"""
Gets the address and least significant bit of a delay
-
+
:param channel: Channel number
:param profile: Delay profile number
:returns: Register address and least significant bit of the delay location
@@ -149,7 +149,7 @@ def calc_pulse_pattern(frequency:float, duty_cycle:float=DEFAULT_PATTERN_DUTY_CY
:returns: Tuple of lists of levels and lengths, and the clock divider setting
"""
clk_div_n = 0
- while clk_div_n < 6:
+ while clk_div_n < 6:
clk_n = bf_clk / (2**clk_div_n)
period_samples = int(clk_n / frequency)
first_half_period_samples = int(period_samples / 2)
@@ -183,7 +183,7 @@ def calc_pulse_pattern(frequency:float, duty_cycle:float=DEFAULT_PATTERN_DUTY_CY
else:
per_lengths.append(MAX_PATTERN_PERIOD_LENGTH)
samples -= (MAX_PATTERN_PERIOD_LENGTH+2)
- per_levels.append(levels[i])
+ per_levels.append(levels[i])
else:
per_lengths.append(samples-2)
per_levels.append(levels[i])
@@ -191,8 +191,8 @@ def calc_pulse_pattern(frequency:float, duty_cycle:float=DEFAULT_PATTERN_DUTY_CY
if len(per_levels) <= MAX_PATTERN_PERIODS:
t = (np.arange(np.sum(np.array(per_lengths)+2))*(1/clk_n)).tolist()
y = np.concatenate([[yi]*(ni+2) for yi,ni in zip(per_levels, per_lengths)]).tolist()
- pattern = {'levels': per_levels,
- 'lengths': per_lengths,
+ pattern = {'levels': per_levels,
+ 'lengths': per_lengths,
'clk_div_n': clk_div_n,
't': t,
'y': y}
@@ -229,9 +229,9 @@ def print_regs(d):
def pack_registers(regs, pack_single:bool=False):
"""
Packs registers into contiguous blocks
-
+
:param regs: Dictionary of registers
- :param pack_single: Pack single registers into arrays. Default True.
+ :param pack_single: Pack single registers into arrays. Default True.
:returns: Dictionary of packed registers.
"""
addresses = sorted(regs.keys())
@@ -256,7 +256,7 @@ def pack_registers(regs, pack_single:bool=False):
def swap_byte_order(regs):
"""
Swaps the byte order of the registers
-
+
:param regs: Dictionary of registers
:returns: Dictionary of registers with swapped byte order
"""
@@ -283,7 +283,7 @@ def __post_init__(self):
raise ValueError(f"Apodizations list must have {self.num_elements} elements")
if self.profile not in VALID_DELAY_PROFILES:
raise ValueError(f"Invalid Profile {self.profile}")
-
+
@dataclass
class PulseProfile:
profile: int
@@ -292,11 +292,11 @@ class PulseProfile:
duty_cycle: float=DEFAULT_PATTERN_DUTY_CYCLE
tail_count: int=DEFAULT_TAIL_COUNT
invert: bool=False
-
+
def __post_init__(self):
if self.profile not in VALID_PATTERN_PROFILES:
raise ValueError(f"Invalid profile {self.profile}.")
-
+
@dataclass
class Tx7332Registers:
bf_clk: float = DEFAULT_CLK_FREQ
@@ -383,10 +383,10 @@ def get_pulse_profile(self, profile: Optional[int]=None) -> PulseProfile:
raise ValueError(f"Pulse profile {profile} not found")
profile = profiles.index(profile)
return self._pulse_profiles_list[profile]
-
+
def configured_pulse_profiles(self) -> List[int]:
return [p.profile for p in self._pulse_profiles_list]
-
+
def activate_delay_profile(self, profile:int):
if profile not in self.configured_delay_profiles():
raise ValueError(f"Delay profile {profile} not configured")
@@ -407,9 +407,9 @@ def get_delay_control_registers(self, profile: Optional[int]=None) -> Dict[int,i
delay_sel_register = 0
delay_sel_register = set_register_value(delay_sel_register, delay_profile.profile-1, lsb=12, width=4)
delay_sel_register = set_register_value(delay_sel_register, delay_profile.profile-1, lsb=28, width=4)
- return {ADDRESS_DELAY_SEL: delay_sel_register,
+ return {ADDRESS_DELAY_SEL: delay_sel_register,
ADDRESS_APODIZATION: apod_register}
-
+
def get_pulse_control_registers(self, profile: Optional[int]=None) -> Dict[int,int]:
if profile is None:
profile = self.active_pulse_profile
@@ -437,7 +437,7 @@ def get_pulse_control_registers(self, profile: Optional[int]=None) -> Dict[int,i
raise ValueError(f"Pattern duration too long for elastic repeat")
else:
repeat = cycles-1
- elastic_repeat = 0
+ elastic_repeat = 0
elastic_mode = 0
y = pattern['y']*(repeat+1)
y = np.array(y + [0]*pulse_profile.tail_count)
@@ -450,7 +450,7 @@ def get_pulse_control_registers(self, profile: Optional[int]=None) -> Dict[int,i
reg_repeat = set_register_value(reg_repeat, elastic_mode, lsb=11, width=1)
reg_repeat = set_register_value(reg_repeat, elastic_repeat, lsb=12, width=16)
reg_pat_sel = 0
- reg_pat_sel = set_register_value(reg_pat_sel, pulse_profile.profile-1, lsb=0, width=6)
+ reg_pat_sel = set_register_value(reg_pat_sel, pulse_profile.profile-1, lsb=0, width=6)
registers = {ADDRESS_PATTERN_MODE: reg_mode,
ADDRESS_PATTERN_REPEAT: reg_repeat,
ADDRESS_PATTERN_SEL_G1: reg_pat_sel,
@@ -470,8 +470,8 @@ def get_delay_data_registers(self, profile: Optional[int]=None, pack: bool=False
data_registers[address] = set_register_value(data_registers[address], delay_value, lsb=lsb, width=DELAY_WIDTH)
if pack:
data_registers = pack_registers(data_registers, pack_single=pack_single)
- return data_registers
-
+ return data_registers
+
def get_pulse_data_registers(self, profile: Optional[int]=None, pack: bool=False, pack_single: bool=False) -> Dict[int,int]:
if profile is None:
profile = self.active_pulse_profile
@@ -507,12 +507,12 @@ def get_registers(self, profiles: ProfileOpts = "configured", pack: bool=False,
raise ValueError(f"No delay profile activated")
if self.active_pulse_profile is None:
raise ValueError(f"No pulse profile activated")
- registers = {addr:0x0 for addr in ADDRESSES_GLOBAL}
+ registers = {addr:0x0 for addr in ADDRESSES_GLOBAL}
registers.update(self.get_delay_control_registers())
registers.update(self.get_pulse_control_registers())
if profiles == "active":
delay_data = self.get_delay_data_registers(pack=pack, pack_single=pack_single)
- pulse_data = self.get_pulse_data_registers(pack=pack, pack_single=pack_single)
+ pulse_data = self.get_pulse_data_registers(pack=pack, pack_single=pack_single)
else:
if profiles == "all":
delay_data = {addr:0x0 for addr in ADDRESSES_DELAY_DATA}
@@ -543,7 +543,7 @@ class TxModule:
def __post_init__(self):
self.transmitters = tuple([Tx7332Registers(bf_clk=self.bf_clk) for _ in range(self.num_transmitters)])
-
+
def add_pulse_profile(self, pulse_profile: PulseProfile, activate: Optional[bool]=None):
"""
Add a pulse profile
@@ -562,12 +562,12 @@ def add_pulse_profile(self, pulse_profile: PulseProfile, activate: Optional[bool
if activate:
self.active_pulse_profile = pulse_profile.profile
for tx in self.transmitters:
- tx.add_pulse_profile(pulse_profile, activate = activate)
-
+ tx.add_pulse_profile(pulse_profile, activate = activate)
+
def add_delay_profile(self, delay_profile: DelayProfile, activate: Optional[bool]=None):
"""
Add a delay profile
-
+
:param p: Delay profile
:param activate: Activate the delay profile
"""
@@ -610,7 +610,7 @@ def remove_delay_profile(self, profile:int):
def remove_pulse_profile(self, profile:int):
"""
Remove a pulse profile
-
+
:param profile: Pulse profile number
"""
profiles = self.configured_pulse_profiles()
@@ -636,12 +636,12 @@ def get_delay_profile(self, profile:Optional[int]=None) -> DelayProfile:
if profile not in profiles:
raise ValueError(f"Delay profile {profile} not found")
i = profiles.index(profile)
- return self._delay_profiles_list[i]
-
+ return self._delay_profiles_list[i]
+
def _configured_delay_profiles(self) -> List[int]:
"""
Get the configured delay profiles
-
+
:return: List of delay profiles
"""
return [p.profile for p in self._delay_profiles_list]
@@ -660,11 +660,11 @@ def get_pulse_profile(self, profile:Optional[int]=None) -> PulseProfile:
raise ValueError(f"Pulse profile {profile} not found")
i = profiles.index(profile)
return self._pulse_profiles_list[i]
-
+
def configured_pulse_profiles(self) -> List[int]:
"""
Get the configured pulse profiles
-
+
:return: List of pulse profiles
"""
return [p.profile for p in self._pulse_profiles_list]
@@ -672,17 +672,17 @@ def configured_pulse_profiles(self) -> List[int]:
def activate_delay_profile(self, profile:int=1):
"""
Activates a delay profile
-
+
:param profile: Delay profile number
"""
for tx in self.transmitters:
- tx.activate_delay_profile(profile)
+ tx.activate_delay_profile(profile)
self.active_delay_profile = profile
def activate_pulse_profile(self, profile:int=1):
"""
Activates a pulse profile
-
+
:param profile: Pulse profile number
"""
for tx in self.transmitters:
@@ -723,7 +723,7 @@ def get_registers(self, profiles: ProfileOpts = "configured", recompute: bool =
self.recompute_delay_profiles()
self.recompute_pulse_profiles()
return [tx.get_registers(profiles, pack=pack, pack_single=pack_single) for tx in self.transmitters]
-
+
def get_delay_control_registers(self, profile:Optional[int]=None) -> List[Dict[int,int]]:
"""
Get the delay control registers for all transmitters
@@ -734,7 +734,7 @@ def get_delay_control_registers(self, profile:Optional[int]=None) -> List[Dict[i
if profile is None:
profile = self.active_delay_profile
return [tx.get_delay_control_registers(profile) for tx in self.transmitters]
-
+
def get_pulse_control_registers(self, profile:Optional[int]=None) -> List[Dict[int,int]]:
"""
Get the pulse control registers for all transmitters
@@ -745,7 +745,7 @@ def get_pulse_control_registers(self, profile:Optional[int]=None) -> List[Dict[i
if profile is None:
profile = self.active_pulse_profile
return [tx.get_pulse_control_registers(profile) for tx in self.transmitters]
-
+
def get_delay_data_registers(self, profile:Optional[int]=None, pack: bool=False, pack_single: bool=False) -> List[Dict[int,int]]:
"""
Get the delay data registers for all transmitters
@@ -756,7 +756,7 @@ def get_delay_data_registers(self, profile:Optional[int]=None, pack: bool=False,
if profile is None:
profile = self.active_delay_profile
return [tx.get_delay_data_registers(profile, pack=pack, pack_single=pack_single) for tx in self.transmitters]
-
+
def get_pulse_data_registers(self, profile:Optional[int]=None, pack: bool=False, pack_single: bool=False) -> List[Dict[int,int]]:
"""
Get the pulse data registers for all transmitters
@@ -767,7 +767,7 @@ def get_pulse_data_registers(self, profile:Optional[int]=None, pack: bool=False,
if profile is None:
profile = self.active_pulse_profile
return [tx.get_pulse_data_registers(profile, pack=pack, pack_single=pack_single) for tx in self.transmitters]
-
+
@dataclass
class TxArray:
i2c_addresses: Tuple[int] = (0x0,)
@@ -804,11 +804,11 @@ def add_pulse_profile(self, pulse_profile: PulseProfile, activate: Optional[bool
self.active_pulse_profile = pulse_profile.profile
for module in self.modules.values():
module.add_pulse_profile(pulse_profile, activate)
-
+
def add_delay_profile(self, delay_profile: DelayProfile, activate: Optional[bool]=None):
"""
Add a delay profile
-
+
:param p: Delay profile
:param activate: Activate the delay profile
"""
@@ -835,7 +835,7 @@ def add_delay_profile(self, delay_profile: DelayProfile, activate: Optional[bool
def remove_pulse_profile(self, profile:int):
"""
Remove a pulse profile
-
+
:param profile: Pulse profile number
"""
profiles = self.configured_pulse_profiles()
@@ -863,7 +863,7 @@ def remove_delay_profile(self, profile:int):
self.active_delay_profile = None
for module in self.modules.values():
module.remove_delay_profile(profile)
-
+
def get_pulse_profile(self, profile:Optional[int]=None) -> PulseProfile:
"""
Retrieve a pulse profile
@@ -878,11 +878,11 @@ def get_pulse_profile(self, profile:Optional[int]=None) -> PulseProfile:
raise ValueError(f"Pulse profile {profile} not found")
i = profiles.index(profile)
return self._pulse_profiles_list[i]
-
+
def configured_pulse_profiles(self) -> List[int]:
"""
Get the configured pulse profiles
-
+
:return: List of pulse profiles
"""
return [p.profile for p in self._pulse_profiles_list]
@@ -901,11 +901,11 @@ def get_delay_profile(self, profile:Optional[int]=None) -> DelayProfile:
raise ValueError(f"Delay profile {profile} not found")
i = profiles.index(profile)
return self._delay_profiles_list[i]
-
+
def configured_delay_profiles(self) -> List[int]:
"""
Get the configured delay profiles
-
+
:return: List of delay profiles
"""
return [p.profile for p in self._delay_profiles_list]
@@ -913,21 +913,21 @@ def configured_delay_profiles(self) -> List[int]:
def activate_pulse_profile(self, profile:int=1):
"""
Activates a pulse profile
-
+
:param profile: Pulse profile number
"""
for module in self.modules.values():
module.activate_pulse_profile(profile)
self.active_pulse_profile = profile
-
+
def activate_delay_profile(self, profile:int=1):
"""
Activates a delay profile
-
+
:param profile: Delay profile number
"""
for module in self.modules.values():
- module.activate_delay_profile(profile)
+ module.activate_delay_profile(profile)
self.active_delay_profile = profile
def recompute_pulse_profiles(self):
@@ -964,7 +964,7 @@ def get_registers(self, profiles: ProfileOpts = "configured", recompute: bool =
self.recompute_delay_profiles()
self.recompute_pulse_profiles()
return {addr:module.get_registers(profiles, pack=pack, pack_single=pack_single) for addr, module in self.modules.items()}
-
+
def get_delay_control_registers(self, profile:Optional[int]=None) -> Dict[int, List[Dict[int,int]]]:
"""
Get the delay control registers for all modules
@@ -975,7 +975,7 @@ def get_delay_control_registers(self, profile:Optional[int]=None) -> Dict[int, L
if profile is None:
profile = self.active_delay_profile
return {addr:module.get_delay_control_registers(profile) for addr, module in self.modules.items()}
-
+
def get_pulse_control_registers(self, profile:Optional[int]=None) -> Dict[int, List[Dict[int,int]]]:
"""
Get the pulse control registers for all modules
@@ -986,7 +986,7 @@ def get_pulse_control_registers(self, profile:Optional[int]=None) -> Dict[int, L
if profile is None:
profile = self.active_pulse_profile
return {addr:module.get_pulse_control_registers(profile) for addr, module in self.modules.items()}
-
+
def get_delay_data_registers(self, profile:Optional[int]=None, pack: bool=False, pack_single: bool=False) -> Dict[int, List[Dict[int,int]]]:
"""
Get the delay data registers for all modules
@@ -997,7 +997,7 @@ def get_delay_data_registers(self, profile:Optional[int]=None, pack: bool=False,
if profile is None:
profile = self.active_delay_profile
return {addr:module.get_delay_data_registers(profile, pack=pack, pack_single=pack_single) for addr, module in self.modules.items()}
-
+
def get_pulse_data_registers(self, profile:Optional[int]=None, pack: bool=False, pack_single: bool=False) -> Dict[int, List[Dict[int,int]]]:
"""
Get the pulse data registers for all modules
@@ -1008,4 +1008,3 @@ def get_pulse_data_registers(self, profile:Optional[int]=None, pack: bool=False,
if profile is None:
profile = self.active_pulse_profile
return {addr:module.get_pulse_data_registers(profile, pack=pack, pack_single=pack_single) for addr, module in self.modules.items()}
-
diff --git a/pyfus/plan/__init__.py b/src/openlifu/plan/__init__.py
similarity index 100%
rename from pyfus/plan/__init__.py
rename to src/openlifu/plan/__init__.py
diff --git a/pyfus/plan/protocol.py b/src/openlifu/plan/protocol.py
similarity index 94%
rename from pyfus/plan/protocol.py
rename to src/openlifu/plan/protocol.py
index e8314adb..8cc14877 100644
--- a/pyfus/plan/protocol.py
+++ b/src/openlifu/plan/protocol.py
@@ -1,6 +1,6 @@
from dataclasses import dataclass, field, InitVar
from typing import List
-from pyfus import bf, sim, seg, xdc, geo
+from openlifu import bf, sim, seg, xdc, geo
import json
import xarray as xa
@@ -18,7 +18,7 @@ class Protocol:
seg_method: seg.SegmentationMethod = field(default_factory=seg.seg_methods.Water)
param_constraints: dict = field(default_factory=dict)
target_constraints: dict = field(default_factory=dict)
- analysis_options: dict = field(default_factory=dict)
+ analysis_options: dict = field(default_factory=dict)
@staticmethod
def from_dict(d):
@@ -31,7 +31,7 @@ def from_dict(d):
seg_method_dict = d.get("seg_method", {})
if "materials" in d:
seg_method_dict["materials"] = seg.Material.from_dict(d.pop("materials"))
- d["seg_method"] = seg.SegmentationMethod.from_dict(seg_method_dict)
+ d["seg_method"] = seg.SegmentationMethod.from_dict(seg_method_dict)
return Protocol(**d)
def to_dict(self):
@@ -50,14 +50,14 @@ def to_dict(self):
"target_constraints": self.target_constraints,
"analysis_options": self.analysis_options,
}
-
+
@staticmethod
def from_file(filename):
with open(filename, "r") as f:
d = json.load(f)
return Protocol.from_dict(d)
-
+
def beamform(self, arr: xdc.Transducer, target:geo.Point, params: xa.Dataset):
delays = self.delay_method.calc_delays(arr, target, params)
apod = self.apod_method.calc_apodization(arr, target, params)
- return delays, apod
\ No newline at end of file
+ return delays, apod
diff --git a/pyfus/plan/solution.py b/src/openlifu/plan/solution.py
similarity index 76%
rename from pyfus/plan/solution.py
rename to src/openlifu/plan/solution.py
index c39f4e96..9171a780 100644
--- a/pyfus/plan/solution.py
+++ b/src/openlifu/plan/solution.py
@@ -3,4 +3,4 @@
@dataclass
class Solution:
id: str = "solution"
- name: str = "Solution"
\ No newline at end of file
+ name: str = "Solution"
diff --git a/pyfus/seg/__init__.py b/src/openlifu/seg/__init__.py
similarity index 100%
rename from pyfus/seg/__init__.py
rename to src/openlifu/seg/__init__.py
diff --git a/pyfus/seg/material.py b/src/openlifu/seg/material.py
similarity index 96%
rename from pyfus/seg/material.py
rename to src/openlifu/seg/material.py
index 64869894..6bb88e34 100644
--- a/pyfus/seg/material.py
+++ b/src/openlifu/seg/material.py
@@ -11,7 +11,7 @@ class Material:
attenuation: float = 0.0 # dB/cm/MHz
specific_heat: float = 4182.0 # J/kg/K
thermal_conductivity: float = 0.598 # W/m/K
- param_ids: Tuple[str] = field(default_factory= lambda: ("sound_speed", "density", "attenuation", "specific_heat", "thermal_conductivity"), init=False, repr=False)
+ param_ids: Tuple[str] = field(default_factory= lambda: ("sound_speed", "density", "attenuation", "specific_heat", "thermal_conductivity"), init=False, repr=False)
@classmethod
def param_info(cls, param_id: str):
@@ -38,14 +38,14 @@ def get_param(self, param_id: str):
if param_id not in self.param_ids:
raise ValueError(f"Parameter {param_id} not found.")
return self.__getattribute__(param_id)
-
+
@staticmethod
def get_materials(material_id="all", as_dict=True):
material_id = ("water", "tissue", "skull", "air", "standoff") if material_id == "all" else material_id
if isinstance(material_id, tuple) or isinstance(material_id, list):
materials = {m: Material.get_materials(m, as_dict=False) for m in material_id}
elif material_id in MATERIALS:
- materials = MATERIALS[material_id]
+ materials = MATERIALS[material_id]
else:
raise ValueError(f"Material {material_id} not found.")
if as_dict:
@@ -109,4 +109,4 @@ def from_dict(d):
"tissue": TISSUE,
"skull": SKULL,
"air": AIR,
- "standoff": STANDOFF}
\ No newline at end of file
+ "standoff": STANDOFF}
diff --git a/pyfus/seg/seg_methods/__init__.py b/src/openlifu/seg/seg_methods/__init__.py
similarity index 100%
rename from pyfus/seg/seg_methods/__init__.py
rename to src/openlifu/seg/seg_methods/__init__.py
diff --git a/pyfus/seg/seg_methods/seg_method.py b/src/openlifu/seg/seg_methods/seg_method.py
similarity index 88%
rename from pyfus/seg/seg_methods/seg_method.py
rename to src/openlifu/seg/seg_methods/seg_method.py
index f241d734..4eeb84fb 100644
--- a/pyfus/seg/seg_methods/seg_method.py
+++ b/src/openlifu/seg/seg_methods/seg_method.py
@@ -1,16 +1,16 @@
from dataclasses import dataclass, field
from abc import ABC, abstractmethod
from typing import Optional
-from pyfus.seg.material import Material, MATERIALS
+from openlifu.seg.material import Material, MATERIALS
import xarray as xa
import numpy as np
-from pyfus.seg import seg_methods
+from openlifu.seg import seg_methods
@dataclass
class SegmentationMethod:
materials: dict = field(default_factory=lambda: MATERIALS.copy())
ref_material: str = "water"
-
+
def __post_init__(self):
if self.ref_material not in self.materials.keys():
raise ValueError(f"Reference material {self.ref_material} not found.")
@@ -21,13 +21,13 @@ def _segment(self, volume: xa.DataArray):
@staticmethod
def from_dict(d):
if isinstance(d, str):
- import pyfus.seg.seg_methods
+ import openlifu.seg.seg_methods
if d == "water":
- return pyfus.seg.seg_methods.Water()
+ return openlifu.seg.seg_methods.Water()
elif d == "tissue":
- return pyfus.seg.seg_methods.Tissue()
+ return openlifu.seg.seg_methods.Tissue()
elif d == "segmented":
- return pyfus.seg.seg_methods.SegmentMRI()
+ return openlifu.seg.seg_methods.SegmentMRI()
else:
d = d.copy()
short_classname = d.pop("class")
@@ -38,7 +38,7 @@ def from_dict(d):
def _material_indices(self, materials: Optional[dict] = None):
materials = self.materials if materials is None else materials
return {material_id: i for i, material_id in enumerate(materials.keys())}
-
+
def _map_params(self, seg: xa.DataArray, materials: Optional[dict] = None):
materials = self.materials if materials is None else materials
material_dict = self._material_indices(materials=materials)
@@ -53,25 +53,25 @@ def _map_params(self, seg: xa.DataArray, materials: Optional[dict] = None):
params[param_id] = param
params.attrs['ref_material'] = ref_mat
return params
-
+
def seg_params(self, volume: xa.DataArray, materials: Optional[dict] = None):
materials = self.materials if materials is None else materials
seg = self._segment(volume)
params = self._map_params(seg, materials=materials)
return params
-
+
def ref_params(self, coords: xa.Coordinates):
seg = self._ref_segment(coords)
params = self._map_params(seg)
return params
-
+
def _ref_segment(self, coords: xa.Coordinates):
material_dict = self._material_indices()
m_idx = material_dict[self.ref_material]
sz = list(coords.sizes.values())
seg = xa.DataArray(np.full(sz, m_idx, dtype=int), coords=coords)
return seg
-
+
def to_dict(self):
d = self.__dict__.copy()
d['class'] = self.__class__.__name__
@@ -80,4 +80,4 @@ def to_dict(self):
@dataclass
class UniformSegmentation(SegmentationMethod):
def _segment(self, vol: xa.DataArray):
- return self._ref_segment(vol.coords)
\ No newline at end of file
+ return self._ref_segment(vol.coords)
diff --git a/pyfus/seg/seg_methods/segment_mri.py b/src/openlifu/seg/seg_methods/segment_mri.py
similarity index 59%
rename from pyfus/seg/seg_methods/segment_mri.py
rename to src/openlifu/seg/seg_methods/segment_mri.py
index 8775ddbd..1f5c5b85 100644
--- a/pyfus/seg/seg_methods/segment_mri.py
+++ b/src/openlifu/seg/seg_methods/segment_mri.py
@@ -1,8 +1,8 @@
from dataclasses import dataclass
-from pyfus.seg.seg_methods.seg_method import SegmentationMethod
+from openlifu.seg.seg_methods.seg_method import SegmentationMethod
import xarray as xa
@dataclass
class SegmentMRI(SegmentationMethod):
def _segment(self, volume: xa.DataArray):
- raise NotImplementedError
\ No newline at end of file
+ raise NotImplementedError
diff --git a/src/openlifu/seg/seg_methods/tissue.py b/src/openlifu/seg/seg_methods/tissue.py
new file mode 100644
index 00000000..1423fbf1
--- /dev/null
+++ b/src/openlifu/seg/seg_methods/tissue.py
@@ -0,0 +1,6 @@
+from dataclasses import dataclass
+from openlifu.seg.seg_methods.seg_method import UniformSegmentation
+
+@dataclass
+class Tissue(UniformSegmentation):
+ ref_material: str = "tissue"
diff --git a/src/openlifu/seg/seg_methods/water.py b/src/openlifu/seg/seg_methods/water.py
new file mode 100644
index 00000000..fdff9ece
--- /dev/null
+++ b/src/openlifu/seg/seg_methods/water.py
@@ -0,0 +1,6 @@
+from dataclasses import dataclass
+from openlifu.seg.seg_methods.seg_method import UniformSegmentation
+
+@dataclass
+class Water(UniformSegmentation):
+ ref_material: str = "water"
diff --git a/pyfus/sim/__init__.py b/src/openlifu/sim/__init__.py
similarity index 100%
rename from pyfus/sim/__init__.py
rename to src/openlifu/sim/__init__.py
diff --git a/pyfus/sim/kwave_if.py b/src/openlifu/sim/kwave_if.py
similarity index 91%
rename from pyfus/sim/kwave_if.py
rename to src/openlifu/sim/kwave_if.py
index 9b1dab28..2310f8e5 100644
--- a/pyfus/sim/kwave_if.py
+++ b/src/openlifu/sim/kwave_if.py
@@ -1,5 +1,5 @@
-from pyfus import xdc
-from pyfus.util.units import getunitconversion
+from openlifu import xdc
+from openlifu.util.units import getunitconversion
import kwave
import kwave.data
from kwave.kgrid import kWaveGrid
@@ -29,7 +29,7 @@ def get_kgrid(coords: xa.Coordinates, t_end = 0, dt = 0, sound_speed_ref=1500):
kgrid.setTime(Nt, dt)
return kgrid
-def get_karray(arr: xdc.Transducer,
+def get_karray(arr: xdc.Transducer,
bli_tolerance: float = 0.05,
upsampling_rate: int = 5,
translation: List[float] = [0.,0.,0.],
@@ -47,7 +47,7 @@ def get_karray(arr: xdc.Transducer,
return karray
def get_medium(params: xa.Dataset):
- medium= kWaveMedium(sound_speed=params['sound_speed'].attrs['ref_value'],
+ medium= kWaveMedium(sound_speed=params['sound_speed'].attrs['ref_value'],
density=params['density'].attrs['ref_value'])
return medium
@@ -73,10 +73,10 @@ def hash_array_kgrid(kgrid, karray):
'BLI_tolerance': karray.bli_tolerance,
'upsampling_rate': karray.upsampling_rate}
check = c.checksum(bytes(json.dumps(d), 'utf-8'))
- return f'{check:x}'
+ return f'{check:x}'
-def run_simulation(arr: xdc.Transducer,
- params: xa.Dataset,
+def run_simulation(arr: xdc.Transducer,
+ params: xa.Dataset,
delays: Optional[np.ndarray] = None,
apod: Optional[np.ndarray] = None,
freq: float = 1e6,
@@ -100,7 +100,7 @@ def run_simulation(arr: xdc.Transducer,
pcoords = params.coords['lat'].attrs['units']
scl = getunitconversion(pcoords, 'm')
array_offset =[-float(coord.mean())*scl for coord in params.coords.values()]
- karray = get_karray(arr,
+ karray = get_karray(arr,
translation=array_offset,
bli_tolerance=bli_tolerance,
upsampling_rate=upsampling_rate)
@@ -127,26 +127,26 @@ def run_simulation(arr: xdc.Transducer,
data_cast='single'
)
execution_options = SimulationExecutionOptions(is_gpu_simulation=True)
- output = kspaceFirstOrder3D(kgrid=kgrid,
- source=source,
- sensor=sensor,
- medium=medium,
+ output = kspaceFirstOrder3D(kgrid=kgrid,
+ source=source,
+ sensor=sensor,
+ medium=medium,
simulation_options=simulation_options,
execution_options=execution_options)
logging.info('Simulation Complete')
sz = list(params.coords.sizes.values())
p_max = xa.DataArray(output['p_max'].reshape(sz, order='F'),
coords=params.coords,
- name='p_max',
+ name='p_max',
attrs={'units':'Pa', 'long_name':'PPP'})
p_min = xa.DataArray(-1*output['p_min'].reshape(sz, order='F'),
coords=params.coords,
- name='p_min',
+ name='p_min',
attrs={'units':'Pa', 'long_name':'PNP'})
Z = params['density'].data*params['sound_speed'].data
intensity = xa.DataArray(1e-4*output['p_min'].reshape(sz, order='F')**2/(2*Z),
coords=params.coords,
- name='I',
+ name='I',
attrs={'units':'W/cm^2', 'long_name':'Intensity'})
ds = xa.Dataset({'p_max':p_max, 'p_min':p_min, 'ita':intensity})
return ds, output
diff --git a/pyfus/sim/sim_setup.py b/src/openlifu/sim/sim_setup.py
similarity index 95%
rename from pyfus/sim/sim_setup.py
rename to src/openlifu/sim/sim_setup.py
index 21a0b130..b4be6204 100644
--- a/pyfus/sim/sim_setup.py
+++ b/src/openlifu/sim/sim_setup.py
@@ -3,8 +3,8 @@
import numpy as np
import xarray as xa
import logging
-from pyfus.util.units import getunitconversion
-from pyfus.xdc import Transducer
+from openlifu.util.units import getunitconversion
+from openlifu.xdc import Transducer
@dataclass
class SimSetup:
@@ -58,24 +58,24 @@ def get_coords(self, dims=None, units: Optional[str] = None):
coords = xa.Coordinates({dim: np.linspace(extents[i][0], extents[i][1], sizes[i]) for i, dim in enumerate(dims)})
for i, dim in enumerate(dims):
coords[dim].attrs['units'] = units
- coords[dim].attrs['long_name'] = self.names[i]
+ coords[dim].attrs['long_name'] = self.names[i]
return coords
-
+
def get_corners(self, id: str = "corners", units: Optional[str] = None):
units = self.units if units is None else units
scl = getunitconversion(self.units, units)
xyz = np.array(np.meshgrid(self.x_extent, self.y_extent, self.z_extent, indexing='ij'))
corners = xyz.reshape(3,-1)
return corners*scl
-
+
def get_extent(self, dims: Optional[str]=None, units: Optional[str] = None):
dims = self.dims if dims is None else dims
units = self.units if units is None else units
scl = getunitconversion(self.units, units)
extents = [self.x_extent, self.y_extent, self.z_extent]
- return np.array([extents[self.dims.index(dim)] for dim in dims])*scl
-
- def get_max_cycle_offset(self, arr:Transducer, frequency: Optional[float] = None, delays: Optional[np.ndarray]=None, zmin: float =10e-3):
+ return np.array([extents[self.dims.index(dim)] for dim in dims])*scl
+
+ def get_max_cycle_offset(self, arr:Transducer, frequency: Optional[float] = None, delays: Optional[np.ndarray]=None, zmin: float =10e-3):
frequency = arr.frequency if frequency is None else frequency
delays = np.zeros(arr.numelements()) if delays is None else delays
coords = self.get_coords(units="m")
@@ -93,19 +93,19 @@ def get_max_distance(self, arr: Transducer, units: Optional[str] = None):
distances = np.array([[el.distance_to_point(corner, units=units) for corner in corners.T] for el in arr.elements])
max_distance = np.max(distances)
return max_distance
-
+
def get_size(self, dims: Optional[str]=None):
dims = self.dims if dims is None else dims
n = [int(np.round(np.diff(ext)/self.spacing))+1 for ext in [self.x_extent, self.y_extent, self.z_extent]]
return np.array([n[self.dims.index(dim)] for dim in dims]).squeeze()
-
+
def get_spacing(self, units: Optional[str] = None):
units = self.units if units is None else units
return getunitconversion(self.units, units)*self.spacing
def transform_scene(self, scene, id: Optional[str] = None, name: Optional[str] = None, units: Optional[str] = None):
raise NotImplementedError
-
+
@staticmethod
def from_dict(d):
- return SimSetup(**d)
\ No newline at end of file
+ return SimSetup(**d)
diff --git a/pyfus/util/json.py b/src/openlifu/util/json.py
similarity index 76%
rename from pyfus/util/json.py
rename to src/openlifu/util/json.py
index 4ad008f1..170444d6 100644
--- a/pyfus/util/json.py
+++ b/src/openlifu/util/json.py
@@ -1,12 +1,12 @@
import json
import os
import numpy as np
-from pyfus.geo import Point
-from pyfus.xdc.transducer import Transducer
-from pyfus.xdc.element import Element
-from pyfus.seg.material import Material
-from pyfus.db.session import Session
-from pyfus.db.subject import Subject
+from openlifu.geo import Point
+from openlifu.xdc.transducer import Transducer
+from openlifu.xdc.element import Element
+from openlifu.seg.material import Material
+from openlifu.db.session import Session
+from openlifu.db.subject import Subject
class PYFUSEncoder(json.JSONEncoder):
def default(self, obj):
@@ -35,4 +35,4 @@ def to_json(obj, filename):
if dirname and not os.path.exists(dirname):
os.makedirs(dirname)
with open(filename, 'w') as file:
- json.dump(obj, file, cls=PYFUSEncoder, indent=4)
\ No newline at end of file
+ json.dump(obj, file, cls=PYFUSEncoder, indent=4)
diff --git a/pyfus/util/strings.py b/src/openlifu/util/strings.py
similarity index 98%
rename from pyfus/util/strings.py
rename to src/openlifu/util/strings.py
index 3ee533d9..9f8a2488 100644
--- a/pyfus/util/strings.py
+++ b/src/openlifu/util/strings.py
@@ -36,4 +36,4 @@ def sanitize(in_str, case: Cases ='snake'):
else:
raise ValueError(f'Unrecognized case type {case}')
- return out_str
\ No newline at end of file
+ return out_str
diff --git a/pyfus/util/units.py b/src/openlifu/util/units.py
similarity index 97%
rename from pyfus/util/units.py
rename to src/openlifu/util/units.py
index 6f95f1cd..5bb3abf0 100644
--- a/pyfus/util/units.py
+++ b/src/openlifu/util/units.py
@@ -28,17 +28,17 @@ def getunittype(unit):
def getunitconversion(from_unit, to_unit, unitratio=None, constant=None):
if not from_unit:
return 1.0
-
+
if unitratio is not None and constant is not None:
if '/' not in unitratio:
raise ValueError('Conversion unit ratio must have a \'/\' symbol')
-
+
unitn, unitd = unitratio.split('/')
type0 = getunittype(from_unit)
type1 = getunittype(to_unit)
typen = getunittype(unitn)
typed = getunittype(unitd)
-
+
if type0 == typed and type1 == typen:
scl = getunitconversion(from_unit, unitd) * constant * getunitconversion(unitn, to_unit)
elif type0 == typen and type1 == typed:
@@ -50,7 +50,7 @@ def getunitconversion(from_unit, to_unit, unitratio=None, constant=None):
else:
slash0 = from_unit.find('/')
slash1 = to_unit.find('/')
-
+
if slash0 != -1 and slash1 != -1:
num0 = from_unit[:slash0]
denom0 = from_unit[slash0+1:]
@@ -60,19 +60,19 @@ def getunitconversion(from_unit, to_unit, unitratio=None, constant=None):
elif slash0 == -1 and slash1 == -1:
type0 = getunittype(from_unit)
type1 = getunittype(to_unit)
-
+
if type0 != type1:
raise ValueError('Unit type mismatch ({}) vs ({})'.format(type0, type1))
-
+
if type0 == 'other':
if from_unit[-1] != to_unit[-1]:
raise ValueError('Cannot convert {} to {}'.format(from_unit, to_unit))
-
+
i = 0
while i < min(len(from_unit), len(to_unit)) and from_unit[-i:] == to_unit[-i:]:
type = from_unit[-i:]
i += 1
-
+
scl0 = getsiscale(from_unit, type)
scl1 = getsiscale(to_unit, type)
scl = scl0 / scl1
@@ -82,12 +82,12 @@ def getunitconversion(from_unit, to_unit, unitratio=None, constant=None):
scl = scl0 / scl1
else:
raise ValueError('Unit ratio mismatch ({} vs {})'.format(from_unit, to_unit))
-
+
return scl
def getsiscale(unit, type):
type = type.lower()
-
+
if type in ['distance', 'area', 'volume']:
idx = unit.find('meters')
if idx == -1:
@@ -99,7 +99,7 @@ def getsiscale(unit, type):
idx = unit.rfind('m')
if idx == -1:
idx = len(unit)
-
+
elif type == 'time':
idx = unit.find('seconds')
if idx == -1:
@@ -110,25 +110,25 @@ def getsiscale(unit, type):
idx = unit.rfind('s')
if idx == -1:
idx = len(unit)
-
+
elif type == 'angle':
idx = len(unit)
-
+
elif type == 'frequency':
idx = len(unit) - 1
-
+
else:
idx = len(unit) - len(type) + 1
-
+
idx = idx
prefix = unit[:idx]
-
+
if not prefix:
scl = 1.0
else:
prefix = prefix.lower()
scl = 1.0
-
+
if prefix == 'pico' or prefix == 'p':
scl = 1.0e-12
elif prefix == 'nano' or prefix == 'n':
@@ -162,10 +162,10 @@ def getsiscale(unit, type):
else:
if prefix:
raise ValueError('Unknown prefix {}'.format(prefix))
-
+
if type == 'area':
scl = scl ** 2.0
elif type == 'volume':
scl = scl ** 3.0
-
+
return scl
diff --git a/pyfus/xdc/__init__.py b/src/openlifu/xdc/__init__.py
similarity index 68%
rename from pyfus/xdc/__init__.py
rename to src/openlifu/xdc/__init__.py
index 70fdfd99..fd1bd724 100644
--- a/pyfus/xdc/__init__.py
+++ b/src/openlifu/xdc/__init__.py
@@ -1,4 +1,4 @@
from . import element
from . import transducer
from .element import Element
-from .transducer import Transducer
\ No newline at end of file
+from .transducer import Transducer
diff --git a/pyfus/xdc/element.py b/src/openlifu/xdc/element.py
similarity index 93%
rename from pyfus/xdc/element.py
rename to src/openlifu/xdc/element.py
index 8f86aa6f..0e7fa70c 100644
--- a/pyfus/xdc/element.py
+++ b/src/openlifu/xdc/element.py
@@ -1,7 +1,7 @@
import numpy as np
-from pyfus.util.units import getunitconversion
+from openlifu.util.units import getunitconversion
from dataclasses import dataclass, field
-from collections.abc import Iterable
+from collections.abc import Iterable
from typing import List, Dict, Any, Tuple
import copy
@@ -163,7 +163,7 @@ def angle_to_point(self, point, units=None, return_as="rad", matrix=np.eye(4)):
if return_as == "deg":
theta = np.degrees(theta)
return theta
-
+
def set_matrix(self, matrix, units=None):
if units is not None:
self.rescale(units)
@@ -176,18 +176,18 @@ def set_matrix(self, matrix, units=None):
self.roll = roll
def to_dict(self):
- return {"index": self.index,
- "x": self.x,
- "y": self.y,
- "z": self.z,
- "az": self.az,
- "el": self.el,
- "roll": self.roll,
- "w": self.w,
- "l": self.l,
- "impulse_response": self.impulse_response.tolist(),
- "impulse_dt": self.impulse_dt,
- "pin": self.pin,
+ return {"index": self.index,
+ "x": self.x,
+ "y": self.y,
+ "z": self.z,
+ "az": self.az,
+ "el": self.el,
+ "roll": self.roll,
+ "w": self.w,
+ "l": self.l,
+ "impulse_response": self.impulse_response.tolist(),
+ "impulse_dt": self.impulse_dt,
+ "pin": self.pin,
"units": self.units}
@staticmethod
diff --git a/pyfus/xdc/transducer.py b/src/openlifu/xdc/transducer.py
similarity index 96%
rename from pyfus/xdc/transducer.py
rename to src/openlifu/xdc/transducer.py
index 5c31a051..88f3e395 100644
--- a/pyfus/xdc/transducer.py
+++ b/src/openlifu/xdc/transducer.py
@@ -1,9 +1,9 @@
import numpy as np
import pandas as pd
-from pyfus.util.units import getunitconversion
+from openlifu.util.units import getunitconversion
from dataclasses import dataclass, field
-from collections.abc import Iterable
+from collections.abc import Iterable
from typing import List, Dict, Any, Tuple
import vtk
import logging
@@ -28,7 +28,7 @@ def __post_init__(self):
self.matrix = np.array(self.matrix, dtype=np.float64)
for element in self.elements:
element.rescale(self.units)
-
+
def calc_output(self, input_signal, dt, delays: np.ndarray = None, apod: np.ndarray = None):
if delays is None:
delays = np.zeros(self.numelements())
@@ -40,14 +40,14 @@ def calc_output(self, input_signal, dt, delays: np.ndarray = None, apod: np.ndar
for i, o in enumerate(outputs):
output_signal[i, :len(o)] = o
return output_signal
-
+
def copy(self):
return copy.deepcopy(self)
- def draw(self,
- units=None,
- transform=True,
- facecolor=[0,1,1],
+ def draw(self,
+ units=None,
+ transform=True,
+ facecolor=[0,1,1],
facealpha=0.5):
units = self.units if units is None else units
actor = self.get_actor(units=units, transform=transform, facecolor=facecolor, facealpha=facealpha)
@@ -116,7 +116,7 @@ def get_corners(self, transform=True, units=None):
else:
matrix = np.eye(4)
return [element.get_corners(units=units, matrix=matrix) for element in self.elements]
-
+
def get_positions(self, transform=True, units=None):
units = self.units if units is None else units
if transform:
@@ -154,7 +154,7 @@ def merge(list_of_transducers):
xform_array.transform(np.dot(np.linalg.inv(arr.get_matrix()),ref_matrix), transform_elements=True)
merged_array.elements += xform_array.elements
return merged_array
-
+
def numelements(self):
return len(self.elements)
@@ -165,15 +165,15 @@ def rescale(self, units):
scl = getunitconversion(self.units, units)
self.matrix[0:3, 3] *= scl
self.units = units
-
+
def to_dict(self):
d = self.__dict__.copy()
d["elements"] = [element.to_dict() for element in d["elements"]]
d["matrix"] = d["matrix"].tolist()
return d
-
+
def to_file(self, filename):
- from pyfus.util.json import to_json
+ from openlifu.util.json import to_json
to_json(self.to_dict(), filename)
def transform(self, matrix, units=None, transform_elements: bool=False):
@@ -221,6 +221,3 @@ def gen_matrix_array(nx=2, ny=2, pitch=1, kerf=0, units="mm", impulse_response=1
units=units
))
return Transducer(elements=elements, id=id, name=name, attrs=attrs)
-
-
-