lavavu 1.8.84__cp311-cp311-macosx_11_0_arm64.whl → 1.9.5__cp311-cp311-macosx_11_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lavavu/_LavaVuPython.cpython-311-darwin.so +0 -0
- lavavu/control.py +18 -5
- lavavu/html/webview.html +1 -1
- lavavu/lavavu.py +391 -116
- lavavu/osmesa/LavaVuPython.py +561 -0
- lavavu/osmesa/__init__.py +0 -0
- lavavu/shaders/default.frag +0 -6
- lavavu/shaders/default.vert +4 -4
- lavavu/shaders/fontShader.frag +0 -5
- lavavu/shaders/lineShader.frag +0 -4
- lavavu/shaders/lineShader.vert +0 -2
- lavavu/shaders/pointShader.frag +0 -5
- lavavu/shaders/pointShader.vert +0 -4
- lavavu/shaders/triShader.frag +0 -17
- lavavu/shaders/triShader.vert +0 -4
- lavavu/shaders/volumeShader.frag +0 -63
- lavavu/tracers.py +180 -110
- {lavavu-1.8.84.dist-info → lavavu-1.9.5.dist-info}/METADATA +22 -17
- {lavavu-1.8.84.dist-info → lavavu-1.9.5.dist-info}/RECORD +23 -21
- {lavavu-1.8.84.dist-info → lavavu-1.9.5.dist-info}/WHEEL +2 -1
- {lavavu-1.8.84.dist-info → lavavu-1.9.5.dist-info}/entry_points.txt +0 -0
- {lavavu-1.8.84.dist-info → lavavu-1.9.5.dist-info/licenses}/LICENSE.md +0 -0
- {lavavu-1.8.84.dist-info → lavavu-1.9.5.dist-info}/top_level.txt +0 -0
lavavu/shaders/triShader.frag
CHANGED
@@ -22,25 +22,10 @@ uniform vec3 uClipMax;
|
|
22
22
|
uniform bool uOpaque;
|
23
23
|
uniform vec4 uLight;
|
24
24
|
|
25
|
-
#ifdef WEBGL
|
26
|
-
#define outColour gl_FragColor
|
27
|
-
#define texture(a,b) texture2D(a,b)
|
28
|
-
|
29
|
-
//Before OpenGL 3+ we need our own isnan function
|
30
|
-
bool isnan3(vec3 val)
|
31
|
-
{
|
32
|
-
if (!(val.x < 0.0 || 0.0 < val.x || val.x == 0.0)) return true;
|
33
|
-
if (!(val.y < 0.0 || 0.0 < val.y || val.y == 0.0)) return true;
|
34
|
-
if (!(val.z < 0.0 || 0.0 < val.z || val.z == 0.0)) return true;
|
35
|
-
return false;
|
36
|
-
}
|
37
|
-
|
38
|
-
#else
|
39
25
|
#define isnan3(v) any(isnan(v))
|
40
26
|
flat in vec4 vFlatColour;
|
41
27
|
uniform bool uFlat;
|
42
28
|
out vec4 outColour;
|
43
|
-
#endif
|
44
29
|
|
45
30
|
uniform bool uCalcNormal;
|
46
31
|
|
@@ -69,10 +54,8 @@ void main(void)
|
|
69
54
|
if (any(lessThan(vVertex, uClipMin)) || any(greaterThan(vVertex, uClipMax))) discard;
|
70
55
|
|
71
56
|
vec4 fColour = vColour;
|
72
|
-
#ifndef WEBGL
|
73
57
|
if (uFlat)
|
74
58
|
fColour = vFlatColour;
|
75
|
-
#endif
|
76
59
|
float alpha = fColour.a;
|
77
60
|
if (uTextured && vTexCoord.x > -1.0) //Null texcoord (-1,-1)
|
78
61
|
{
|
lavavu/shaders/triShader.vert
CHANGED
@@ -2,9 +2,7 @@ in vec3 aVertexPosition;
|
|
2
2
|
in vec3 aVertexNormal;
|
3
3
|
in vec4 aVertexColour;
|
4
4
|
in vec2 aVertexTexCoord;
|
5
|
-
#ifndef WEBGL
|
6
5
|
flat out vec4 vFlatColour;
|
7
|
-
#endif
|
8
6
|
|
9
7
|
uniform mat4 uMVMatrix;
|
10
8
|
uniform mat4 uPMatrix;
|
@@ -34,9 +32,7 @@ void main(void)
|
|
34
32
|
vColour = aVertexColour;
|
35
33
|
|
36
34
|
vTexCoord = aVertexTexCoord;
|
37
|
-
#ifndef WEBGL
|
38
35
|
vFlatColour = vColour;
|
39
|
-
#endif
|
40
36
|
vVertex = aVertexPosition;
|
41
37
|
|
42
38
|
//Head light, lightPos=(0,0,0) - vPosEye
|
lavavu/shaders/volumeShader.frag
CHANGED
@@ -6,17 +6,10 @@
|
|
6
6
|
* https://www.gnu.org/licenses/lgpl.html
|
7
7
|
* (volume shader from sharevol https://github.com/OKaluza/sharevol)
|
8
8
|
*/
|
9
|
-
#ifdef WEBGL
|
10
|
-
uniform sampler2D uVolume;
|
11
|
-
#define NO_DEPTH_WRITE
|
12
|
-
#define outColour gl_FragColor
|
13
|
-
#define texture(a,b) texture2D(a,b)
|
14
|
-
#else
|
15
9
|
//Included dynamically before compile in WebGL mode...
|
16
10
|
const int maxSamples = 2048;
|
17
11
|
uniform sampler3D uVolume;
|
18
12
|
out vec4 outColour;
|
19
|
-
#endif
|
20
13
|
|
21
14
|
const float depthT = 0.99; //Transmissivity threshold below which depth write applied
|
22
15
|
|
@@ -63,63 +56,7 @@ vec3 bbMax;
|
|
63
56
|
float interpolate_tricubic_fast(vec3 coord);
|
64
57
|
#endif
|
65
58
|
|
66
|
-
#ifdef WEBGL
|
67
|
-
|
68
|
-
vec2 islices = vec2(1.0 / slices.x, 1.0 / slices.y);
|
69
|
-
float maxslice = slices.x * slices.y - 1.0;
|
70
|
-
//Clamp to a bit before halfway for the edge voxels
|
71
|
-
vec2 cmin = vec2(0.55/(slices.x*slices.y), 0.55/(slices.x*slices.y));
|
72
|
-
vec2 cmax = vec2(1.0, 1.0) - cmin;
|
73
|
-
|
74
|
-
float sample(vec3 pos)
|
75
|
-
{
|
76
|
-
//Get z slice index and position between two slices
|
77
|
-
float Z = pos.z * maxslice;
|
78
|
-
float slice = floor(Z); //Index of first slice
|
79
|
-
Z = fract(Z);
|
80
|
-
//Edge case at z min (possible with tricubic filtering)
|
81
|
-
if (int(slice) < 0)
|
82
|
-
{
|
83
|
-
slice = 0.0;
|
84
|
-
Z = 0.0;
|
85
|
-
}
|
86
|
-
//Edge case at z max
|
87
|
-
else if (int(slice) > int(maxslice)-1)
|
88
|
-
{
|
89
|
-
slice = maxslice-1.0;
|
90
|
-
Z = 1.0;
|
91
|
-
}
|
92
|
-
//Only start interpolation with next Z slice 1/3 from edges at first & last z slice
|
93
|
-
//(this approximates how 3d texture volume is sampled at edges with linear filtering
|
94
|
-
// due to edge sample being included in weighted average twice)
|
95
|
-
// - min z slice
|
96
|
-
else if (int(slice) == 0)
|
97
|
-
{
|
98
|
-
Z = max(0.0, (Z-0.33) * 1.5);
|
99
|
-
}
|
100
|
-
// - max z slice
|
101
|
-
else if (int(slice) == int(maxslice)-1)
|
102
|
-
{
|
103
|
-
Z = min(1.0, Z*1.5);
|
104
|
-
}
|
105
|
-
|
106
|
-
//X & Y coords of sample scaled to slice size
|
107
|
-
//(Clamp range at borders to prevent bleeding between tiles due to linear filtering)
|
108
|
-
vec2 sampleOffset = clamp(pos.xy, cmin, cmax) * islices;
|
109
|
-
//Offsets in 2D texture of given slice indices
|
110
|
-
//(add offsets to scaled position within slice to get sample positions)
|
111
|
-
float A = slice * islices.x;
|
112
|
-
float B = (slice+1.0) * islices.x;
|
113
|
-
vec2 z1offset = vec2(fract(A), floor(A) / slices.y) + sampleOffset;
|
114
|
-
vec2 z2offset = vec2(fract(B), floor(B) / slices.y) + sampleOffset;
|
115
|
-
|
116
|
-
//Interpolate the final value by position between slices [0,1]
|
117
|
-
return mix(texture2D(uVolume, z1offset).x, texture2D(uVolume, z2offset).x, Z);
|
118
|
-
}
|
119
|
-
|
120
|
-
#else
|
121
59
|
#define sample(pos) (texture(uVolume, pos).x)
|
122
|
-
#endif
|
123
60
|
|
124
61
|
float tex3D(vec3 pos)
|
125
62
|
{
|
lavavu/tracers.py
CHANGED
@@ -1,124 +1,194 @@
|
|
1
1
|
"""
|
2
|
-
Warning! EXPERIMENTAL:
|
3
|
-
these features and functions are under development, will have bugs,
|
4
|
-
and may be heavily modified in the future
|
5
|
-
|
6
2
|
Tracer particles in a vector field
|
7
|
-
Uses a KDTree to find nearest vector to advect the particles
|
8
3
|
|
9
|
-
- Requires scipy.
|
4
|
+
- Requires scipy.interpolate
|
10
5
|
"""
|
11
6
|
import numpy
|
12
7
|
import os
|
13
8
|
import sys
|
14
9
|
import random
|
15
|
-
import
|
16
|
-
from scipy import spatial
|
17
|
-
|
18
|
-
#Necessary? for large trees, detect?
|
19
|
-
#sys.setrecursionlimit(10000)
|
10
|
+
from scipy.interpolate import RegularGridInterpolator
|
20
11
|
|
21
|
-
|
22
|
-
def __init__(self, verts, N=5000):
|
23
|
-
self.tree = spatial.cKDTree(verts)
|
24
|
-
self.tracers = None
|
25
|
-
self.steps = [0]*N
|
26
|
-
self.values = None
|
27
|
-
self.positions = None
|
28
|
-
self.velocities = None
|
29
|
-
|
30
|
-
def trace_particles(state, verts, vecs, N=5000, limit=0.5, speed=1.0, noise=0.0, height=None):
|
12
|
+
def random_particles(count, lowerbound=[0,0,0], upperbound=[1,1,1], dims=3):
|
31
13
|
"""
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
- find the nearest velocity grid point
|
36
|
-
- if within max dist: Multiply position by velocity vector
|
37
|
-
- otherwise: Generate a new start position for tracer
|
38
|
-
|
39
|
-
Parameters
|
40
|
-
----------
|
41
|
-
state : TracerState
|
42
|
-
Object returned from first call, pass None on first pass
|
43
|
-
verts : array or list
|
44
|
-
vertices of the vector field
|
45
|
-
vecs : array or list
|
46
|
-
vector values of the vector field
|
47
|
-
N : int
|
48
|
-
Number of particles to seed
|
49
|
-
limit : float
|
50
|
-
Distance limit over which tracers are not connected,
|
51
|
-
For example if using a periodic boundary, setting limit to
|
52
|
-
half the bounding box size will prevent tracer lines being
|
53
|
-
connected when passing through the boundary
|
54
|
-
speed : float
|
55
|
-
Speed multiplier, scaling factor for the velocity taken from the vector values
|
56
|
-
noise : float
|
57
|
-
A noise factor, if set a random value is generated, multiplied by noise factor
|
58
|
-
and added to each new position
|
59
|
-
height : float
|
60
|
-
A fixed height value, all positions will be given this height as their Z component
|
61
|
-
|
62
|
-
Returns
|
63
|
-
-------
|
64
|
-
TracerState
|
65
|
-
Object to hold the tracer state and track particles
|
66
|
-
Pass this as first paramter on subsequent calls
|
14
|
+
Return an array of *count* 3d vertices of random particle positions
|
15
|
+
Minimum and maximum values defined by lowerbound and upperbound
|
67
16
|
"""
|
17
|
+
p = [None] * dims
|
18
|
+
for c in range(dims):
|
19
|
+
if lowerbound[c] == upperbound[c]:
|
20
|
+
p[c] = numpy.zeros(shape=(count)) + lowerbound[c]
|
21
|
+
else:
|
22
|
+
p[c] = numpy.random.uniform(low=lowerbound[c], high=upperbound[c], size=count)
|
23
|
+
|
24
|
+
return numpy.stack(p).T
|
68
25
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
26
|
+
class Tracers():
|
27
|
+
def __init__(self, grid, count=1000, lowerbound=None, upperbound=None, limit=None, age=4, respawn_chance=0.2, speed_multiply=1.0, height=0.0, viewer=None):
|
28
|
+
"""
|
29
|
+
Seed random particles into a vector field and trace their positions
|
30
|
+
|
31
|
+
Parameters
|
32
|
+
----------
|
33
|
+
grid : list of coord arrays for each dimension as expected by RegularGridInterpolator,
|
34
|
+
or a numpy array of 2d or 3d vertices, which will be converted before being sent to the interpolator
|
35
|
+
Object returned from first call, pass None on first pass
|
36
|
+
count : int
|
37
|
+
Number of particles to seed and track
|
38
|
+
lowerbound : optional minimum vertex point defining particle bounding box,
|
39
|
+
if not provided will be taken from grid lower corner
|
40
|
+
upperbound : optional maximum vertex point defining particle bounding box,
|
41
|
+
if not provided will be taken from grid upper corner
|
42
|
+
limit : float
|
43
|
+
Distance limit over which tracers are not connected,
|
44
|
+
For example if using a periodic boundary, setting limit to
|
45
|
+
half the bounding box size will prevent tracer lines being
|
46
|
+
connected when passing through the boundary
|
47
|
+
age : int
|
48
|
+
Minimum particle age in steps after which particle can be deleted and respawned, defaults to 4
|
49
|
+
respawn : float
|
50
|
+
Probability of respawning, after age reached, default 0.2 ==> 1 in 5 chance of deletion
|
51
|
+
speed_multiply : float
|
52
|
+
Speed multiplier, scaling factor for the velocity taken from the vector values
|
53
|
+
height : float
|
54
|
+
A fixed height value, all positions will be given this height as their Z component
|
55
|
+
viewer : lavavu.Viewer
|
56
|
+
Viewer object for plotting functions
|
57
|
+
"""
|
58
|
+
if len(grid) == 2:
|
59
|
+
self.gridx = grid[0]
|
60
|
+
self.gridy = grid[1]
|
61
|
+
self.gridz = numpy.array((height, height))
|
62
|
+
self.dims = 2
|
63
|
+
elif len(grid) == 3:
|
64
|
+
self.gridx = grid[0]
|
65
|
+
self.gridy = grid[1]
|
66
|
+
self.gridz = grid[2]
|
67
|
+
self.dims = 3
|
68
|
+
elif isinstance(grid, numpy.ndarray) and grid.shape[1] == 3:
|
69
|
+
self.gridx = grid[::,0]
|
70
|
+
self.gridy = grid[::,1]
|
71
|
+
self.gridz = grid[::,2]
|
72
|
+
self.dims = 3
|
73
|
+
elif isinstance(grid, numpy.ndarray) and grid.shape[1] == 2:
|
74
|
+
self.gridx = grid[::,0]
|
75
|
+
self.gridy = grid[::,1]
|
76
|
+
self.gridz = numpy.array((height, height))
|
77
|
+
self.dims = 2
|
114
78
|
else:
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
79
|
+
raise(ValueError('Grid needs to be array of 2d/3d vertices, or arrays of vertex coords (x, y, [z])'))
|
80
|
+
|
81
|
+
self.count = count
|
82
|
+
if lowerbound is None:
|
83
|
+
lowerbound = (self.gridx[0], self.gridy[0], self.gridz[0])
|
84
|
+
if upperbound is None:
|
85
|
+
upperbound = (self.gridx[-1], self.gridy[-1], self.gridz[-1])
|
86
|
+
self.positions = random_particles(self.count, lowerbound, upperbound, self.dims)
|
87
|
+
self.old_pos = numpy.zeros_like(self.positions)
|
88
|
+
self.lowerbound = lowerbound
|
89
|
+
self.upperbound = upperbound
|
90
|
+
self.velocities = None
|
91
|
+
self.steps = [0]*count
|
92
|
+
self.speed = numpy.zeros(shape=(count))
|
93
|
+
self.ages = numpy.zeros(shape=(count))
|
94
|
+
self.interp = None
|
95
|
+
if limit is None:
|
96
|
+
limit = 0.1 * (abs(self.gridx[-1] - self.gridx[0]) + abs(self.gridy[-1] - self.gridy[0]))
|
97
|
+
self.limit = limit
|
98
|
+
self.age = age
|
99
|
+
self.respawn_chance = respawn_chance
|
100
|
+
self.speed_multiply = speed_multiply
|
101
|
+
self.height = height
|
102
|
+
|
103
|
+
self.lv = viewer
|
104
|
+
self.points = None
|
105
|
+
self.arrows = None
|
106
|
+
self.tracers = None
|
107
|
+
|
108
|
+
|
109
|
+
def respawn(self, r):
|
110
|
+
#Dead or out of bounds particle, start at new position
|
111
|
+
#Loop until new position further from current position than limit
|
112
|
+
old_pos = self.positions[r]
|
113
|
+
pos = numpy.array([0.] * self.dims)
|
114
|
+
for i in range(10):
|
115
|
+
pos = random_particles(1, self.lowerbound, self.upperbound, self.dims)
|
116
|
+
dist = numpy.linalg.norm(old_pos - pos)
|
117
|
+
if dist > self.limit*1.01:
|
118
|
+
break
|
119
|
+
|
120
|
+
self.ages[r] = 0
|
121
|
+
self.positions[r] = pos
|
122
|
+
|
123
|
+
def update(self, vectors=None):
|
124
|
+
#Interpolate velocity at all positions,
|
125
|
+
#If vectors not passed, will use previous values
|
126
|
+
if vectors is not None:
|
127
|
+
if self.dims == 2:
|
128
|
+
self.interp = RegularGridInterpolator((self.gridx, self.gridy), vectors, bounds_error=False, fill_value=0.0)
|
129
|
+
else:
|
130
|
+
self.interp = RegularGridInterpolator((self.gridx, self.gridy, self.gridz), vectors, bounds_error=False, fill_value=0.0)
|
131
|
+
|
132
|
+
if self.interp is None:
|
133
|
+
raise(ValueError("No velocity grid, must pass vectors for first call of update()"))
|
134
|
+
|
135
|
+
self.velocities = self.interp(self.positions)
|
136
|
+
self.old_pos = numpy.copy(self.positions)
|
137
|
+
|
138
|
+
for r in range(len(self.velocities)):
|
139
|
+
#Lookup velocity at this index, multiply by position to get delta and add
|
140
|
+
self.speed[r] = numpy.linalg.norm(self.velocities[r])
|
141
|
+
if numpy.isnan(self.speed[r]): self.speed[r] = 0.0
|
142
|
+
if self.speed[r] == 0.0: #numpy.any(numpy.isinf(self.old_pos[r])) or numpy.any(numpy.isinf(self.positions[r])):
|
143
|
+
self.respawn(r)
|
144
|
+
else:
|
145
|
+
self.positions[r] = self.positions[r] + self.speed_multiply * self.velocities[r]
|
146
|
+
self.ages[r] += 1
|
147
|
+
|
148
|
+
#Bounds checks
|
149
|
+
#Chance of killing particle when over age, default 1 in 5 (0.2)
|
150
|
+
if (any(self.positions[r] < self.lowerbound[0:self.dims]) or any(self.positions[r] > self.upperbound[0:self.dims])
|
151
|
+
or (self.ages[r] > self.age and numpy.random.uniform() <= self.respawn_chance)):
|
152
|
+
#if r < 20: print("Kill", r, self.speed[r], numpy.isnan(self.speed[r])) # [0] == numpy.nan)
|
153
|
+
#self.positions[r] = numpy.array([numpy.inf] * self.dims)
|
154
|
+
#self.positions[r] = numpy.array([numpy.nan] * self.dims)
|
155
|
+
self.respawn(r)
|
156
|
+
self.velocities[r] = numpy.array([0.0] * self.dims)
|
157
|
+
self.speed[r] = 0.0
|
158
|
+
|
159
|
+
if self.lv:
|
160
|
+
positions = self.positions
|
161
|
+
if self.dims == 2 and self.height != 0:
|
162
|
+
#Convert to 3d and set z coord to height
|
163
|
+
shape = list(positions.shape)
|
164
|
+
shape[-1] = 3
|
165
|
+
positions = numpy.zeros(shape)
|
166
|
+
positions[::,0:2] = self.positions
|
167
|
+
positions[::,2] = numpy.array([self.height] * shape[0])
|
168
|
+
if self.points:
|
169
|
+
self.points.vertices(positions)
|
170
|
+
if len(self.points["colourmap"]):
|
171
|
+
self.points.values(self.speed)
|
172
|
+
if self.arrows:
|
173
|
+
self.arrows.vectors(self.velocities)
|
174
|
+
self.arrows.vertices(positions)
|
175
|
+
if len(self.arrows["colourmap"]):
|
176
|
+
self.arrows.values(self.speed)
|
177
|
+
|
178
|
+
if self.tracers:
|
179
|
+
self.tracers.vertices(positions)
|
180
|
+
if len(self.tracers["colourmap"]):
|
181
|
+
self.tracers.values(self.speed)
|
182
|
+
|
183
|
+
def plot_points(self, **kwargs):
|
184
|
+
if self.lv is not None and self.points is None:
|
185
|
+
self.points = self.lv.points('tracer_points', **kwargs)
|
186
|
+
|
187
|
+
def plot_arrows(self, **kwargs):
|
188
|
+
if self.lv is not None and self.arrows is None:
|
189
|
+
self.arrows = self.lv.vectors('tracer_arrows', **kwargs)
|
190
|
+
|
191
|
+
def plot_tracers(self, **kwargs):
|
192
|
+
if self.lv is not None and self.tracers is None:
|
193
|
+
self.tracers = self.lv.tracers('tracers', dims=self.count, limit=self.limit, **kwargs)
|
124
194
|
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: lavavu
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.9.5
|
4
4
|
Summary: Python interface to LavaVu OpenGL 3D scientific visualisation utilities
|
5
5
|
Author-email: Owen Kaluza <owen@kaluza.id.au>
|
6
6
|
License: ### Licensing
|
@@ -214,14 +214,17 @@ Description-Content-Type: text/markdown
|
|
214
214
|
License-File: LICENSE.md
|
215
215
|
Requires-Dist: numpy>=1.18
|
216
216
|
Requires-Dist: aiohttp
|
217
|
-
Requires-Dist:
|
217
|
+
Requires-Dist: jupyter_server_proxy
|
218
|
+
Requires-Dist: matplotlib
|
219
|
+
Requires-Dist: numpy-quaternion
|
220
|
+
Dynamic: license-file
|
218
221
|
|
219
222
|

|
220
223
|
|
221
224
|
[](https://github.com/lavavu/LavaVu/actions?query=workflow:Test)
|
222
225
|
[](https://github.com/lavavu/LavaVu/actions?query=workflow:Deploy)
|
223
226
|
[](https://zenodo.org/badge/latestdoi/45163055)
|
224
|
-
[](https://mybinder.org/v2/gh/lavavu/LavaVu/1.
|
227
|
+
[](https://mybinder.org/v2/gh/lavavu/LavaVu/1.9.5)
|
225
228
|
|
226
229
|
A scientific visualisation tool with a python interface for fast and flexible visual analysis.
|
227
230
|
|
@@ -229,11 +232,12 @@ Documentation available here [LavaVu Documentation](https://lavavu.github.io/Doc
|
|
229
232
|
|
230
233
|

|
231
234
|
|
232
|
-
LavaVu development is supported by
|
235
|
+
LavaVu development is supported by [ACCESS-NRI](https://www.access-nri.org.au/).
|
236
|
+
Prior development was funded by the Monash Immersive Visualisation Plaform at [Monash eResearch](https://www.monash.edu/researchinfrastructure/eresearch) and the Simulation, Analysis & Modelling component of the [NCRIS AuScope](http://www.auscope.org.au/ncris/) capability.
|
233
237
|
|
234
238
|
The acronym stands for: lightweight, automatable visualisation and analysis viewing utility, but "lava" is also a reference to its primary application as a viewer for geophysical simulations. It was also chosen to be unique enough to find the repository with google.
|
235
239
|
|
236
|
-
The project started
|
240
|
+
The project started as a replacement rendering library for the gLucifer<sup>1</sup> framework, visualising geodynamics simulations. The new OpenGL visualisation code was re-implemented as a more general purpose visualisation tool. gLucifer continues as a set of sampling tools for Underworld simulations as part of the [Underworld2](https://github.com/underworldcode/underworld2/) code. LavaVu provides the rendering library for creating 2d and 3d visualisations to view this sampled data, inline within interactive Jupyter notebooks and offline through saved visualisation databases and images/movies.
|
237
241
|
|
238
242
|
As a standalone tool it is a scriptable 3D visualisation tool capable of producing publication quality high res images and video output from time varying data sets along with HTML5 3D visualisations in WebGL.
|
239
243
|
Rendering features include correctly and efficiently rendering large numbers of opaque and transparent points and surfaces and volume rendering by GPU ray-marching. There are also features for drawing vector fields and tracers (streamlines).
|
@@ -241,12 +245,11 @@ Rendering features include correctly and efficiently rendering large numbers of
|
|
241
245
|
Control is via python and a set of simple verbose scripting commands along with mouse/keyboard interaction.
|
242
246
|
GUI components can be generated for use from a web browser via the python "control" module and a built in web server.
|
243
247
|
|
248
|
+
Widgets for interactive use in the Jupyter notebook environment allow use for remote visualisation, eg: on supercomputing environments.
|
249
|
+
|
244
250
|
A native data format called GLDB is used to store and visualisations in a compact single file, using SQLite for storage and fast loading. A small number of other data formats are supported for import (OBJ surfaces, TIFF stacks etc).
|
245
251
|
Further data import formats are supported with python scripts, with the numpy interface allowing rapid loading and manipulation of data.
|
246
252
|
|
247
|
-
A CAVE2 virtual reality mode is provided by utilising Omegalib (http://github.com/uic-evl/omegalib) to allow use in Virtual Reality and Immersive Visualisation facilities, such as the CAVE2 at Monash, see (https://github.com/mivp/LavaVR).
|
248
|
-
Side-by-side and quad buffer stereoscopic 3D support is also provided for other 3D displays.
|
249
|
-
|
250
253
|
### This repository ###
|
251
254
|
|
252
255
|
This is the public source code repository for all development on the project.
|
@@ -257,13 +260,10 @@ Development happens in the "master" branch with stable releases tagged, so if yo
|
|
257
260
|
It's now in the python package index, so you can install with *pip*:
|
258
261
|
|
259
262
|
```
|
260
|
-
pip install
|
263
|
+
python -m pip install lavavu
|
261
264
|
```
|
262
265
|
|
263
|
-
>
|
264
|
-
|
265
|
-
> Currently no binaries are provided and the installer needs to compile the library, so on Linux you may need some developer tools and headers first, eg: for Ubuntu:
|
266
|
-
`sudo apt install build-essential libgl1-mesa-dev libx11-dev zlib1g-dev`
|
266
|
+
> Currently binary wheels are provided for Linux x86_64, MacOS x86_64 and ARM64 and Windows x86_64.
|
267
267
|
|
268
268
|
To try it out:
|
269
269
|
|
@@ -280,7 +280,12 @@ Alternatively, clone this repository with *git* and build from source:
|
|
280
280
|
```
|
281
281
|
git clone https://github.com/lavavu/LavaVu
|
282
282
|
cd LavaVu
|
283
|
+
python -m pip install .
|
284
|
+
```
|
285
|
+
or
|
286
|
+
```
|
283
287
|
make -j4
|
288
|
+
|
284
289
|
```
|
285
290
|
|
286
291
|
If all goes well the viewer will be built, try running with:
|
@@ -289,14 +294,14 @@ If all goes well the viewer will be built, try running with:
|
|
289
294
|
### Dependencies ###
|
290
295
|
|
291
296
|
* OpenGL and Zlib, present on most systems, headers may need to be installed
|
292
|
-
* To use with python requires python
|
293
|
-
* For video output, requires: libavcodec, libavformat, libavutil, libswscale (from FFmpeg / libav)
|
297
|
+
* To use with python requires python 3.6+ and NumPy
|
298
|
+
* For video output, requires: PyAV or for built in encoding, libavcodec, libavformat, libavutil, libswscale (from FFmpeg / libav)
|
294
299
|
* To build the python interface from source requires swig (http://www.swig.org/)
|
295
300
|
|
296
301
|
### Who do I talk to? ###
|
297
302
|
|
298
303
|
* Report bugs/issues here on github: https://github.com/lavavu/LavaVu/issues
|
299
|
-
* Contact developer: Owen Kaluza (at)
|
304
|
+
* Contact developer: Owen Kaluza (at) anu.edu.au
|
300
305
|
|
301
306
|
For further documentation / examples, see the online documentation
|
302
307
|
* https://lavavu.github.io/Documentation
|
@@ -1,18 +1,24 @@
|
|
1
|
-
lavavu/
|
1
|
+
lavavu-1.9.5.dist-info/RECORD,,
|
2
|
+
lavavu-1.9.5.dist-info/WHEEL,sha256=EfZGgIDXTDki1cNGEkgBr7YEgShBrw-nMmb-y67Rxxs,136
|
3
|
+
lavavu-1.9.5.dist-info/entry_points.txt,sha256=LC2qXR6EMe45Cb7zGAF99R9HFrAECP6Qkp_YuG6HZB0,44
|
4
|
+
lavavu-1.9.5.dist-info/top_level.txt,sha256=JptS0k1nlBumjLs_0hITr3_XUJhxqvKBXD2jGho3E3A,7
|
5
|
+
lavavu-1.9.5.dist-info/METADATA,sha256=kZSwyc4jj393jf3xRoK7AM4B1x6gZaFAUNsPl6YqKdQ,17877
|
6
|
+
lavavu-1.9.5.dist-info/licenses/LICENSE.md,sha256=EhfNgC6BYh5gDEaq4tcrN3S0wbO4CtJO46botJnCF8c,8603
|
7
|
+
lavavu/lavavu.py,sha256=FX4KuzAW_-JZqG976lZUHkw-_j6Due8l2Z8W4ZBToxU,218332
|
2
8
|
lavavu/vutils.py,sha256=6Vm_xl1bp9mWlfk7jgLDwbRw-tdE_oxin77YkLel3_4,5437
|
3
9
|
lavavu/dict.json,sha256=lsZEHc7Bb6_lt7tkSBQMgkq7AEn_2hnhWzzdokmvIY8,52729
|
4
10
|
lavavu/server.py,sha256=L-_yPCbNfwYxJCPjDQtr_lxPnDp4oMNVFyxXhBERYrQ,12468
|
5
11
|
lavavu/points.py,sha256=jRRtA6CrcA46Y2jUJmkxnIiVoMC5a14xEd_ojhmjhz4,5871
|
6
12
|
lavavu/LavaVuPython.py,sha256=ixhceiAr0gGGfCe3d2cY0IIgS4hbgoYJGa_RfgAmmrU,33207
|
7
|
-
lavavu/tracers.py,sha256
|
13
|
+
lavavu/tracers.py,sha256=-NwdBAj5vYWmLt4NE0gWl36SQShQhICR7vBE4rzNOFI,8488
|
8
14
|
lavavu/convert.py,sha256=tbYRjLE2l1hI4d6tsW41Lia1JXmrWSc0-JAYCiMrjys,35516
|
9
|
-
lavavu/control.py,sha256=
|
15
|
+
lavavu/control.py,sha256=s32rtLPXXYtxpeXd6-iHdupmaMTJ3KhK6Vq-CLjf9OQ,66755
|
10
16
|
lavavu/__init__.py,sha256=JroZQiUbuVN7ifixk2zNDGlyLGaM8bqfRbw4D_F9qIQ,191
|
11
17
|
lavavu/amalgamate.py,sha256=Xloq1IZ4VUvYiROzQtwKcQIWC65c7EZrdiGVhZdolL8,586
|
12
18
|
lavavu/aserver.py,sha256=SfFvLeDTcx1XtS8fY_HIrDmh3q9HicCBRSAriY5yyOE,12003
|
13
19
|
lavavu/font.bin,sha256=fvi5zkvmq6gh9v3jXedBVuxNJWKmHtbjECzv6eT9wb4,225360
|
14
20
|
lavavu/__main__.py,sha256=EbDetijCjyoiNxmExqnDGoRVs996tSVave5DML9zuMY,235
|
15
|
-
lavavu/_LavaVuPython.cpython-311-darwin.so,sha256=
|
21
|
+
lavavu/_LavaVuPython.cpython-311-darwin.so,sha256=LppYygOGPUvCZXfuDMVk7moDCTIIoXN6Lg0mcYAQtRs,3927376
|
16
22
|
lavavu/html/control.css,sha256=PVLwmle00ciEckUV5ZIRmI3Whxhl7-mlVexnyyxoU70,3259
|
17
23
|
lavavu/html/control.js,sha256=oV24eJZ0vfuCxF3fO60eeJSkNFJ9hUkSCThHGJS1Wvc,11652
|
18
24
|
lavavu/html/gui.css,sha256=PRDLsYwM6cgLC9zZsEAG0dnnSd-HYH6oSEfsdEBkuxk,582
|
@@ -27,27 +33,23 @@ lavavu/html/dat.gui.min.js,sha256=S4_QjoXe4IOpU0f0Sj5jEQLTWPoX9uRl1ohB91jyhuw,56
|
|
27
33
|
lavavu/html/OK-min.js,sha256=-4Gc1-dWfxP_w6r9ZOHa8u-X2BlGUoSQbX68lwCxQ3E,39115
|
28
34
|
lavavu/html/emscripten.css,sha256=wkaIJhXaxuMchinQX9Z8c12cJomyvFQMeIZ62WGQEPQ,1813
|
29
35
|
lavavu/html/drawbox.js,sha256=SJxFSmWd7QVFI5__66hFkKzLKeqg1JPcx-gJuqdMkXw,34590
|
30
|
-
lavavu/html/webview.html,sha256=
|
36
|
+
lavavu/html/webview.html,sha256=aUS6ZlGmrsZ4TkKv1-zKV_g_QQezWxL4DN0-ALnAOZs,1521
|
31
37
|
lavavu/html/emscripten-template.js,sha256=h63mzl3Lv7aQT1wMOiOucPOvHTJjpKkzsL-SFVYaZlA,6135
|
32
38
|
lavavu/html/draw.js,sha256=57LlHlYRh0IvWVwzGDnF6PaCxYLzokpokLNCuZlG1ds,84108
|
33
39
|
lavavu/html/dat-gui-light-theme.css,sha256=uPhvJs-1IAsdxudItyOw8lZy8Hrih0zmFM1u-xRwZ-M,1142
|
34
40
|
lavavu/html/menu.js,sha256=WCli3UYcQ7frjNq0aAXNALu33iNiN8lpTYwKZ7pUcn4,21501
|
35
41
|
lavavu/html/baseviewer.js,sha256=u3UhC1At6rMBKmcQ7d2DXTRxQ20wsQkc4lqA-7sL7i4,9567
|
36
|
-
lavavu/
|
37
|
-
lavavu/
|
38
|
-
lavavu/shaders/
|
39
|
-
lavavu/shaders/
|
40
|
-
lavavu/shaders/
|
41
|
-
lavavu/shaders/
|
42
|
-
lavavu/shaders/triShader.
|
43
|
-
lavavu/shaders/
|
42
|
+
lavavu/osmesa/LavaVuPython.py,sha256=ixhceiAr0gGGfCe3d2cY0IIgS4hbgoYJGa_RfgAmmrU,33207
|
43
|
+
lavavu/osmesa/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
44
|
+
lavavu/shaders/volumeShader.frag,sha256=Ajkpt0S2p0PpbQ2jygDnrymSgPMU2CG5xQT-dq2rr90,14194
|
45
|
+
lavavu/shaders/pointShader.vert,sha256=mDMF4wAPvHELXT5rXN_QZFezxvK4q50Mdm-qZZJ7FYI,1160
|
46
|
+
lavavu/shaders/lineShader.frag,sha256=2PQBMcb149jVKnsBhTvU1vf94x91O0kAdOBTSs8OpGY,888
|
47
|
+
lavavu/shaders/fontShader.frag,sha256=clgomy2lu-1u7w0GwFd0BNU_L3-SkYt8zv03N5ciJug,351
|
48
|
+
lavavu/shaders/triShader.frag,sha256=SkPatq2s7Osa5o7U3lg-7We8ldY0oHZHCLuQjRY4Vgk,4601
|
49
|
+
lavavu/shaders/default.vert,sha256=3xKybexF39UGsESMLQQcqHlE1MgLCDEXUMLz4sr5blQ,352
|
50
|
+
lavavu/shaders/triShader.vert,sha256=H7rTS-WO5QiT9uP1ClhufQM8minSWknJ9UvKAEVnzRU,1078
|
51
|
+
lavavu/shaders/lineShader.vert,sha256=5HDJMphXW438yMc0I2NtBdnvF6uXrOUac9hjk3S7mfk,501
|
44
52
|
lavavu/shaders/fontShader.vert,sha256=yCBmRugaPUeUQUdIh62-AK_5KELiJqVS2M82iyIqPwo,290
|
45
|
-
lavavu/shaders/pointShader.frag,sha256=
|
53
|
+
lavavu/shaders/pointShader.frag,sha256=3zREBdsimlL9fAXBPjhzomGaFUWmlG_QYkhwMTVURHQ,3291
|
46
54
|
lavavu/shaders/volumeShader.vert,sha256=uGdQjGqi7V5kE6V7nxymfugtU4cbf6u570xBy13RgmY,78
|
47
|
-
lavavu/shaders/default.frag,sha256=
|
48
|
-
lavavu-1.8.84.dist-info/LICENSE.md,sha256=EhfNgC6BYh5gDEaq4tcrN3S0wbO4CtJO46botJnCF8c,8603
|
49
|
-
lavavu-1.8.84.dist-info/RECORD,,
|
50
|
-
lavavu-1.8.84.dist-info/WHEEL,sha256=poswUSLteh-e2fl9um8bzvGmfWIWqlPA5zz46K8O6JE,109
|
51
|
-
lavavu-1.8.84.dist-info/entry_points.txt,sha256=LC2qXR6EMe45Cb7zGAF99R9HFrAECP6Qkp_YuG6HZB0,44
|
52
|
-
lavavu-1.8.84.dist-info/top_level.txt,sha256=JptS0k1nlBumjLs_0hITr3_XUJhxqvKBXD2jGho3E3A,7
|
53
|
-
lavavu-1.8.84.dist-info/METADATA,sha256=MFufiRsa4bX84GlDYNKdHy3uH7jsoAK4xCJu-jUjkHE,18237
|
55
|
+
lavavu/shaders/default.frag,sha256=5XLYVfLwzN0sFT3aMYGmxbyquA_cmndp55YCOuy1t4E,180
|
File without changes
|
File without changes
|
File without changes
|