Skip to content

Commit 4bfb868

Browse files
authored
Merge pull request #1892 from SCIInstitute/macro-toolbar
Macro toolbar, plus multiple bug fixes
2 parents cbdd7ef + 71c8497 commit 4bfb868

38 files changed

+1453
-665
lines changed

.travis.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ matrix:
2626
- os: osx
2727
osx_image: xcode9.3
2828
env: PYTHON_VERSION=3.4.3 OSPRAY_BUILD=OFF
29+
- os: osx
30+
osx_image: xcode10.1
31+
env: PYTHON_VERSION=3.4.3 OSPRAY_BUILD=OFF
2932
- os: osx
3033
osx_image: xcode7.2
3134
env: PYTHON_VERSION=3.5.6 OSPRAY_BUILD=OFF
@@ -35,6 +38,9 @@ matrix:
3538
- os: osx
3639
osx_image: xcode9.3
3740
env: PYTHON_VERSION=3.5.6 OSPRAY_BUILD=OFF
41+
- os: osx
42+
osx_image: xcode10.1
43+
env: PYTHON_VERSION=3.5.6 OSPRAY_BUILD=OFF
3844
- os: osx
3945
osx_image: xcode7.2
4046
env: PYTHON_VERSION=3.6.7 OSPRAY_BUILD=OFF
@@ -44,6 +50,9 @@ matrix:
4450
- os: osx
4551
osx_image: xcode9.3
4652
env: PYTHON_VERSION=3.6.7 OSPRAY_BUILD=OFF
53+
- os: osx
54+
osx_image: xcode10.1
55+
env: PYTHON_VERSION=3.6.7 OSPRAY_BUILD=OFF
4756

4857
before_install:
4958
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then date -u; fi

Superbuild/UseBoost.cmake

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,20 @@ foreach(lib ${SCI_BOOST_LIBRARY})
3434
if(${lib} MATCHES "boost_python-mt")
3535
if(WIN32)
3636
set(FULL_LIB_NAME_RELEASE "${SCI_BOOST_LIBRARY_DIR}/${boost_LIB_PREFIX}boost_python${USER_PYTHON_VERSION_MAJOR}${USER_PYTHON_VERSION_MINOR}-mt${CMAKE_STATIC_LIBRARY_SUFFIX}")
37+
set(FULL_LIB_NAME_DEBUG "${SCI_BOOST_LIBRARY_DIR}/${boost_LIB_PREFIX}boost_python${USER_PYTHON_VERSION_MAJOR}${USER_PYTHON_VERSION_MINOR}-mt${DEBUG_POSTFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}")
3738
else()
3839
if (${USER_PYTHON_VERSION} VERSION_GREATER "3.7")
3940
set(FULL_LIB_NAME_RELEASE "${SCI_BOOST_LIBRARY_DIR}/${boost_LIB_PREFIX}boost_python${USER_PYTHON_VERSION_MAJOR}${USER_PYTHON_VERSION_MINOR}-mt${CMAKE_STATIC_LIBRARY_SUFFIX}")
41+
set(FULL_LIB_NAME_DEBUG "${SCI_BOOST_LIBRARY_DIR}/${boost_LIB_PREFIX}boost_python${USER_PYTHON_VERSION_MAJOR}${USER_PYTHON_VERSION_MINOR}-mt${DEBUG_POSTFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}")
4042
else()
4143
set(FULL_LIB_NAME_RELEASE "${SCI_BOOST_LIBRARY_DIR}/${boost_LIB_PREFIX}boost_python3-mt${CMAKE_STATIC_LIBRARY_SUFFIX}")
44+
set(FULL_LIB_NAME_DEBUG "${SCI_BOOST_LIBRARY_DIR}/${boost_LIB_PREFIX}boost_python3-mt${DEBUG_POSTFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}")
4245
endif()
4346
endif()
4447
else()
4548
set(FULL_LIB_NAME_RELEASE "${SCI_BOOST_LIBRARY_DIR}/${boost_LIB_PREFIX}${lib}${CMAKE_STATIC_LIBRARY_SUFFIX}")
49+
set(FULL_LIB_NAME_DEBUG "${SCI_BOOST_LIBRARY_DIR}/${boost_LIB_PREFIX}${lib}${DEBUG_POSTFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}")
4650
endif()
47-
48-
set(FULL_LIB_NAME_DEBUG "${SCI_BOOST_LIBRARY_DIR}/${boost_LIB_PREFIX}${lib}${DEBUG_POSTFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}")
4951
endif()
5052

5153
message(STATUS "Configure Boost library ${lib}")

