## SciVis 2017 Project 5: "tensr"

## Assigned March 8; Due Wed March 15 at 11:59pm

For this project, you will implement 2-D symmetric field convolution, integration along eigenvectors, and Line Integral Convolution (LIC).## Logistics

The usual ...Like in p4vectr, if you want to compile your code without the

-O2optimization, you can:Compiling without optimization may produce an executable that is easier to debug.export DASHO=-O0 make clean; makeLike in earlier projects, there is a

tnsVerboseglobal variable that you should use to control the printing of any debugging messages.tnsVerboseis set from the value of environment variableTNS_VERBOSEby thetensras soon as it starts. Grading will be done withTNS_VERBOSEunset.## What to do

Run "./rtensr" to review the commands available, and run "./rtensr about" to see what needs to be implemented. The convolution code (fortnsConvoEval) will be nearly identical to what was done for p4vectr: we again need 2-D convolution, but now in a tensor field rather than a vector field, but that just means 3 values instead of 2 need to be reconstru. Reading through and understanding the header filetns.his essential. ThetnsMath.hmacro collection will be familiar.The handling of these lines

is the same as in previous assignments. There are detailed notes in the comments preceeding these blocks detailing what has to be done./* v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v begin student code */ /* ^'^'^'^'^'^'^'^'^'^'^'^'^'^'^'^'^'^'^ end student code */Just like p4vectr, 33710 students have two additional things to implement:

- Runge-Kutta Fourth-order integration along streamlines: the "
-iintg rk4" option for "tensr sline" and "tensr lic", which determines the value of theintgvariable passed totnsSlineTrace()andtnsLIC, respectively.- In
tnsLIC, if therndLinterpargument is nonzero, do bilinear interpolation into the given noise texture, instead of nearest-neighbor interplation.## Example

The commands here use "tensr/rtensrcommands to try./rrendr"; you should make sure that you get the exactly same results by running "./rendr". To an unfortunate extent the commands are intended to be executed in the order shown: later commands assume the presence of files created by running earlier commands.

