lavavu 1.9.5__cp313-cp313-macosx_11_0_arm64.whl → 1.9.7__cp313-cp313-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.
Binary file
lavavu/html/control.js CHANGED
@@ -87,7 +87,7 @@ function WindowInteractor(id, uid, port) {
87
87
 
88
88
  //Several possible modes to try
89
89
  //Modern JupyterHub lab URL
90
- var regex = /\/lab\//;
90
+ var regex = /\/lab(\/|\?|$)/; //Match "/lab" at end of url or "/lab/" or "/lab?" anywhere
91
91
  var parsed = regex.exec(loc.href);
92
92
  if (parsed && parsed.length > 0) {
93
93
  connect(loc.href.substring(0,parsed.index) + "/proxy/" + port);
lavavu/html/menu.js CHANGED
@@ -123,7 +123,12 @@ function menu_addctrls(menu, obj, viewer, onchange) {
123
123
  //Check if it has been set on the target object
124
124
  if (prop in obj) {
125
125
  //console.log(prop + " ==> " + JSON.stringify(viewer.dict[prop]));
126
- menu_addctrl(menu, obj, viewer, prop, onchange);
126
+ try {
127
+ //Catch errors and continue gracefully
128
+ menu_addctrl(menu, obj, viewer, prop, onchange);
129
+ } catch(e) {
130
+ console.log("Error adding control to menu: " + e);
131
+ }
127
132
 
128
133
  } else {
129
134
  //Save list of properties without controls
@@ -159,9 +164,9 @@ function menu_addctrls(menu, obj, viewer, onchange) {
159
164
 
160
165
  function menu_addcmaps(menu, obj, viewer, onchange) {
161
166
  //Colourmap editing menu
162
- if (viewer.cgui.prmenu) viewer.cgui.removeFolder(viewer.cgui.prmenu);
163
- if (viewer.cgui.cmenu) viewer.cgui.removeFolder(viewer.cgui.cmenu);
164
- if (viewer.cgui.pomenu) viewer.cgui.removeFolder(viewer.cgui.pomenu);
167
+ if (viewer.cgui.prmenu) viewer.cgui.remove(viewer.cgui.prmenu);
168
+ if (viewer.cgui.cmenu) viewer.cgui.remove(viewer.cgui.cmenu);
169
+ if (viewer.cgui.pomenu) viewer.cgui.remove(viewer.cgui.pomenu);
165
170
  viewer.cgui.prmenu = viewer.cgui.addFolder("Properties");
166
171
  viewer.cgui.cmenu = viewer.cgui.addFolder("Colours");
167
172
  viewer.cgui.pomenu = viewer.cgui.addFolder("Positions");
lavavu/html/webview.html CHANGED
@@ -27,7 +27,7 @@
27
27
 
28
28
  <input id="fileinput" type="file" style="visibility:hidden" onchange="useFileInput(this)" />
29
29
 
30
- <script async src="https://cdn.jsdelivr.net/gh/lavavu/lavavu.github.io@1.9.5/LavaVu-amalgamated.min.js"></script>
30
+ <script async src="https://cdn.jsdelivr.net/gh/lavavu/lavavu.github.io@1.9.7/LavaVu-amalgamated.min.js"></script>
31
31
  <!--script src="dat.gui.min.js"></script>
32
32
  <script src="OK-min.js"></script>
33
33
 
lavavu/lavavu.py CHANGED
@@ -23,7 +23,7 @@ __all__ = ['Viewer', 'Object', 'Properties', 'ColourMap', 'DrawData', 'Figure',
23
23
  import os
24
24
  #must be an object or won't be referenced from __init__.py import
25
25
  #(enures values are passed on when set externally)
26
- settings = {"default_args" : [], "echo_fails" : False, "quality_override" : None}
26
+ settings = {"default_args" : [], "echo_fails" : False, "quality_override" : None, "test_mode" : False}
27
27
  #Default arguments for viewer creation
28
28
  _val = os.environ.get('LV_ARGS')
29
29
  if _val:
@@ -36,6 +36,10 @@ if _val:
36
36
  _val = os.environ.get('LV_QUALITY')
37
37
  if _val:
38
38
  settings["quality_override"] = int(_val)
39
+ #Test mode - changes some behaviour to support automated testing
40
+ _val = os.environ.get('LV_TEST')
41
+ if _val:
42
+ settings["test_mode"] = bool(_val)
39
43
 
40
44
  import json
41
45
  import math
@@ -54,6 +58,7 @@ import asyncio
54
58
  import quaternion as quat
55
59
  import platform
56
60
  import matplotlib
61
+ from pathlib import Path
57
62
 
58
63
  if sys.version_info[0] < 3:
59
64
  print("Python 3 required. LavaVu no longer supports Python 2.7.")
@@ -3562,7 +3567,6 @@ class Viewer(dict):
3562
3567
  ll = len(self.objects.list) #Save list length before load
3563
3568
  if not self.app.loadFile(filename):
3564
3569
  #Support trimesh formats
3565
- from pathlib import Path
3566
3570
  path = Path(filename)
3567
3571
  ext = path.suffix.lower()[1:]
3568
3572
  import convert
@@ -3876,6 +3880,9 @@ class Viewer(dict):
3876
3880
  """
3877
3881
  Render a new frame, explicit display update
3878
3882
  """
3883
+ if settings["test_mode"] and self.recording and self.recording.framecount != 0:
3884
+ #Skip rendering all except first and last frames when testing
3885
+ return
3879
3886
  self.app.render()
3880
3887
  #Video recording?
3881
3888
  if self.recording:
@@ -4187,7 +4194,7 @@ class Viewer(dict):
4187
4194
  from IPython.display import display,HTML,Javascript
4188
4195
  display(Javascript(js + code))
4189
4196
 
4190
- def video(self, filename="", resolution=(0,0), fps=30, quality=0, encoder="h264", player=None, options={}, **kwargs):
4197
+ def video(self, filename="", resolution=(0,0), fps=30, quality=2, encoder="h264", embed=False, player=None, options={}, **kwargs):
4191
4198
  """
4192
4199
  Record and show the generated video inline within an ipython notebook.
4193
4200
 
@@ -4214,6 +4221,9 @@ class Viewer(dict):
4214
4221
  If omitted will use default settings, can fine tune settings in kwargs
4215
4222
  encoder : str
4216
4223
  Name of encoder to use, eg: "h264" (default), "mpeg"
4224
+ embed : bool
4225
+ Set to true to embed the video file rather than link to url
4226
+ Not recommended for large videos, default is False
4217
4227
  player : dict
4218
4228
  Args to pass to the player when the video is finished, eg:
4219
4229
  {"width" : 800, "height", 400, "params": "controls autoplay"}
@@ -4228,12 +4238,11 @@ class Viewer(dict):
4228
4238
  recorder : Video(object)
4229
4239
  Context manager object that controls the video recording
4230
4240
  """
4231
- return Video(self, filename, resolution, fps, quality, encoder, player, options, **kwargs)
4241
+ return Video(self, filename, resolution, fps, quality, encoder, embed, player, options, **kwargs)
4232
4242
 
4233
- def video_steps(self, filename="", start=0, end=0, resolution=(0,0), fps=30, quality=2, encoder="h264", player=None, options={}, **kwargs):
4243
+ def video_steps(self, filename="", start=0, end=0, resolution=(0,0), fps=30, quality=2, encoder="h264", embed=False, player=None, options={}, **kwargs):
4244
+ my_func.__doc__
4234
4245
  """
4235
- TODO: Fix to use pyAV
4236
-
4237
4246
  Record a video of the model by looping through all time steps
4238
4247
 
4239
4248
  Shows the generated video inline within an ipython notebook.
@@ -4245,21 +4254,12 @@ class Viewer(dict):
4245
4254
 
4246
4255
  Parameters
4247
4256
  ----------
4248
- filename : str
4249
- Name of the file to save, if not provided a default will be used
4250
4257
  start : int
4251
4258
  First timestep to record, if not specified will use first available
4252
4259
  end : int
4253
4260
  Last timestep to record, if not specified will use last available
4254
- resolution : list or tuple
4255
- Video resolution in pixels [x,y]
4256
- fps : int
4257
- Frames to output per second of video
4258
- quality : int
4259
- Encoding quality, 1=low, 2=medium(default), 3=high, higher quality reduces
4260
- encoding artifacts at cost of larger file size
4261
- **kwargs :
4262
- Any additional keyword args will also be passed as options to the encoder
4261
+
4262
+ All other parameters same as video()
4263
4263
  """
4264
4264
 
4265
4265
  try:
@@ -4267,7 +4267,7 @@ class Viewer(dict):
4267
4267
  if end == 0: end = len(steps)
4268
4268
  steps = steps[start:end]
4269
4269
  from tqdm.notebook import tqdm
4270
- with Video(self, filename, resolution, fps, quality, encoder, player, options, **kwargs):
4270
+ with Video(self, filename, resolution, fps, quality, encoder, embed, player, options, **kwargs):
4271
4271
  for s in tqdm(steps, desc='Rendering loop'):
4272
4272
  self.timestep(s)
4273
4273
  self.render()
@@ -4312,7 +4312,7 @@ class Viewer(dict):
4312
4312
  #This is thread safe as doesn't load texture
4313
4313
  return self.app.imageFromFile(filename)
4314
4314
 
4315
- def testimages(self, imagelist=None, tolerance=TOL_DEFAULT, expectedPath='expected/', outputPath='./', clear=True):
4315
+ def testimages(self, imagelist=None, tolerance=TOL_DEFAULT, expectedPath='expected/', outputPath='./', png=True, jpg=False, clear=True):
4316
4316
  """
4317
4317
  Compare a list of images to expected images for testing
4318
4318
 
@@ -4327,6 +4327,10 @@ class Viewer(dict):
4327
4327
  Where to find the expected result images (should have the same filenames as output images)
4328
4328
  outputPath : str
4329
4329
  Where to find the output images
4330
+ png : boolean
4331
+ Check png image outputs, defaults to True
4332
+ jpng : boolean
4333
+ Check jpg image outputs, defaults to False
4330
4334
  clear : boolean
4331
4335
  If the test passes the output images will be deleted, set to False to disable deletion
4332
4336
  """
@@ -4340,14 +4344,17 @@ class Viewer(dict):
4340
4344
  #No expected images yet, just get images in cwd
4341
4345
  #will be copied in to expected in testimage()
4342
4346
  pass
4343
- imagelist = glob.glob("*.png")
4344
- imagelist += glob.glob("*.jpg")
4347
+ imagelist = []
4348
+ if png:
4349
+ imagelist += glob.glob("*.png")
4350
+ if jpg:
4351
+ imagelist += glob.glob("*.jpg")
4345
4352
  imagelist.sort(key=os.path.getmtime)
4346
4353
  os.chdir(cwd)
4347
4354
 
4348
4355
  for f in sorted(imagelist):
4349
- outfile = outputPath+f
4350
- expfile = expectedPath+f
4356
+ outfile = os.path.join(outputPath, f)
4357
+ expfile = os.path.join(expectedPath, f)
4351
4358
  results.append(self.testimage(expfile, outfile, tolerance, clear))
4352
4359
 
4353
4360
  #Combined result
@@ -5415,37 +5422,44 @@ def player(filename, params="controls autoplay loop", **kwargs):
5415
5422
 
5416
5423
  if is_notebook():
5417
5424
  from IPython.display import display,HTML,Video,Javascript
5418
- import uuid
5419
- vid = 'video_' + str(uuid.uuid4())[:8]
5420
5425
 
5421
5426
  # Fallback - replace url on gadi and similar jupyterhub installs with
5422
5427
  # fixed working directory that doesn't match notebook dir
5423
5428
  # check the video tag url and remove subpath on 404 error
5424
- display(Javascript(f"""
5425
- function video_error(el) {{
5426
- let url = el.src;
5427
- console.log("Bad video url: " + url);
5428
- let toppath = "/files/home/"
5429
- let baseurl = url.substring(0, url.indexOf(toppath)+toppath.length);
5430
- let endurl = url.substring(url.indexOf("{filename}"));
5431
- let fixed = baseurl + endurl;
5432
- if (url != fixed) {{
5433
- console.log("Replaced video url: " + fixed);
5434
- el.src = fixed;
5429
+ onerror = """{
5430
+ let url = this.src;
5431
+ console.log('Error in video url: ' + url);
5432
+ var urlp = new window.URL(url);
5433
+ let toppath = '/files/home/';
5434
+ let startidx = urlp.pathname.indexOf(toppath);
5435
+ if (startidx < 0) {
5436
+ toppath = '/files/';
5437
+ startidx = urlp.pathname.indexOf(toppath);
5438
+ }
5439
+ if (startidx >= 0) {
5440
+ let filename = urlp.pathname.split('/').pop();
5441
+ let base = urlp.pathname.substring(0, startidx+toppath.length);
5442
+ urlp.pathname = base + filename;
5443
+ if (url != urlp.href) {
5444
+ console.log('Replaced video url: ' + urlp.href);
5445
+ this.src = urlp.href;
5435
5446
  //Also fix download link
5436
- document.getElementById('link_{vid}').href = fixed;
5437
- }} else {{
5438
- console.log("Not replacing video url, no change: " + fixed);
5439
- }}
5440
- }}
5441
- """))
5442
-
5443
- #Embed player
5444
- filename = os.path.relpath(filename)
5445
- display(Video(url=filename, html_attributes=f'id="{vid}" onerror="video_error(this)"' + params, **kwargs))
5447
+ let link = document.getElementById('link_' + this.id);
5448
+ if (link) link.href = urlp.href;
5449
+ }
5450
+ }
5451
+ }"""
5446
5452
 
5447
- #Add download link
5448
- display(HTML(f'<a id="link_{vid}" href="{filename}" download>Download Video</a>'))
5453
+ if "embed" in kwargs:
5454
+ #Not needed if embedding
5455
+ onerror = ""
5456
+
5457
+ #Display player and download link
5458
+ import uuid
5459
+ vid = 'video_' + str(uuid.uuid4())[:8]
5460
+ filename = os.path.relpath(filename)
5461
+ display(Video(filename=filename, html_attributes=f'id="{vid}" onerror="{onerror}" ' + params, **kwargs),
5462
+ HTML(f'<a id="link_{vid}" href="{filename}" download>Download Video</a>'))
5449
5463
 
5450
5464
  #Class for managing video animation recording
5451
5465
  class Video(object):
@@ -5465,7 +5479,7 @@ class Video(object):
5465
5479
  ... lv.rotate('y', 10) # doctest: +SKIP
5466
5480
  ... lv.render() # doctest: +SKIP
5467
5481
  """
5468
- def __init__(self, viewer, filename="output.mp4", resolution=(0,0), framerate=30, quality=2, encoder="h264", player=None, options={}, **kwargs):
5482
+ def __init__(self, viewer, filename="output.mp4", resolution=(0,0), framerate=30, quality=2, encoder="h264", embed=False, player=None, options={}, **kwargs):
5469
5483
  """
5470
5484
  Record and show the generated video inline within an ipython notebook.
5471
5485
 
@@ -5492,6 +5506,9 @@ class Video(object):
5492
5506
  Video resolution in pixels [x,y]
5493
5507
  encoder : str
5494
5508
  Name of encoder to use, eg: "h264" (default), "mpeg"
5509
+ embed : bool
5510
+ Set to true to embed the video file rather than link to url
5511
+ Not recommended for large videos, default is False
5495
5512
  player : dict
5496
5513
  Args to pass to the player when the video is finished, eg:
5497
5514
  {"width" : 800, "height", 400, "params": "controls autoplay"}
@@ -5501,9 +5518,6 @@ class Video(object):
5501
5518
  **kwargs :
5502
5519
  Any additional keyword args will also be passed as options to the encoder
5503
5520
  """
5504
- if av is None:
5505
- raise(ImportError("Video output not supported without pyAV - pip install av"))
5506
- return
5507
5521
  self.resolution = list(resolution)
5508
5522
  if self.resolution[0] == 0 or self.resolution[1] == 0:
5509
5523
  self.resolution = (viewer.app.viewer.width, viewer.app.viewer.height)
@@ -5512,7 +5526,20 @@ class Video(object):
5512
5526
  self.framerate = framerate
5513
5527
  self.quality = quality
5514
5528
  self.viewer = viewer
5515
- self.filename = filename
5529
+ self.filename = Path(filename)
5530
+ if settings["test_mode"]:
5531
+ #Force png output when testing
5532
+ encoder = 'png'
5533
+ if av is None or encoder == 'png' or encoder == 'jpg':
5534
+ if av is None:
5535
+ print("Video output not supported without pyAV - pip install av, writing image frames instead")
5536
+ self.encoder = 'png' if encoder == 'png' else 'jpg'
5537
+ p = self.filename
5538
+ self.basename = p.stem
5539
+ self.filename = p.parent / p.stem
5540
+ self.framecount = 0
5541
+ return
5542
+
5516
5543
  self.player = player
5517
5544
  if self.player is None:
5518
5545
  #Default player is half output resolution, unless < 900 then full
@@ -5526,6 +5553,8 @@ class Video(object):
5526
5553
  self.player = {"width": self.resolution[0]//2, "height": self.resolution[1]//2}
5527
5554
  else:
5528
5555
  self.player = {}
5556
+ if embed:
5557
+ self.player["embed"] = True
5529
5558
  self.encoder = encoder
5530
5559
  self.options = options
5531
5560
  #Also include extra args
@@ -5542,6 +5571,12 @@ class Video(object):
5542
5571
  #Compression level, lower = high quality
5543
5572
  #See also: https://github.com/PyAV-Org/PyAV/blob/main/tests/test_encode.py
5544
5573
  options = {}
5574
+ if self.encoder == 'jpg' or self.encoder == 'png':
5575
+ if not settings["test_mode"]:
5576
+ self.filename.mkdir(exist_ok=True)
5577
+ self.viewer.recording = self
5578
+ return
5579
+
5545
5580
  if self.encoder == 'h264' or self.encoder == 'libx265':
5546
5581
  #Only have default options for h264/265 for now
5547
5582
  if self.quality == 1:
@@ -5571,7 +5606,7 @@ class Video(object):
5571
5606
  options.update(self.options)
5572
5607
 
5573
5608
  #print(options)
5574
- self.container = av.open(self.filename, mode="w")
5609
+ self.container = av.open(str(self.filename), mode="w")
5575
5610
  self.stream = self.container.add_stream(self.encoder, rate=self.framerate, options=options)
5576
5611
  self.stream.width = self.resolution[0]
5577
5612
  self.stream.height = self.resolution[1]
@@ -5597,10 +5632,19 @@ class Video(object):
5597
5632
  Write a frame, called when viewer.render() is called
5598
5633
  while a recording is in progress
5599
5634
  """
5600
- img = self.viewer.rawimage(resolution=self.resolution, channels=3)
5601
- frame = av.VideoFrame.from_ndarray(img.data, format="rgb24")
5602
- for packet in self.stream.encode(frame):
5603
- self.container.mux(packet)
5635
+ if self.encoder == 'jpg' or self.encoder == 'png':
5636
+ if settings["test_mode"]:
5637
+ #Don't output in subdir
5638
+ fn = f"{self.framecount:06}_{self.basename}.{self.encoder}"
5639
+ else:
5640
+ fn = self.filename / f"{self.framecount:06}_{self.basename}.{self.encoder}"
5641
+ self.framecount += 1
5642
+ self.viewer.image(str(fn), resolution=self.resolution)
5643
+ else:
5644
+ img = self.viewer.rawimage(resolution=self.resolution, channels=3)
5645
+ frame = av.VideoFrame.from_ndarray(img.data, format="rgb24")
5646
+ for packet in self.stream.encode(frame):
5647
+ self.container.mux(packet)
5604
5648
 
5605
5649
  def pause(self):
5606
5650
  """
@@ -5616,6 +5660,15 @@ class Video(object):
5616
5660
  Stop recording, final frames will be written and file closed, ready to play.
5617
5661
  No further frames will be added to the video
5618
5662
  """
5663
+ if self.encoder == 'jpg' or self.encoder == 'png':
5664
+ self.viewer.recording = None
5665
+ if settings["test_mode"]:
5666
+ #Render the last frame for tests
5667
+ self.viewer.app.render()
5668
+ fn = f"{self.framecount:06}_{self.basename}.{self.encoder}"
5669
+ self.viewer.image(str(fn), resolution=self.resolution)
5670
+ self.framecount = 0
5671
+ return
5619
5672
  # Flush stream
5620
5673
  for packet in self.stream.encode():
5621
5674
  self.container.mux(packet)
@@ -5643,7 +5696,14 @@ class Video(object):
5643
5696
  if image.size == self.resolution[0] * self.resolution[1] * 4:
5644
5697
  image = image.reshape(self.resolution[0], self.resolution[1], 4)
5645
5698
  image = image[::,::,:3] #Remove alpha channel
5646
- #self.encoder.copyframe(image.ravel())
5699
+
5700
+ if self.encoder == 'jpg' or self.encoder == 'png':
5701
+ from PIL import Image as PILImage
5702
+ img = PILImage.fromarray(image)
5703
+ fn = self.filename / f"{self.framecount:06}_{self.basename}.{self.encoder}"
5704
+ self.framecount += 1
5705
+ img.save(fn)
5706
+ return
5647
5707
 
5648
5708
  frame = av.VideoFrame.from_ndarray(image, format="rgb24")
5649
5709
  for packet in self.stream.encode(frame):
@@ -5653,7 +5713,11 @@ class Video(object):
5653
5713
  """
5654
5714
  Show the video in an inline player if in an interactive notebook
5655
5715
  """
5656
- player(self.filename, **self.player)
5716
+ if self.encoder == 'jpg' or self.encoder == 'png':
5717
+ from IPython.display import display,HTML
5718
+ display(HTML('<p>Video written to images, no player available</p>'))
5719
+ else:
5720
+ player(self.filename, **self.player)
5657
5721
 
5658
5722
  def __enter__(self):
5659
5723
  self.start()
@@ -5666,6 +5730,8 @@ class Video(object):
5666
5730
  self.play()
5667
5731
  else:
5668
5732
  print('Recording failed: ', exc_value)
5733
+ import traceback
5734
+ print(traceback.format_exc())
5669
5735
  return True
5670
5736
 
5671
5737
  #Wrapper class for raw image data
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lavavu
3
- Version: 1.9.5
3
+ Version: 1.9.7
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
@@ -224,7 +224,7 @@ Dynamic: license-file
224
224
  [![Build Status](https://github.com/lavavu/LavaVu/workflows/Test/badge.svg)](https://github.com/lavavu/LavaVu/actions?query=workflow:Test)
225
225
  [![Deploy Status](https://github.com/lavavu/LavaVu/workflows/Deploy/badge.svg?branch=1.7.3)](https://github.com/lavavu/LavaVu/actions?query=workflow:Deploy)
226
226
  [![DOI](https://zenodo.org/badge/45163055.svg)](https://zenodo.org/badge/latestdoi/45163055)
227
- [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/lavavu/LavaVu/1.9.5)
227
+ [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/lavavu/LavaVu/1.9.7)
228
228
 
229
229
  A scientific visualisation tool with a python interface for fast and flexible visual analysis.
230
230
 
@@ -1,10 +1,4 @@
1
- lavavu-1.9.5.dist-info/RECORD,,
2
- lavavu-1.9.5.dist-info/WHEEL,sha256=Cxq5pla4scSj9raD9htoFbIhfTk0lSQlQLVCyAjgIi4,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
1
+ lavavu/lavavu.py,sha256=v7tXwp6gQzu1F05hHyALng8FXznv4rVwdCJ3sO65O8o,221223
8
2
  lavavu/vutils.py,sha256=6Vm_xl1bp9mWlfk7jgLDwbRw-tdE_oxin77YkLel3_4,5437
9
3
  lavavu/dict.json,sha256=lsZEHc7Bb6_lt7tkSBQMgkq7AEn_2hnhWzzdokmvIY8,52729
10
4
  lavavu/server.py,sha256=L-_yPCbNfwYxJCPjDQtr_lxPnDp4oMNVFyxXhBERYrQ,12468
@@ -15,12 +9,12 @@ lavavu/convert.py,sha256=tbYRjLE2l1hI4d6tsW41Lia1JXmrWSc0-JAYCiMrjys,35516
15
9
  lavavu/control.py,sha256=s32rtLPXXYtxpeXd6-iHdupmaMTJ3KhK6Vq-CLjf9OQ,66755
16
10
  lavavu/__init__.py,sha256=JroZQiUbuVN7ifixk2zNDGlyLGaM8bqfRbw4D_F9qIQ,191
17
11
  lavavu/amalgamate.py,sha256=Xloq1IZ4VUvYiROzQtwKcQIWC65c7EZrdiGVhZdolL8,586
18
- lavavu/_LavaVuPython.cpython-313-darwin.so,sha256=v8ZUe162pI-u7iamVu383Wmbp-RFPodlV6gmoqcmqKY,3927376
12
+ lavavu/_LavaVuPython.cpython-313-darwin.so,sha256=7BX8bLplJs0YG-UIabUasfipkxPCMXkE7N9w9K_csxY,3927376
19
13
  lavavu/aserver.py,sha256=SfFvLeDTcx1XtS8fY_HIrDmh3q9HicCBRSAriY5yyOE,12003
20
14
  lavavu/font.bin,sha256=fvi5zkvmq6gh9v3jXedBVuxNJWKmHtbjECzv6eT9wb4,225360
21
15
  lavavu/__main__.py,sha256=EbDetijCjyoiNxmExqnDGoRVs996tSVave5DML9zuMY,235
22
16
  lavavu/html/control.css,sha256=PVLwmle00ciEckUV5ZIRmI3Whxhl7-mlVexnyyxoU70,3259
23
- lavavu/html/control.js,sha256=oV24eJZ0vfuCxF3fO60eeJSkNFJ9hUkSCThHGJS1Wvc,11652
17
+ lavavu/html/control.js,sha256=dBjFHgDal3aixVWoQuMOt_ZyhiGSAcEUFJJx9I_ndOQ,11719
24
18
  lavavu/html/gui.css,sha256=PRDLsYwM6cgLC9zZsEAG0dnnSd-HYH6oSEfsdEBkuxk,582
25
19
  lavavu/html/favicon.ico,sha256=OrIWwvxOSnOCuynrGRUyEIVQng0ZwA9Rrz89S9eiog0,1150
26
20
  lavavu/html/LavaVu-amalgamated.css,sha256=iE2xrxFcwmY0AcASrXxNa_RpvFEbS_YO4H5OILbPteE,8640
@@ -33,11 +27,11 @@ lavavu/html/dat.gui.min.js,sha256=S4_QjoXe4IOpU0f0Sj5jEQLTWPoX9uRl1ohB91jyhuw,56
33
27
  lavavu/html/OK-min.js,sha256=-4Gc1-dWfxP_w6r9ZOHa8u-X2BlGUoSQbX68lwCxQ3E,39115
34
28
  lavavu/html/emscripten.css,sha256=wkaIJhXaxuMchinQX9Z8c12cJomyvFQMeIZ62WGQEPQ,1813
35
29
  lavavu/html/drawbox.js,sha256=SJxFSmWd7QVFI5__66hFkKzLKeqg1JPcx-gJuqdMkXw,34590
36
- lavavu/html/webview.html,sha256=aUS6ZlGmrsZ4TkKv1-zKV_g_QQezWxL4DN0-ALnAOZs,1521
30
+ lavavu/html/webview.html,sha256=Tjv9TWx1k6ovHY8xxaG_NGwHwuiDC0Hz5Npm39afHAU,1521
37
31
  lavavu/html/emscripten-template.js,sha256=h63mzl3Lv7aQT1wMOiOucPOvHTJjpKkzsL-SFVYaZlA,6135
38
32
  lavavu/html/draw.js,sha256=57LlHlYRh0IvWVwzGDnF6PaCxYLzokpokLNCuZlG1ds,84108
39
33
  lavavu/html/dat-gui-light-theme.css,sha256=uPhvJs-1IAsdxudItyOw8lZy8Hrih0zmFM1u-xRwZ-M,1142
40
- lavavu/html/menu.js,sha256=WCli3UYcQ7frjNq0aAXNALu33iNiN8lpTYwKZ7pUcn4,21501
34
+ lavavu/html/menu.js,sha256=42h-BCnrmEpW4IdZRKC_FIXUVczJP0sm4ciZ2ccfs-k,21630
41
35
  lavavu/html/baseviewer.js,sha256=u3UhC1At6rMBKmcQ7d2DXTRxQ20wsQkc4lqA-7sL7i4,9567
42
36
  lavavu/osmesa/LavaVuPython.py,sha256=ixhceiAr0gGGfCe3d2cY0IIgS4hbgoYJGa_RfgAmmrU,33207
43
37
  lavavu/osmesa/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -53,3 +47,9 @@ lavavu/shaders/fontShader.vert,sha256=yCBmRugaPUeUQUdIh62-AK_5KELiJqVS2M82iyIqPw
53
47
  lavavu/shaders/pointShader.frag,sha256=3zREBdsimlL9fAXBPjhzomGaFUWmlG_QYkhwMTVURHQ,3291
54
48
  lavavu/shaders/volumeShader.vert,sha256=uGdQjGqi7V5kE6V7nxymfugtU4cbf6u570xBy13RgmY,78
55
49
  lavavu/shaders/default.frag,sha256=5XLYVfLwzN0sFT3aMYGmxbyquA_cmndp55YCOuy1t4E,180
50
+ lavavu-1.9.7.dist-info/RECORD,,
51
+ lavavu-1.9.7.dist-info/WHEEL,sha256=89IgJaLF6X8hMUjC4DKLcrcADd48Z33aA8odPAkCuhg,136
52
+ lavavu-1.9.7.dist-info/entry_points.txt,sha256=LC2qXR6EMe45Cb7zGAF99R9HFrAECP6Qkp_YuG6HZB0,44
53
+ lavavu-1.9.7.dist-info/top_level.txt,sha256=JptS0k1nlBumjLs_0hITr3_XUJhxqvKBXD2jGho3E3A,7
54
+ lavavu-1.9.7.dist-info/METADATA,sha256=pDV89WKg6njzJArxsKbduk1rcj2NHSb75oV1lUtNx30,17877
55
+ lavavu-1.9.7.dist-info/licenses/LICENSE.md,sha256=EhfNgC6BYh5gDEaq4tcrN3S0wbO4CtJO46botJnCF8c,8603
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (78.1.0)
2
+ Generator: setuptools (80.4.0)
3
3
  Root-Is-Purelib: false
4
4
  Tag: cp313-cp313-macosx_11_0_arm64
5
5
  Generator: delocate 0.13.0