Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/OpenGATE/opengate into im…
Browse files Browse the repository at this point in the history
…plement_dynamic_parametrisation
  • Loading branch information
nkrah committed Jan 12, 2024
2 parents 96bba80 + 7aaceda commit abaefa1
Show file tree
Hide file tree
Showing 56 changed files with 1,407 additions and 189 deletions.
21 changes: 10 additions & 11 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-11, windows-latest]
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: [3.8, 3.9, '3.10', '3.11']
exclude:
- os: macos-11
- os: macos-latest
python-version: '3.11'

env:
Expand All @@ -36,7 +36,7 @@ jobs:
if [[ ${{ matrix.os }} == "ubuntu-latest" ]]; then
export GIT_SSL_NO_VERIFY=1
git submodule update --init --recursive
elif [[ ${{ matrix.os }} == "macos-11" ]]; then
elif [[ ${{ matrix.os }} == "macos-latest" ]]; then
export GIT_SSL_NO_VERIFY=1
git submodule update --init --recursive
else
Expand All @@ -56,7 +56,7 @@ jobs:
varOS=`cat /etc/os-release | grep "VERSION=" | grep -oP '(?<=\").*?(?=\")'`
varOS=($varOS)
echo "release=${varOS[0]}" >> $GITHUB_OUTPUT
elif [[ ${{ matrix.os }} == "macos-11" ]]; then
elif [[ ${{ matrix.os }} == "macos-latest" ]]; then
varOS=`sw_vers | grep "ProductVersion:"`
varOS="${varOS#*:}"
echo "release=${varOS:1}" >> $GITHUB_OUTPUT
Expand Down Expand Up @@ -106,22 +106,22 @@ jobs:
mv dist_opengate/* dist/
fi
- uses: conda-incubator/setup-miniconda@v2
if: (matrix.os == 'macos-11') || (matrix.os == 'windows-latest')
if: (matrix.os == 'macos-latest') || (matrix.os == 'windows-latest')
with:
auto-update-conda: true
activate-environment: opengate_core
python-version: ${{ matrix.python-version }}
- name: Set up Homebrew
if: matrix.os == 'macos-11'
if: matrix.os == 'macos-latest'
id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master
- name: Create opengate_core Wheel Mac
if: matrix.os == 'macos-11'
if: matrix.os == 'macos-latest'
shell: bash -l {0}
run: |
brew update
rm -rf /usr/local/bin/python3.1*-config /usr/local/bin/2to3-3.1* /usr/local/bin/idle3.1* /usr/local/bin/pydoc3.1* /usr/local/bin/python3.1*
rm -rf /usr/local/bin/python3-config /usr/local/bin/2to3 /usr/local/bin/idle3 /usr/local/bin/pydoc3 /usr/local/bin/python3
#rm -rf /usr/local/bin/python3.1*-config /usr/local/bin/2to3-3.1* /usr/local/bin/idle3.1* /usr/local/bin/pydoc3.1* /usr/local/bin/python3.1*
#rm -rf /usr/local/bin/python3-config /usr/local/bin/2to3 /usr/local/bin/idle3 /usr/local/bin/pydoc3 /usr/local/bin/python3
brew install --force --verbose --overwrite \
ccache \
fftw \
Expand Down Expand Up @@ -363,8 +363,7 @@ jobs:
pip install torch
fi
pip install SimpleITK
pip install gaga_phsp
pip install garf
pip install gaga_phsp==0.7.1
pip install dist/opengate_core-*-${PYTHONFOLDER}-${OSNAME}*_${PLATFORM}64.whl
pip install dist/opengate-*.whl
export GIT_SSL_NO_VERIFY=1
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/psf/black
rev: 23.12.0
rev: 23.12.1
hooks:
- id: black
- repo: https://github.com/pre-commit/mirrors-clang-format
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
10.0beta06
10.0beta07
28 changes: 21 additions & 7 deletions core/opengate_core/opengate_lib/GateARFActor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ GateARFActor::GateARFActor(py::dict &user_info) : GateVActor(user_info, true) {
fActions.insert("EndOfRunAction");
// User option: batch size
fBatchSize = DictGetInt(user_info, "batch_size");
fKeepNegativeSide = DictGetBool(user_info, "flip_plane");
}

void GateARFActor::SetARFFunction(ARFFunctionType &f) { fApply = f; }
Expand All @@ -36,17 +37,31 @@ void GateARFActor::EndOfRunAction(const G4Run * /*run*/) {
l.fPositionY.clear();
l.fDirectionX.clear();
l.fDirectionY.clear();
l.fDirectionZ.clear();
l.fCurrentNumberOfHits = 0;
}
}