- Always make sure your code builds cleanly with "
make"- See if a 2-D eignsystem can be computed:
The three values given are the unique Txx, Txy, Tyy elements of a symmetric 2D matrix. When two eigenvalues are equal, or very nearly equal (as with the last example), the is no single stable correct answer for what the eigenvectors should be. What matter is that Tv=Lv, or Tv-Lv=0, for eigenvector v and eignevalue L; that is what is tested in the./rtensr esys 1 2 3 ./rtensr esys 1 0 1 ./rtensr esys 1 0.1 1 ./rtensr esys 1 0.0000000000001 1tensr esysoutput.- Make a little tensor dataset, and try convolution. This one has a constantly rotating eigensystem, and a region of higher anisotropy in a ring around the origin. The highest anisotropy also varies as a function of position, from highest anisotropy on the right, to lowest anisotropy on the left.
You should try other kernels, too (see./rtensr sdg -w 1 -o circ.nrrd ./rtensr ceval -i circ.nrrd -w 0.6 0.3 -k bspln3 -pe ./rtensr ceval -i circ.nrrd -w 0.1 0.1 -k bspln3 -petensr klist). Many students seem to ignore the odd-support bspln2 kernel.- Try some streamlines along eigenvectors. The trick with these is that with eigenvectors not having a meaningful sign, "upstream" and "upstream" no longer have instrinsic meaning, and yet the streamline has to depart from the seed point in two opposite directions, and trace the locally-computed eigenvector as it goes.
To get a view of these; we make a background image that outlines where in world-space the data is:for I in euler rk2; do for E in 0 1; do ./rtensr sline -i circ.nrrd -k bspln2 -s 0.5 0.3 -h 0.15 -l 70 -intg $I -we $E -o sln${E}-$I.txt done doneAnd then we can show the single streamlines:unu slice -i circ.nrrd -a 0 -p 0 | # scalar image unu crop -min 1 1 -max M-1 M-1 | # cropped by one unu 1op 1 | # all values are 1 unu pad -min -1 -1 -max M+1 M+1 -b pad -v 0 | # border of 0s unu quantize -b 8 -o background.png(You can force Preview to display all the files with the same size by clicking on one of the thumbnails on the left, typing Command-a and then Command-0). One way to follow the path of the principle eigenvector (associated with the larger eigenvalue) all the way around the circle, as opposed to having the path double back on itself, is to make sure that the sign of the eigenvector (the one being integrated) is such that it has a positive dot product with the incoming direction (the prior direction along the path).for WUT in sln0-euler sln0-rk2 sln1-euler sln1-rk2; do ./rtensr eps -i background.png -s $WUT.txt -th 0.007 -o $WUT.eps done open sln{0,1}-{euler,rk2}.eps- 33710 students should also be implementing RK4 integration:
for I in euler rk2 rk4; do for E in 0 1; do ./rtensr sline -i circ.nrrd -k bspln2 -s 0.5 0.3 -h 0.15 -l 70 -intg $I -we $E -o sln${E}-$I.txt done done for WUT in sln0-euler sln0-rk2 sln0-rk4 sln1-euler sln1-rk2 sln1-rk4; do ./rtensr eps -i background.png -s $WUT.txt -th 0.007 -o $WUT.eps done open sln{0,1}-{euler,rk2,rk4}.eps- While vector streamlines can continue until they hit the field boundary, tensor eigenvector streamlines can stop when the anisotropy falls below some threshold:
In./rtensr sline -i circ.nrrd -k bspln2 -s 0.5 0.3 -h 0.1 -l 70 -intg euler -we 0 -at 0.00001 -o sln0-at6.txt ./rtensr sline -i circ.nrrd -k bspln2 -s 0.5 0.3 -h 0.1 -l 70 -intg euler -we 0 -at 0.1 -o sln0-at1.txt for T in 6 1; do ./rtensr eps -i background.png -s sln0-at${T}.txt -th 0.01 -o sln0-at${T}.eps done open sln0-at{6,1}.epssln0-at0.epsthe paths are stopped by the low anisotropy on the left side of the domain, whereas insln0-at6.epsthe field anisotropy is always above the anisotropy threshold, so the path can continue around.- On to LIC. First make a noise texture:
Then compute some LICs:unu slice -i circ.nrrd -a 0 -p 0 | # get scalar image with same orientation unu crop -min 1 1 -max M-1 M-1 | # crop to get away from edges of tensor field unu resample -s x4 x4 | # noise is 4x resolution of vector data unu 1op nrand -s 42 | # generate noise unu resample -s x1 x1 -k hann:1.6,7 | # blur a bit (to help anti-alias LIC) unu flip -a 1 -o noise.nrrd # so standard raster display looks correct ./rtensr info noise.nrrd unu quantize -b 8 -i noise.nrrd -min 0.1% -max 0.1% -o noise.png open noise.pngThis shows the direction of the first (LPARM="-i circ.nrrd -r noise.nrrd -k tent " QPARM="-b 8 -min 0.1% -max 0.1%" ./rtensr lic $LPARM -h 0.003 -l 150 -we 0 -ao aniso.nrrd -o lic0.nrrd ./rtensr lic $LPARM -h 0.003 -l 150 -we 1 -o lic1.nrrd unu 2op x aniso.nrrd lic0.nrrd | unu quantize $QPARM -o lic0.png unu 2op x aniso.nrrd lic1.nrrd | unu quantize $QPARM -o lic1.png unu quantize -b 8 -i aniso.nrrd -o aniso.png open lic0.png lic1.png aniso.pnglic0.png) and second (lic1.png) eigenvector, as well as the field anisotropy (aniso.png).- 33710 students should implement the linear interpolation into the noise texture triggered by the
-rlinoption to theliccommand (exactly as in p4vectr):LPARM="-i circ.nrrd -r noise.nrrd -k tent " QPARM="-b 8 -min 0.1% -max 0.1%" ./rtensr lic $LPARM -h 0.003 -l 150 -we 0 -rlin -o lic0-rlin.nrrd ./rtensr lic $LPARM -h 0.003 -l 150 -we 1 -rlin -o lic1-rlin.nrrd unu 2op x aniso.nrrd lic0-rlin.nrrd | unu quantize $QPARM -o lic0-rlin.png unu 2op x aniso.nrrd lic1-rlin.nrrd | unu quantize $QPARM -o lic1-rlin.png open lic0-rlin.png lic1-rlin.png- One big source of confusion or bugs with p4vectr was how to handle when when the streamline leaves the domain of the vector field, and how samples along the streamline should be weighted; this test highlights that. First make the tensor field
right.nrrdand the "noise" texturenoise.nrrd.In the./rtensr sdg -sz 151 201 -l 151 201 -p 1 0 0 0 0 0 5 0 0 1 0 0 -o right.nrrd unu slice -i right.nrrd -a 0 -p 2 | # scalar image unu grid -i - | # array of sample locations unu reshape -s 2 151 201 | # put back in shape unu dice -a 0 -o ./ # extract X and Y coords unu 2op gt 0.nrrd 1.nrrd -o edge.nrrd # make edge image unu slice -i right.nrrd -a 0 -p 2 | # scalar image w/ orientation unu 1op 0 | unu 2op + - edge.nrrd | # insert edge image unu crop -min 1 1 -max M-1 M-1 -o edge.nrrd # crop out edge unu quantize -b 8 -i edge.nrrd -o edge.png # look at it open edge.pngright.nrrd, the streamlines along the principle eigenvector go left-right (the principle eigenvector is (1,0) or (-1,0)), which allows you to predict somewhat how LIC should produce a horizontal blurring of theedgeimage. Do LIC and compare with reference:The order infor W in ./r ./; do ${W}tensr lic -i right.nrrd -k tent -r edge.nrrd -h 0.21 -l 101 -lk box -o ${W}edge-lic.nrrd unu quantize -b 8 -i ${W}edge-lic.nrrd -min -0.03 -max 1.03 -o ${W}edge-lic.png done unu 2op - {,r}edge-lic.nrrd | unu quantize -b 8 -min -0.125 -max 0.125 -o diff.png unu join -a 0 -i {r,}edge-lic.png diff.png -o compare-edge-lic.png open compare-edge-lic.png rm -f 0.nrrd 1.nrrd right.nrrd edge.nrrd {r,}edge-lic.{png,nrrd} diff.pngcompare-edge-lic.pngis: reference, your result, difference. Solid gray is good; anything markedly significantly different from solid gray indicates a bug. The difference image may also show (subtly, with faint bars on the left and right sides) a more minor difference: whether, when you are testing whether a streamline vertex is inside the noise texture, you do that test based on the floating-point index-space coordinates (just after conversion from world-space), or whether you do it after rounding those the index-space coordinate to integers. The directions never specified which is correct, so no deductions are made based on this. The reference implementation first rounds index-space positions to integers, and then tests whether they are valid indices into the noise texture.## Grading

The grade will be based on style (10%) and correctness (90%), similar to previous projects. The style points will be the same as for Project 2: new functions are "static", convolution uses 2*S not S^2 kernel evaluations, the code compiles without warnings, and there are no memory leaks (though how this is tested may be more rigorous than it was for Project 2). Also,points will be deducted if there are extraneous debugging messages.. The correctness points will be based on the commands above or some slight modifications.