girder-large-image 1.29.3.dev6__tar.gz → 1.29.3.dev22__tar.gz

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.
Files changed (80) hide show
  1. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/PKG-INFO +3 -3
  2. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/__init__.py +22 -0
  3. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/girder_tilesource.py +5 -1
  4. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/rest/large_image_resource.py +68 -2
  5. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image.egg-info/PKG-INFO +3 -3
  6. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image.egg-info/requires.txt +2 -2
  7. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/test_girder/test_large_image.py +31 -0
  8. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/LICENSE +0 -0
  9. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/README.rst +0 -0
  10. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/constants.py +0 -0
  11. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/loadmodelcache.py +0 -0
  12. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/models/__init__.py +0 -0
  13. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/models/image_item.py +0 -0
  14. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/rest/__init__.py +0 -0
  15. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/rest/item_meta.py +0 -0
  16. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/rest/tiles.py +0 -0
  17. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/eventStream.js +0 -0
  18. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/extra/.gitignore +0 -0
  19. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/index.js +0 -0
  20. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/main.js +0 -0
  21. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/package.json +0 -0
  22. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/routes.js +0 -0
  23. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/stylesheets/fileList.styl +0 -0
  24. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/stylesheets/imageViewerSelectWidget.styl +0 -0
  25. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/stylesheets/itemList.styl +0 -0
  26. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/stylesheets/itemView.styl +0 -0
  27. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/stylesheets/itemViewCodemirror.styl +0 -0
  28. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/stylesheets/largeImageConfig.styl +0 -0
  29. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/stylesheets/metadataWidget.styl +0 -0
  30. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/templates/imageViewerSelectWidget.pug +0 -0
  31. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/templates/itemList.pug +0 -0
  32. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/templates/itemView.pug +0 -0
  33. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/templates/itemViewCodemirror.pug +0 -0
  34. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/templates/largeImageConfig.pug +0 -0
  35. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/templates/largeImage_fileAction.pug +0 -0
  36. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/templates/metadataWidget.pug +0 -0
  37. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/templates/metadatumEditWidget.pug +0 -0
  38. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/views/configView.js +0 -0
  39. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/views/fileList.js +0 -0
  40. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/views/imageViewerSelectWidget.js +0 -0
  41. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/views/imageViewerWidget/base.js +0 -0
  42. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/views/imageViewerWidget/geojs.js +0 -0
  43. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/views/imageViewerWidget/index.js +0 -0
  44. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/views/imageViewerWidget/leaflet.js +0 -0
  45. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/views/imageViewerWidget/openlayers.js +0 -0
  46. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/views/imageViewerWidget/openseadragon.js +0 -0
  47. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/views/imageViewerWidget/setFrameQuad.js +0 -0
  48. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/views/imageViewerWidget/slideatlas.js +0 -0
  49. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/views/index.js +0 -0
  50. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/views/itemList.js +0 -0
  51. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/views/itemView.js +0 -0
  52. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/views/itemViewCodemirror.js +0 -0
  53. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/views/itemViewWidget.js +0 -0
  54. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/views/metadataWidget.js +0 -0
  55. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/vue/components/CompositeLayers.vue +0 -0
  56. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/vue/components/DualInput.vue +0 -0
  57. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/vue/components/FrameSelector.vue +0 -0
  58. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/vue/components/HistogramEditor.vue +0 -0
  59. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/vue/components/PresetsMenu.vue +0 -0
  60. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/vue/utils/clamp.js +0 -0
  61. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/vue/utils/colors.js +0 -0
  62. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/vue/utils/drag.js +0 -0
  63. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image/web_client/webpack.helper.js +0 -0
  64. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image.egg-info/SOURCES.txt +0 -0
  65. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image.egg-info/dependency_links.txt +0 -0
  66. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image.egg-info/entry_points.txt +0 -0
  67. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image.egg-info/not-zip-safe +0 -0
  68. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/girder_large_image.egg-info/top_level.txt +0 -0
  69. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/pyproject.toml +0 -0
  70. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/setup.cfg +0 -0
  71. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/setup.py +0 -0
  72. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/test_girder/__init__.py +0 -0
  73. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/test_girder/conftest.py +0 -0
  74. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/test_girder/girder_utilities.py +0 -0
  75. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/test_girder/test_tiles_rest.py +0 -0
  76. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/test_girder/test_web_client.py +0 -0
  77. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/test_girder/web_client_specs/.eslintrc +0 -0
  78. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/test_girder/web_client_specs/imageViewerSpec.js +0 -0
  79. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/test_girder/web_client_specs/largeImageSpec.js +0 -0
  80. {girder-large-image-1.29.3.dev6 → girder-large-image-1.29.3.dev22}/test_girder/web_client_specs/otherFeatures.js +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: girder-large-image
