@@ -14,6 +14,7 @@ import com.scalableminds.webknossos.datastore.datareaders.n5.{N5Header, N5Metada
1414import com .scalableminds .webknossos .datastore .datareaders .precomputed .PrecomputedHeader .FILENAME_INFO
1515import com .scalableminds .webknossos .datastore .datareaders .zarr .NgffMetadata .FILENAME_DOT_ZATTRS
1616import com .scalableminds .webknossos .datastore .datareaders .zarr .ZarrHeader .FILENAME_DOT_ZARRAY
17+ import com .scalableminds .webknossos .datastore .datareaders .zarr3 .Zarr3ArrayHeader .FILENAME_ZARR_JSON
1718import com .scalableminds .webknossos .datastore .datavault .S3DataVault
1819import com .scalableminds .webknossos .datastore .explore .ExploreLocalLayerService
1920import com .scalableminds .webknossos .datastore .helpers .{DatasetDeleter , DirectoryConstants , UPath }
@@ -481,13 +482,14 @@ class UploadService @Inject()(dataSourceService: DataSourceService,
481482 _ <- Fox .successful(())
482483 uploadedDataSourceType = guessTypeOfUploadedDataSource(unpackToDir)
483484 _ <- uploadedDataSourceType match {
484- case UploadedDataSourceType .ZARR | UploadedDataSourceType .NEUROGLANCER_PRECOMPUTED |
485- UploadedDataSourceType .N5_MULTISCALES | UploadedDataSourceType .N5_ARRAY =>
485+ case UploadedDataSourceType .ZARR | UploadedDataSourceType .ZARR3 |
486+ UploadedDataSourceType .NEUROGLANCER_PRECOMPUTED | UploadedDataSourceType .N5_MULTISCALES |
487+ UploadedDataSourceType .N5_ARRAY =>
486488 exploreLocalDatasource(unpackToDir, dataSourceId, uploadedDataSourceType)
487489 case UploadedDataSourceType .EXPLORED =>
488490 checkPathsInUploadedDatasourcePropertiesJson(unpackToDir, dataSourceId.organizationId)
489- case UploadedDataSourceType .ZARR_MULTILAYER | UploadedDataSourceType .NEUROGLANCER_MULTILAYER |
490- UploadedDataSourceType .N5_MULTILAYER =>
491+ case UploadedDataSourceType .ZARR_MULTILAYER | UploadedDataSourceType .ZARR3_MULTILAYER |
492+ UploadedDataSourceType .NEUROGLANCER_MULTILAYER | UploadedDataSourceType . N5_MULTILAYER =>
491493 tryExploringMultipleLayers(unpackToDir, dataSourceId, uploadedDataSourceType)
492494 case UploadedDataSourceType .WKW => addLayerAndMagDirIfMissing(unpackToDir).toFox
493495 }
@@ -509,6 +511,7 @@ class UploadService @Inject()(dataSourceService: DataSourceService,
509511 typ : UploadedDataSourceType .Value ): Fox [Unit ] =
510512 for {
511513 _ <- Fox .runIf(typ == UploadedDataSourceType .ZARR )(addLayerAndMagDirIfMissing(path, FILENAME_DOT_ZARRAY ).toFox)
514+ _ <- Fox .runIf(typ == UploadedDataSourceType .ZARR3 )(addLayerAndMagDirIfMissing(path, FILENAME_ZARR_JSON ).toFox)
512515 explored <- exploreLocalLayerService.exploreLocal(path, dataSourceId)
513516 _ <- exploreLocalLayerService.writeLocalDatasourceProperties(explored, path)
514517 } yield ()
@@ -518,7 +521,8 @@ class UploadService @Inject()(dataSourceService: DataSourceService,
518521 typ : UploadedDataSourceType .Value ): Fox [Option [Path ]] =
519522 for {
520523 layerDirs <- typ match {
521- case UploadedDataSourceType .ZARR_MULTILAYER => getZarrLayerDirectories(path).toFox
524+ case UploadedDataSourceType .ZARR_MULTILAYER => getZarrLayerDirectories(path).toFox
525+ case UploadedDataSourceType .ZARR3_MULTILAYER => getZarr3LayerDirectories(path).toFox
522526 case UploadedDataSourceType .NEUROGLANCER_MULTILAYER | UploadedDataSourceType .N5_MULTILAYER =>
523527 PathUtils .listDirectories(path, silent = false ).toFox
524528 }
@@ -680,6 +684,10 @@ class UploadService @Inject()(dataSourceService: DataSourceService,
680684 UploadedDataSourceType .ZARR
681685 } else if (looksLikeZarrArray(dataSourceDir, maxDepth = 3 ).getOrElse(false )) {
682686 UploadedDataSourceType .ZARR_MULTILAYER
687+ } else if (looksLikeZarr3Array(dataSourceDir, maxDepth = 2 ).getOrElse(false )) {
688+ UploadedDataSourceType .ZARR3
689+ } else if (looksLikeZarr3Array(dataSourceDir, maxDepth = 3 ).getOrElse(false )) {
690+ UploadedDataSourceType .ZARR3_MULTILAYER
683691 } else if (looksLikeNeuroglancerPrecomputed(dataSourceDir, 1 ).getOrElse(false )) {
684692 UploadedDataSourceType .NEUROGLANCER_PRECOMPUTED
685693 } else if (looksLikeNeuroglancerPrecomputed(dataSourceDir, 2 ).getOrElse(false )) {
@@ -705,6 +713,9 @@ class UploadService @Inject()(dataSourceService: DataSourceService,
705713 private def looksLikeZarrArray (dataSourceDir : Path , maxDepth : Int ): Box [Boolean ] =
706714 containsMatchingFile(List (FILENAME_DOT_ZARRAY , FILENAME_DOT_ZATTRS ), dataSourceDir, maxDepth)
707715
716+ private def looksLikeZarr3Array (dataSourceDir : Path , maxDepth : Int ): Box [Boolean ] =
717+ containsMatchingFile(List (FILENAME_ZARR_JSON ), dataSourceDir, maxDepth)
718+
708719 private def looksLikeNeuroglancerPrecomputed (dataSourceDir : Path , maxDepth : Int ): Box [Boolean ] =
709720 containsMatchingFile(List (FILENAME_INFO ), dataSourceDir, maxDepth)
710721
@@ -754,14 +765,20 @@ class UploadService @Inject()(dataSourceService: DataSourceService,
754765 private def getZarrLayerDirectories (dataSourceDir : Path ): Box [Seq [Path ]] =
755766 for {
756767 potentialLayers <- PathUtils .listDirectories(dataSourceDir, silent = false )
757- layerDirs = potentialLayers.filter(p => looksLikeZarrArray(p, maxDepth = 2 ).isDefined)
768+ layerDirs = potentialLayers.filter(p => looksLikeZarrArray(p, maxDepth = 2 ).getOrElse(false ))
769+ } yield layerDirs
770+
771+ private def getZarr3LayerDirectories (dataSourceDir : Path ): Box [Seq [Path ]] =
772+ for {
773+ potentialLayers <- PathUtils .listDirectories(dataSourceDir, silent = false )
774+ layerDirs = potentialLayers.filter(p => looksLikeZarr3Array(p, maxDepth = 2 ).getOrElse(false ))
758775 } yield layerDirs
759776
760777 private def addLayerAndMagDirIfMissing (dataSourceDir : Path , headerFile : String = FILENAME_HEADER_WKW ): Box [Unit ] =
761778 if (Files .exists(dataSourceDir)) {
762779 for {
763780 listing : Seq [Path ] <- PathUtils .listFilesRecursive(dataSourceDir,
764- maxDepth = 2 ,
781+ maxDepth = 3 ,
765782 silent = false ,
766783 filters = p => p.getFileName.toString == headerFile)
767784 listingRelative = listing.map(dataSourceDir.normalize().relativize(_))
@@ -777,17 +794,19 @@ class UploadService @Inject()(dataSourceService: DataSourceService,
777794 } yield ()
778795 } else Full (())
779796
780- private def looksLikeMagDir (headerWkwPaths : Seq [Path ]): Boolean =
781- headerWkwPaths.headOption.exists { oneHeaderWkwPath =>
782- pathDepth(oneHeaderWkwPath) == 0
783- }
797+ private def looksLikeMagDir (headerFilePaths : Seq [Path ]): Boolean =
798+ pathExistsWithDepth( 0 , headerFilePaths) && ! pathExistsWithDepth( 1 , headerFilePaths) && ! pathExistsWithDepth(
799+ 2 ,
800+ headerFilePaths)
784801
785- private def pathDepth (path : Path ) = path.toString.count(_ == '/' )
802+ private def looksLikeLayerDir (headerFilePaths : Seq [Path ]): Boolean =
803+ pathExistsWithDepth(1 , headerFilePaths) && ! pathExistsWithDepth(2 , headerFilePaths)
786804
787- private def looksLikeLayerDir (headerWkwPaths : Seq [Path ]): Boolean =
788- headerWkwPaths.headOption.exists { oneHeaderWkwPath =>
789- pathDepth(oneHeaderWkwPath) == 1
790- }
805+ private def pathExistsWithDepth (pathDepth : Int , paths : Seq [Path ]) =
806+ paths.exists(getPathDepth(_) == pathDepth)
807+
808+ private def getPathDepth (path : Path ) =
809+ path.toString.count(_ == '/' )
791810
792811 private def unpackDataset (uploadDir : Path , unpackToDir : Path , datasetId : ObjectId ): Fox [Unit ] =
793812 for {
@@ -897,6 +916,6 @@ class UploadService @Inject()(dataSourceService: DataSourceService,
897916}
898917
899918object UploadedDataSourceType extends Enumeration {
900- val ZARR, EXPLORED, ZARR_MULTILAYER, WKW, NEUROGLANCER_PRECOMPUTED, NEUROGLANCER_MULTILAYER, N5_MULTISCALES ,
901- N5_MULTILAYER , N5_ARRAY = Value
919+ val ZARR, ZARR3, ZARR3_MULTILAYER, EXPLORED, ZARR_MULTILAYER, WKW, NEUROGLANCER_PRECOMPUTED, NEUROGLANCER_MULTILAYER ,
920+ N5_MULTISCALES , N5_MULTILAYER , N5_ARRAY = Value
902921}
0 commit comments