src/Core/Algorithms/Field/Tests/CMakeLists.txt

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
#
22
# For more information, please see: http://software.sci.utah.edu
3-
#
3+
#
44
# The MIT License
5-
#
5+
#
66
# Copyright (c) 2015 Scientific Computing and Imaging Institute,
77
# University of Utah.
8-
#
9-
#
8+
#
9+
#
1010
# Permission is hereby granted, free of charge, to any person obtaining a
1111
# copy of this software and associated documentation files (the "Software"),
1212
# to deal in the Software without restriction, including without limitation
1313
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
1414
# and/or sell copies of the Software, and to permit persons to whom the
1515
# Software is furnished to do so, subject to the following conditions:
16-
#
16+
#
1717
# The above copyright notice and this permission notice shall be included
18-
# in all copies or substantial portions of the Software.
19-
#
18+
# in all copies or substantial portions of the Software.
19+
#
2020
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2121
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2222
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -57,12 +57,14 @@ SET(Algorithms_Field_Tests_SRCS
5757
SetComplexFieldDataTests.cc
5858
RemoveUnusedNodesTests.cc
5959
CleanupTetMeshTests.cc
60+
GenerateStreamLinesTests.cc
6061
)
6162

6263
SCIRUN_ADD_UNIT_TEST(Algorithms_Field_Tests
6364
${Algorithms_Field_Tests_SRCS}
6465
)
6566