3
- Version: 1.29.3.dev6
3
+ Version: 1.29.3.dev22
4
4
  Summary: A Girder plugin to work with large, multiresolution images.
5
5
  Home-page: https://github.com/girder/large_image
6
6
  Author: Kitware, Inc.
@@ -19,9 +19,9 @@ Requires-Python: >=3.8
19
19
  License-File: LICENSE
20
20
  Requires-Dist: girder>=3.1.18
21
21
  Requires-Dist: girder-jobs>=3.0.3
22
- Requires-Dist: large_image>=1.29.3.dev6
22
+ Requires-Dist: large_image>=1.29.3.dev22
23
23
  Provides-Extra: tasks
24
- Requires-Dist: large-image-tasks[girder]>=1.29.3.dev6; extra == "tasks"
24
+ Requires-Dist: large-image-tasks[girder]>=1.29.3.dev22; extra == "tasks"
25
25
  Requires-Dist: girder-worker[girder]>=0.6.0; extra == "tasks"
26
26
 
27
27
  A Girder plugin to work with large, multiresolution images.
@@ -673,6 +673,26 @@ def unbindGirderEventsByHandlerName(handlerName):
673
673
  events.unbind(eventName, handlerName)
674
674
 
675
675
 
676
+ def patchMount():
677
+ try:
678
+ import girder.cli.mount
679
+
680
+ def _flatItemFile(self, item):
681
+ return next(File().collection.aggregate([
682
+ {'$match': {'itemId': item['_id']}},
683
+ ] + ([
684
+ {'$addFields': {'matchLI': {'$eq': ['$_id', item['largeImage']['fileId']]}}},
685
+ ] if 'largeImage' in item and 'expected' not in item['largeImage'] else []) + [
686
+ {'$addFields': {'matchName': {'$eq': ['$name', item['name']]}}},
687
+ {'$sort': {'matchLI': -1, 'matchName': -1, '_id': 1}},
688
+ {'$limit': 1},
689
+ ]), None)
690
+
691
+ girder.cli.mount.ServerFuse._flatItemFile = _flatItemFile
692
+ except Exception:
693
+ pass
694
+
695
+
676
696
  class LargeImagePlugin(GirderPlugin):
677
697
  DISPLAY_NAME = 'Large Image'
678
698
  CLIENT_SOURCE_PATH = 'web_client'
@@ -727,3 +747,5 @@ class LargeImagePlugin(GirderPlugin):
727
747
 
728
748
  search._allowedSearchMode.pop('li_metadata', None)
729
749
  search.addSearchMode('li_metadata', metadataSearchHandler)
750
+
751
+ patchMount()
@@ -1,3 +1,4 @@
1
+ import inspect
1
2
  import os
2
3
  import re
3
4
 
@@ -99,7 +100,10 @@ class GirderTileSource(tilesource.FileTileSource):
99
100
  pass
100
101
  if not largeImagePath:
101
102
  try:
102
- largeImagePath = File().getGirderMountFilePath(largeImageFile)
103
+ largeImagePath = File().getGirderMountFilePath(
104
+ largeImageFile,
105
+ **({'preferFlat': True} if 'preferFlat' in inspect.signature(
106
+ File.getGirderMountFilePath).parameters else {}))
103
107
  except FilePathException:
104
108
  pass
105
109
  if not largeImagePath:
@@ -35,13 +35,14 @@ from girder import logger
35
35
  from girder.api import access
36
36
  from girder.api.describe import Description, autoDescribeRoute, describeRoute
37
37
  from girder.api.rest import Resource