void GateARFActor::SteppingAction(G4Step *step) {
auto &l = fThreadLocalData.Get();

// get direction and transform to local
auto *pre = step->GetPreStepPoint();
auto dir = pre->GetMomentumDirection();
dir = pre->GetTouchable()->GetHistory()->GetTopTransform().TransformAxis(dir);

// which side of the plane ?
if (!fKeepNegativeSide && dir[2] < 0)
return;
if (fKeepNegativeSide && dir[2] > 0)
return;

l.fCurrentNumberOfHits++;
l.fDirectionX.push_back(dir[0]);
l.fDirectionY.push_back(dir[1]);
// l.fDirectionZ.push_back(dir[2]); // not used

// get energy
auto *pre = step->GetPreStepPoint();
l.fEnergy.push_back(pre->GetKineticEnergy());

// get position and transform to local
Expand All @@ -56,12 +71,6 @@ void GateARFActor::SteppingAction(G4Step *step) {
l.fPositionX.push_back(pos[0]);
l.fPositionY.push_back(pos[1]);

// get direction and transform to local
auto dir = pre->GetMomentumDirection();
dir = pre->GetTouchable()->GetHistory()->GetTopTransform().TransformAxis(dir);
l.fDirectionX.push_back(dir[0]);
l.fDirectionY.push_back(dir[1]);

// trigger the "apply" (ARF) if the number of hits in the batch is reached
if (l.fCurrentNumberOfHits >= fBatchSize) {
fApply(this);
Expand All @@ -70,6 +79,7 @@ void GateARFActor::SteppingAction(G4Step *step) {
l.fPositionY.clear();
l.fDirectionX.clear();
l.fDirectionY.clear();
l.fDirectionZ.clear();
l.fCurrentNumberOfHits = 0;
}
}
Expand Down Expand Up @@ -101,3 +111,7 @@ std::vector<double> GateARFActor::GetDirectionX() const {
std::vector<double> GateARFActor::GetDirectionY() const {
return fThreadLocalData.Get().fDirectionY;
}

std::vector<double> GateARFActor::GetDirectionZ() const {
return fThreadLocalData.Get().fDirectionZ;
}
4 changes: 4 additions & 0 deletions core/opengate_core/opengate_lib/GateARFActor.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class GateARFActor : public GateVActor {

std::vector<double> GetDirectionY() const;

std::vector<double> GetDirectionZ() const;

// Main function called every step in attached volume
void SteppingAction(G4Step *) override;

Expand All @@ -52,6 +54,7 @@ class GateARFActor : public GateVActor {
protected:
int fBatchSize;
ARFFunctionType fApply;
bool fKeepNegativeSide;

// For MT, all threads local variables are gathered here
struct threadLocalT {
Expand All @@ -60,6 +63,7 @@ class GateARFActor : public GateVActor {
std::vector<double> fPositionY;
std::vector<double> fDirectionX;
std::vector<double> fDirectionY;
std::vector<double> fDirectionZ;
// number of particle hitting the detector
int fCurrentNumberOfHits;
// Current run id (to detect if run has changed)
Expand Down
1 change: 1 addition & 0 deletions core/opengate_core/opengate_lib/GateGANSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ G4ThreeVector GateGANSource::GeneratePrimariesPosition() {
position =
G4ThreeVector(fPositionX[fCurrentIndex], fPositionY[fCurrentIndex],
fPositionZ[fCurrentIndex]);
position = fLocalRotation * position + fLocalTranslation; // FIXME
// move position according to mother volume
auto &l = fThreadLocalData.Get();
position = l.fGlobalRotation * position + l.fGlobalTranslation;
Expand Down
6 changes: 5 additions & 1 deletion core/opengate_core/opengate_lib/GateHelpersGeometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ void ComputeTransformationFromVolumeToWorld(const std::string &phys_volume_name,
auto rot = phys->GetObjectRotationValue();
rotation = rot * rotation;
translation = rot * translation + tr;
name = phys->GetMotherLogical()->GetName();
// Warning, the world can be a parallel world
if (phys->GetMotherLogical() == nullptr)
name = "world";
else
name = phys->GetMotherLogical()->GetName();
}
}

Expand Down
3 changes: 2 additions & 1 deletion core/opengate_core/opengate_lib/pyGateARFActor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ void init_GateARFActor(py::module &m) {
.def("GetPositionX", &GateARFActor::GetPositionX)
.def("GetPositionY", &GateARFActor::GetPositionY)
.def("GetDirectionX", &GateARFActor::GetDirectionX)
.def("GetDirectionY", &GateARFActor::GetDirectionY);
.def("GetDirectionY", &GateARFActor::GetDirectionY)
.def("GetDirectionZ", &GateARFActor::GetDirectionZ);
}
2 changes: 1 addition & 1 deletion core/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ def build_extension(self, ext):
packages=find_packages(),
package_data=package_data,
zip_safe=False,
python_requires=">=3.5",
python_requires=">=3.8",
include_package_data=True,
classifiers=(
"Programming Language :: Python :: 3",
Expand Down
6 changes: 3 additions & 3 deletions docs/source/developer_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ For **ITK**, you need to compile with the following options:

```bash
git clone --branch v5.2.1 https://github.com/InsightSoftwareConsortium/ITK.git --depth 1
mkdir build-v5.2.1
cd build-v5.2.1
mkdir itk-build
cd itk-build
cmake -DCMAKE_CXX_FLAGS=-std=c++17 \
-DBUILD_TESTING=OFF \
-DITK_USE_FFTWD=ON \
Expand All @@ -76,7 +76,7 @@ Once it is done, you can compile `opengate_core`.
```bash
pip install colored
cd <path-to-opengate>/core
export CMAKE_PREFIX_PATH=<path-to>/geant4.11-build/:<path-to>/build-v5.1.0/:${CMAKE_PREFIX_PATH}
export CMAKE_PREFIX_PATH=<path-to>/geant4.11-build/:<path-to>/itk-build/:${CMAKE_PREFIX_PATH}
pip install -e . -v
```

Expand Down
36 changes: 23 additions & 13 deletions opengate/actors/arfactors.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def import_garf():
from packaging import version

garf_version = pkg_resources.get_distribution("garf").version
garf_minimal_version = "2.4"
garf_minimal_version = "2.5"
if version.parse(garf_version) < version.parse(garf_minimal_version):
fatal(
"The minimal version of garf is not correct. You should install at least the version "
Expand Down Expand Up @@ -105,13 +105,16 @@ def set_default_user_info(user_info):
user_info.verbose_batch = False
user_info.output = ""
user_info.enable_hit_slice = False
user_info.flip_plane = False
# Can be cpu / auto / gpu
user_info.gpu_mode = "auto"

def __init__(self, user_info):
ActorBase.__init__(self, user_info)
g4.GateARFActor.__init__(self, user_info.__dict__)
# import module
self.debug_nb_hits_before = None
self.debug_nb_hits = 0
self.garf = import_garf()
if self.garf is None:
print("Cannot run GANSource")
Expand Down Expand Up @@ -152,13 +155,17 @@ def initialize(self, volume_engine=None):
self.ActorInitialize()
self.SetARFFunction(self.apply)
self.user_info.output_image = None
self.debug_nb_hits_before = 0
self.debug_nb_hits = 0

# load the pth file
self.nn, self.model = self.garf.load_nn(self.pth_filename, verbose=False)
p = self.param
p.batch_size = int(float(self.user_info.batch_size))

# size and spacing (2D)
# size and spacing (2D) (force to float)
self.user_info.image_spacing[0] = float(self.user_info.image_spacing[0])
self.user_info.image_spacing[1] = float(self.user_info.image_spacing[1])
p.image_size = self.user_info.image_size
p.image_spacing = self.user_info.image_spacing
p.distance_to_crystal = self.user_info.distance_to_crystal
Expand Down Expand Up @@ -223,13 +230,15 @@ def apply_with_lock(self, actor):

# build the data
x = np.column_stack((px, py, theta, phi, energy))
self.debug_nb_hits_before += len(x)

# apply the neural network
if self.user_info.verbose_batch:
print(
f"Apply ARF to {energy.shape[0]} hits (device = {self.model_data['current_gpu_mode']})"
)
ax = x[:, 2:5] # two angles and energy

ax = x[:, 2:5] # two angles and energy # FIXME index ?
w = self.garf.nn_predict(self.model, self.nn["model_data"], ax)

# positions
Expand All @@ -242,20 +251,17 @@ def apply_with_lock(self, actor):
coord = np.around(coord).astype(int)
v = coord[:, 0]
u = coord[:, 1]
u, v, w_pred = self.garf.remove_out_of_image_boundaries(u, v, w, p.image_size)
u, v, w_pred = self.garf.remove_out_of_image_boundaries2(
u, v, w, self.user_info.image_size
)

# do nothing if there is no hit in the image
if u.shape[0] != 0:
temp = np.zeros(p.image_size, dtype=np.float64)
temp = self.garf.image_from_coordinates(temp, u, v, w_pred)
# add to previous, at the correct slice location
# the slice is : current_ene_window + run_id * nb_ene_windows
run_id = actor.GetCurrentRunId()
# self.simulation_engine_wr().g4_RunManager.GetCurrentRun().GetRunID()
s = p.nb_ene * run_id
self.output_image[s : s + p.nb_ene] = (
self.output_image[s : s + p.nb_ene] + temp
)
img = self.output_image[s : s + p.nb_ene]
self.garf.image_from_coordinates_add(img, u, v, w_pred)
self.debug_nb_hits += u.shape[0]

def EndSimulationAction(self):
g4.GateARFActor.EndSimulationAction(self)
Expand All @@ -265,7 +271,7 @@ def EndSimulationAction(self):
# Should we keep the first slice (with all hits) ?
if not self.user_info.enable_hit_slice:
self.output_image = self.output_image[1:, :, :]
self.param.image_size[1] = self.param.image_size[1] - 1
self.param.image_size[0] = self.param.image_size[0] - 1

# convert to itk image
self.output_image = itk.image_from_array(self.output_image)
Expand Down Expand Up @@ -294,3 +300,7 @@ def EndSimulationAction(self):
itk.imwrite(
self.output_image, ensure_filename_is_str(self.user_info.output)
)

# debug
# print(f"{self.debug_nb_hits_before=}")
# print(f"{self.debug_nb_hits=}")
2 changes: 1 addition & 1 deletion opengate/actors/doseactors.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ def EndSimulationAction(self):
)
itk.imwrite(self.py_LETd_image, ensure_filename_is_str(fPath))

# for parrallel computation we need to provide both outputs
# for parallel computation we need to provide both outputs
if self.user_info.separate_output:
fPath = fPath.replace(".mhd", "_numerator.mhd")
itk.imwrite(self.py_numerator_image, ensure_filename_is_str(fPath))
Expand Down
Loading

0 comments on commit abaefa1

Please sign in to comment.