67+
6668
TARGET_LINK_LIBRARIES(Algorithms_Field_Tests
6769
Algorithms_DataIO
6870
Algorithms_Field
Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
/*
2+
For more information, please see: http://software.sci.utah.edu
3+
4+
The MIT License
5+
6+
Copyright (c) 2019 Scientific Computing and Imaging Institute,
7+
University of Utah.
8+
9+
Permission is hereby granted, free of charge, to any person obtaining a
10+
copy of this software and associated documentation files (the "Software"),
11+
to deal in the Software without restriction, including without limitation
12+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
13+
and/or sell copies of the Software, and to permit persons to whom the
14+
Software is furnished to do so, subject to the following conditions:
15+
16+
The above copyright notice and this permission notice shall be included
17+
in all copies or substantial portions of the Software.
18+
19+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22+
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25+
DEALINGS IN THE SOFTWARE.
26+
*/
27+
28+
#include <gtest/gtest.h>
29+
30+
#include <Core/Datatypes/Legacy/Field/VField.h>
31+
#include <Core/Datatypes/Legacy/Field/FieldInformation.h>
32+
#include <Core/Datatypes/Matrix.h>
33+
#include <Core/Algorithms/Legacy/Fields/StreamLines/GenerateStreamLines.h>
34+
#include <Testing/Utils/SCIRunUnitTests.h>
35+
#include <Core/Datatypes/DenseMatrix.h>
36+
#include <Core/Algorithms/Base/AlgorithmPreconditions.h>
37+
#include <Testing/Utils/MatrixTestUtilities.h>
38+
#include <Core/Datatypes/DenseMatrix.h>
39+
40+
using namespace SCIRun;
41+
using namespace SCIRun::Core::Datatypes;
42+
using namespace SCIRun::Core::Geometry;
43+
using namespace SCIRun::Core::Algorithms::Fields;
44+
using namespace SCIRun::TestUtils;
45+
46+
FieldHandle LoadMultiSeeds()
47+
{
48+
return loadFieldFromFile(TestResources::rootDir() / "Fields/streamlines/multiSeeds.fld");
49+
}
50+
51+
FieldHandle LoadSingleSeed()
52+
{
53+
return loadFieldFromFile(TestResources::rootDir() / "Fields/streamlines/singleSeed.fld");
54+
}
55+
56+
FieldHandle LoadTorsoSeeds()
57+
{
58+
return loadFieldFromFile(TestResources::rootDir() / "Fields/seedPointsFromTorso.fld");
59+
}
60+
61+
FieldHandle LoadTorso()
62+
{
63+
return loadFieldFromFile(TestResources::rootDir() / "Fields/utahtorso-lowres/gradient.fld");
64+
}
65+
66+
FieldHandle LoadVectorField()
67+
{
68+
return loadFieldFromFile(TestResources::rootDir() / "Fields/streamlines/vectorField.fld");
69+
}
70+
71+
static std::vector<std::string> methods { "AdamsBashforth", "Heun", "RungeKutta",
72+
"RungeKuttaFehlberg", "CellWalk" };
73+
74+
TEST(GenerateStreamLinesTests, SingleSeedProducesSinglePositiveStreamlineSingleThreaded)
75+
{
76+
auto singleSeed = LoadSingleSeed();
77+
auto vectorField = LoadVectorField();
78+
79+
for (const auto& method : methods)
80+
{
81+
GenerateStreamLinesAlgo algo;
82+
FieldHandle output;
83+
84+
//std::cout << "method: " << method << std::endl;
85+
algo.set(Parameters::UseMultithreading, false);
86+
algo.setOption(Parameters::StreamlineValue, "Distance from seed");
87+
algo.setOption(Parameters::StreamlineMethod, method);
88+
89+
algo.runImpl(vectorField, singleSeed, output);
90+
91+
EXPECT_GT(output->vmesh()->num_nodes(), 0);
92+
EXPECT_GT(output->vmesh()->num_elems(), 0);
93+
EXPECT_GT(output->vfield()->num_values(), 0);
94+
95+
double min,max;
96+
output->vfield()->minmax(min, max);
97+
//std::cout << min << " " << max << std::endl;
98+
99+
// streamlines contained within 8x8x8 latvol
100+
EXPECT_EQ(min, 0.0);
101+
if (method == "AdamsBashforth")
102+
EXPECT_LT(max, 65.0); // corkscrew streamlines
103+
else
104+
EXPECT_LT(max, 12.0);
105+
}
106+
}
107+
108+
TEST(GenerateStreamLinesTests, SingleSeedProducesSinglePositiveStreamlineMultiThreaded)
109+
{
110+
auto singleSeed = LoadSingleSeed();
111+
auto vectorField = LoadVectorField();
112+
113+
for (const auto& method : methods)
114+
{
115+
GenerateStreamLinesAlgo algo;
116+
FieldHandle output;
117+
118+
algo.set(Parameters::UseMultithreading, true);
119+
algo.setOption(Parameters::StreamlineValue, "Distance from seed");
120+
algo.setOption(Parameters::StreamlineMethod, method);
121+
122+
algo.runImpl(vectorField, singleSeed, output);
123+
124+
EXPECT_GT(output->vmesh()->num_nodes(), 0);
125+
EXPECT_GT(output->vmesh()->num_elems(), 0);
126+
EXPECT_GT(output->vfield()->num_values(), 0);
127+
128+
double min,max;
129+
output->vfield()->minmax(min, max);
130+
//std::cout << min << " " << max << std::endl;
131+
132+
// streamlines contained within 8x8x8 latvol
133+
EXPECT_EQ(min, 0.0);
134+
if (method == "AdamsBashforth")
135+
EXPECT_LT(max, 65.0); // corkscrew streamlines
136+
else
137+
EXPECT_LT(max, 12.0);
138+
}
139+
}
140+
141+
//TODO: use > 16 seeds to force multithreading
142+
TEST(GenerateStreamLinesTests, MultipleSeedsProducesMultipleStreamlinesSingleThreaded)
143+
{
144+
auto multiSeeds = LoadMultiSeeds();
145+
auto vectorField = LoadVectorField();
146+
147+
for (const auto& method : methods)
148+
{
149+
GenerateStreamLinesAlgo algo;
150+
FieldHandle output;
151+
152+
algo.set(Parameters::UseMultithreading, false);
153+
algo.setOption(Parameters::StreamlineValue, "Distance from seed");
154+
algo.setOption(Parameters::StreamlineMethod, method);
155+
156+
algo.runImpl(vectorField, multiSeeds, output);
157+
158+
EXPECT_GT(output->vmesh()->num_nodes(), 0);
159+
EXPECT_GT(output->vmesh()->num_elems(), 0);
160+
EXPECT_GT(output->vfield()->num_values(), 0);
161+
162+
double min,max;
163+
output->vfield()->minmax(min, max);
164+
//std::cout << min << " " << max << std::endl;
165+
166+
// streamlines contained within 8x8x8 latvol
167+
EXPECT_EQ(min, 0.0);
168+
if (method == "AdamsBashforth")
169+
EXPECT_LT(max, 93.0); // corkscrew streamlines
170+
else
171+
EXPECT_LT(max, 17.0);
172+
}
173+
}
174+
175+
TEST(GenerateStreamLinesTests, MultipleSeedsProducesMultipleStreamlinesMultiThreaded)
176+
{
177+
auto multiSeeds = LoadMultiSeeds();
178+
auto vectorField = LoadVectorField();
179+
180+
for (const auto& method : methods)
181+
{
182+
GenerateStreamLinesAlgo algo;
183+
FieldHandle output;
184+
185+
algo.set(Parameters::UseMultithreading, true);
186+
algo.setOption(Parameters::StreamlineValue, "Distance from seed");
187+
algo.setOption(Parameters::StreamlineMethod, method);
188+
189+
algo.runImpl(vectorField, multiSeeds, output);
190+
191+
EXPECT_GT(output->vmesh()->num_nodes(), 0);
192+
EXPECT_GT(output->vmesh()->num_elems(), 0);
193+
EXPECT_GT(output->vfield()->num_values(), 0);
194+
195+
double min,max;
196+
output->vfield()->minmax(min, max);
197+
//std::cout << min << " " << max << std::endl;
198+
199+
// streamlines contained within 8x8x8 latvol
200+
EXPECT_EQ(min, 0.0);
201+
if (method == "AdamsBashforth")
202+
EXPECT_LT(max, 93.0); // corkscrew streamlines
203+
else
204+
EXPECT_LT(max, 17.0);
205+
}
206+
}
207+
208+
static std::map<std::string, std::vector<int>> meshOutputByMethod
209+
{ { "AdamsBashforth", {400617, 399617, 400617} },
210+
{ "Heun", {400617, 399617, 400617} },
211+
{ "RungeKutta", {400617, 399617, 400617} },
212+
{ "RungeKuttaFehlberg", {214100, 213100, 214100} },
213+
{ "CellWalk", {98120, 97120, 98120} }
214+
};
215+
216+
TEST(GenerateStreamLinesTests, ManySeedsMultithreaded)
217+
{
218+
auto torsoSeeds = LoadTorsoSeeds();
219+
auto torso = LoadTorso();
220+
221+
for (const auto& method : methods)
222+
{
223+
GenerateStreamLinesAlgo algo;
224+
FieldHandle output;
225+
226+
algo.set(Parameters::UseMultithreading, true);
227+
algo.set(Parameters::StreamlineMaxSteps, 200);
228+
algo.setOption(Parameters::StreamlineValue, "Distance from seed");
229+
algo.setOption(Parameters::StreamlineMethod, method);
230+
231+
//std::cout << "processing real streamlines using " << method << " method." << std::endl;
232+
algo.runImpl(torso, torsoSeeds, output);
233+
234+
EXPECT_GT(output->vmesh()->num_nodes(), 0);
235+
EXPECT_GT(output->vmesh()->num_elems(), 0);
236+
EXPECT_GT(output->vfield()->num_values(), 0);
237+
238+
EXPECT_EQ(output->vmesh()->num_nodes(), meshOutputByMethod[method][0]);
239+
EXPECT_EQ(output->vmesh()->num_elems(), meshOutputByMethod[method][1]);
240+
EXPECT_EQ(output->vfield()->num_values(), meshOutputByMethod[method][2]);
241+
242+
double min,max;
243+
output->vfield()->minmax(min, max);
244+
//std::cout << min << " " << max << std::endl;
245+
246+
// streamlines contained within mesh with greatest dimension <= 600
247+
EXPECT_EQ(min, 0.0);
248+
if (method == "AdamsBashforth")
249+
EXPECT_LT(max, 6300.0); // corkscrew streamlines
250+
else if (method == "CellWalk")
251+
EXPECT_LT(max, 2900.0);
252+
else
253+
EXPECT_LT(max, 600.0);
254+
}
255+
}
256+
257+
static std::map<std::string, std::pair<double,double>> meshOutputByMethodTotalLength
258+
{ { "AdamsBashforth", {0.0269025, 6260.01} },
259+
{ "Heun", {0.0269025, 517.404} },
260+
{ "RungeKutta", {0.0269025, 476.269} },
261+
{ "RungeKuttaFehlberg", {0.767026, 127.16} },
262+
{ "CellWalk", {0.0, 2861.98} }
263+
};
264+
265+
TEST(GenerateStreamLinesTests, ManySeedsMultithreadedStreamlineLength)
266+
{
267+
auto torsoSeeds = LoadTorsoSeeds();
268+
auto torso = LoadTorso();
269+
270+
for (const auto& method : methods)
271+
{
272+
GenerateStreamLinesAlgo algo;
273+
FieldHandle output;
274+
275+
algo.set(Parameters::UseMultithreading, true);
276+
algo.set(Parameters::StreamlineMaxSteps, 200);
277+
algo.setOption(Parameters::StreamlineValue, "Streamline length");
278+
algo.setOption(Parameters::StreamlineMethod, method);
279+
280+
//std::cout << "processing real streamlines using " << method << " method." << std::endl;
281+
algo.runImpl(torso, torsoSeeds, output);
282+
283+
double min,max;
284+
output->vfield()->minmax(min, max);
285+
//std::cout << min << " " << max << std::endl;
286+
EXPECT_NEAR(min, meshOutputByMethodTotalLength[method].first, 1e-2);
287+
EXPECT_NEAR(max, meshOutputByMethodTotalLength[method].second, 1e-1);
288+
}
289+
}

0 commit comments

Comments
 (0)