38
- from girder.constants import SortDir, TokenScope
38
+ from girder.constants import AccessType, SortDir, TokenScope
39
39
  from girder.exceptions import RestException
40
40
  from girder.models.file import File
41
+ from girder.models.folder import Folder
41
42
  from girder.models.item import Item
42
43
  from girder.models.setting import Setting
43
44
  from large_image import cache_util
44
- from large_image.exceptions import TileGeneralError
45
+ from large_image.exceptions import TileGeneralError, TileSourceError
45
46
 
46
47
  from .. import constants, girder_tilesource
47
48
  from ..models.image_item import ImageItem
@@ -255,6 +256,7 @@ class LargeImageResource(Resource):
255
256
  self.route('GET', ('histograms',), self.countHistograms)
256
257
  self.route('DELETE', ('histograms',), self.deleteHistograms)
257
258
  self.route('DELETE', ('tiles', 'incomplete'), self.deleteIncompleteTiles)
259
+ self.route('PUT', ('folder', ':id', 'tiles'), self.createLargeImages)
258
260
 
259
261
  @describeRoute(
260
262
  Description('Clear tile source caches to release resources and file handles.'),
@@ -445,6 +447,70 @@ class LargeImageResource(Resource):
445
447
  removed += 1
446
448
  return removed
447
449
 
450
+ @access.user(scope=TokenScope.DATA_WRITE)
451
+ @autoDescribeRoute(
452
+ Description('Create new large images for all items within a folder.')
453
+ .notes('Does not work for items with multiple files and skips over items with '
454
+ 'existing or unfinished large images.')
455
+ .modelParam('id', 'The ID of the folder.', model=Folder, level=AccessType.WRITE,
456
+ required=True)
457
+ .param('force', 'Whether creation job(s) should be forced for each large image.',
458
+ required=False, default=False, dataType='boolean')
459
+ .param('localJobs', 'Whether the job(s) created should be local.', required=False,
460
+ default=False, dataType='boolean')
461
+ .param('recurse', 'Whether child folders should be recursed.', required=False,
462
+ default=False, dataType='boolean')
463
+ .errorResponse('ID was invalid.')
464
+ .errorResponse('Write access was denied for the folder.', 403),
465
+ )
466
+ def createLargeImages(self, folder, params):
467
+ user = self.getCurrentUser()
468
+ createJobs = 'always' if self.boolParam('force', params, default=False) else True
469
+ return self.createImagesRecurseOption(folder=folder, createJobs=createJobs, user=user,
470
+ recurse=params.get('recurse'),
471
+ localJobs=params.get('localJobs'))
472
+
473
+ def createImagesRecurseOption(self, folder, createJobs, user, recurse, localJobs):
474
+ result = {'childFoldersRecursed': 0,
475
+ 'itemsSkipped': 0,
476
+ 'largeImagesCreated': 0,
477
+ 'largeImagesRemovedAndRecreated': 0,
478
+ 'totalItems': 0}
479
+ if recurse:
480
+ for childFolder in Folder().childFolders(parent=folder, parentType='folder'):
481
+ result['childFoldersRecursed'] += 1
482
+ childResult = self.createImagesRecurseOption(folder=childFolder,
483
+ createJobs=createJobs, user=user,
484
+ recurse=recurse, localJobs=localJobs)
485
+ for key in childResult:
486
+ result[key] += childResult[key]
487
+ for item in Folder().childItems(folder=folder):
488
+ result['totalItems'] += 1
489
+ if item.get('largeImage'):
490
+ if item['largeImage'].get('expected'):
491
+ result['itemsSkipped'] += 1
492
+ else:
493
+ try:
494
+ ImageItem().getMetadata(item)
495
+ result['itemsSkipped'] += 1
496
+ continue
497
+ except (TileSourceError, KeyError):
498
+ previousFileId = item['largeImage'].get('originalId',
499
+ item['largeImage']['fileId'])
500
+ ImageItem().delete(item)
501
+ ImageItem().createImageItem(item, File().load(user=user, id=previousFileId),
502
+ createJob=createJobs, localJob=localJobs)
503
+ result['largeImagesRemovedAndRecreated'] += 1
504
+ else:
505
+ files = list(Item().childFiles(item=item, limit=2))
506
+ if len(files) == 1:
507
+ ImageItem().createImageItem(item, files[0], createJob=createJobs,
508
+ localJob=localJobs)
509
+ result['largeImagesCreated'] += 1
510
+ else:
511
+ result['itemsSkipped'] += 1
512
+ return result
513
+
448
514
  @describeRoute(
449
515
  Description('Remove large images from items where the large image job '
450
516
  'incomplete.')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: girder-large-image
3
- Version: 1.29.3.dev6
3
+ Version: 1.29.3.dev22
4
4
  Summary: A Girder plugin to work with large, multiresolution images.
5
5
  Home-page: https://github.com/girder/large_image
6
6
  Author: Kitware, Inc.
@@ -19,9 +19,9 @@ Requires-Python: >=3.8
19
19
  License-File: LICENSE
20
20
  Requires-Dist: girder>=3.1.18
21
21
  Requires-Dist: girder-jobs>=3.0.3
22
- Requires-Dist: large_image>=1.29.3.dev6
22
+ Requires-Dist: large_image>=1.29.3.dev22
23
23
  Provides-Extra: tasks
24
- Requires-Dist: large-image-tasks[girder]>=1.29.3.dev6; extra == "tasks"
24
+ Requires-Dist: large-image-tasks[girder]>=1.29.3.dev22; extra == "tasks"
25
25
  Requires-Dist: girder-worker[girder]>=0.6.0; extra == "tasks"
26
26
 
27
27
  A Girder plugin to work with large, multiresolution images.
@@ -1,7 +1,7 @@
1
1
  girder>=3.1.18
2
2
  girder-jobs>=3.0.3
3
- large_image>=1.29.3.dev6
3
+ large_image>=1.29.3.dev22
4
4
 
5
5
  [tasks]
6
- large-image-tasks[girder]>=1.29.3.dev6
6
+ large-image-tasks[girder]>=1.29.3.dev22
7
7
  girder-worker[girder]>=0.6.0
@@ -237,6 +237,37 @@ def testThumbnailFileJob(server, admin, user, fsAssetstore):
237
237
  Setting().set(constants.PluginSettings.LARGE_IMAGE_MAX_THUMBNAIL_FILES, 0)
238
238
 
239
239
 
240
+ @pytest.mark.usefixtures('unbindLargeImage')
241
+ @pytest.mark.plugin('large_image')
242
+ def testFolderCreateImages(server, admin, user, fsAssetstore):
243
+ file = utilities.uploadExternalFile('sample_image.ptif', admin, fsAssetstore)
244
+ itemId = file['itemId']
245
+ item = Item().load(itemId, user=admin)
246
+ folderId = str(item['folderId'])
247
+ # Remove the large image from this item
248
+ ImageItem().delete(item)
249
+ # Ask to make all items in this folder large images
250
+ resp = server.request(
251
+ method='PUT', path=f'/large_image/folder/{folderId}/tiles', user=admin)
252
+ assert utilities.respStatus(resp) == 200
253
+ assert resp.json['largeImagesCreated'] == 1
254
+ item = Item().load(itemId, user=admin)
255
+ # Check that this item became a large image again
256
+ assert 'largeImage' in item
257
+ # Hitting the endpoint again should skip the item
258
+ resp = server.request(
259
+ method='PUT', path=f'/large_image/folder/{folderId}/tiles', user=admin)
260
+ assert utilities.respStatus(resp) == 200
261
+ assert resp.json['itemsSkipped'] == 1
262
+ # If the item's source isn't working, it should be recreated.
263
+ item['largeImage']['sourceName'] = 'unknown'
264
+ Item().updateItem(item)
265
+ resp = server.request(
266
+ method='PUT', path=f'/large_image/folder/{folderId}/tiles', user=admin)
267
+ assert utilities.respStatus(resp) == 200
268
+ assert resp.json['largeImagesRemovedAndRecreated'] == 1
269
+
270
+
240
271
  @pytest.mark.singular()
241
272
  @pytest.mark.usefixtures('unbindLargeImage')
242
273
  @pytest.mark.plugin('large_image')