Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mesh does not render in neuroglancer #181

Open
chourroutm opened this issue Oct 25, 2024 · 4 comments
Open

Mesh does not render in neuroglancer #181

chourroutm opened this issue Oct 25, 2024 · 4 comments
Labels

Comments

@chourroutm
Copy link

chourroutm commented Oct 25, 2024

Hi, I am creating a precomputed segmentation with cloudvolume and igneous, and generating the mesh on the fly. The mesh directory is not empty, and neuroglancer can detect the "mesh" entry in the info file, but it does not render. (Unfortunately, the gs bucket is private, I cannot share the link directly. Instead, I provide the MWE below with a spherical phantom.)

image

Phantom creation script

import numpy as np
import tifffile as tiff

size_xy = 1000
size_z = 1200
radius = 300

x0, y0, z0 = (500, 500, 500)

x, y, z = np.mgrid[0:size_xy:1, 0:size_xy:1, 0:size_z:1]
r = np.sqrt((x - x0)**2 + (y - y0)**2 + (z - z0)**2)

img = np.ones((size_xy,size_xy,size_z),dtype=np.uint8)
img[r > radius] = 0

tiff.imwrite("input/sphere_phantom.tif",img)

`cloudvolume` & `igneous` script

import tifffile as tiff
import os
from tqdm import tqdm
from cloudvolume import CloudVolume
from cloudvolume.lib import mkdir
from pathlib import Path
import numpy as np

image_filename = Path("input/sphere_phantom.tif")

is_zyx_instead_of_xyz = False

first_image = tiff.imread(image_filename)
img_shape = first_image.shape
dtype = first_image.dtype

print(f"Dataset shape: {img_shape}")
print(f"Dataset dtype: {dtype}")

output_dir = "output/phantom.precomputed/"
output_dir = Path(output_dir)
mkdir(output_dir)

output_dir = output_dir.absolute().as_uri() + "/"

print(output_dir)

native_resolution_nm = 100
binned_resolution_nm = native_resolution_nm*16

# Create a CloudVolume object for the Neuroglancer precomputed format
info = CloudVolume.create_new_info(
	num_channels = 1,
	layer_type = 'segmentation', # 'image' or 'segmentation'
	data_type = 'uint8', # can pick any popular uint
	encoding = 'compresso', # see: https://github.com/seung-lab/cloud-volume/wiki/Compression-Choices
	resolution = [ binned_resolution_nm ] * 3, # X,Y,Z values in nanometers
	voxel_offset = [ 0, 0, 0 ], # values X,Y,Z values in voxels
	chunk_size = [ 256 ] * 3, # rechunk of image X,Y,Z in voxels
	volume_size = img_shape[::-1] if is_zyx_instead_of_xyz else img_shape, # X,Y,Z size in voxels
	max_mip = 4,
	factor = (2,2,2),
)
vol = CloudVolume(
	output_dir,
	info=info,
	progress=False,
	parallel=False,
	cache_locking=True,
	compress=False,
	delete_black_uploads = True,
)

vol.commit_info()

print("CloudVolume info:")
print(vol.info)

data_to_write = tiff.imread(image_filename).astype(np.uint8)

if is_zyx_instead_of_xyz:
	data_to_write = np.transpose(data_to_write, (2, 1, 0))[..., np.newaxis]
else:
	data_to_write = data_to_write[..., np.newaxis]

vol[:,:,:, 1] = data_to_write

# ------------------------

from taskqueue import LocalTaskQueue
import igneous.task_creation as tc

tq = LocalTaskQueue(parallel=True)
tasks = tc.create_downsampling_tasks(output_dir, mip=0, num_mips = 3, factor= (2,2,2), fill_missing=True, delete_black_uploads=True,sparse=True,memory_target=int(500e9))
tq.insert(tasks)
tq.execute()
# tasks = tc.create_mesh_manifest_tasks(output_dir)
# tq.insert(tasks)
# tq.execute()
print("Done!")

# ----------------------

tq = LocalTaskQueue(parallel=True)
tasks = tc.create_meshing_tasks(output_dir, mip=0, shape=(256, 256, 256), fill_missing=True, sharded=False)
tq.insert(tasks)
tq.execute()
tasks = tc.create_unsharded_multires_mesh_tasks(output_dir)
tq.insert(tasks)
tq.execute()
tasks = tc.create_mesh_manifest_tasks(output_dir)
tq.insert(tasks)
tq.execute()
print("Done!")

Info file

{
  "data_type": "uint8",
  "mesh": "mesh_mip_0_err_40",
  "num_channels": 1,
  "scales": [
    {
      "chunk_sizes": [
        [
          256,
          256,
          256
        ]
      ],
      "encoding": "compresso",
      "key": "1600_1600_1600",
      "resolution": [
        1600,
        1600,
        1600
      ],
      "size": [
        1000,
        1000,
        1200
      ],
      "voxel_offset": [
        0,
        0,
        0
      ]
    },
    {
      "chunk_sizes": [
        [
          256,
          256,
          256
        ]
      ],
      "encoding": "compresso",
      "key": "3200_3200_3200",
      "resolution": [
        3200,
        3200,
        3200
      ],
      "size": [
        500,
        500,
        600
      ],
      "voxel_offset": [
        0,
        0,
        0
      ]
    },
    {
      "chunk_sizes": [
        [
          256,
          256,
          256
        ]
      ],
      "encoding": "compresso",
      "key": "6400_6400_6400",
      "resolution": [
        6400,
        6400,
        6400
      ],
      "size": [
        250,
        250,
        300
      ],
      "voxel_offset": [
        0,
        0,
        0
      ]
    },
    {
      "chunk_sizes": [
        [
          256,
          256,
          256
        ]
      ],
      "encoding": "compresso",
      "key": "12800_12800_12800",
      "resolution": [
        12800,
        12800,
        12800
      ],
      "size": [
        125,
        125,
        150
      ],
      "voxel_offset": [
        0,
        0,
        0
      ]
    },
    {
      "chunk_sizes": [
        [
          256,
          256,
          256
        ]
      ],
      "encoding": "compresso",
      "key": "25600_25600_25600",
      "resolution": [
        25600,
        25600,
        25600
      ],
      "size": [
        63,
        63,
        75
      ],
      "voxel_offset": [
        0,
        0,
        0
      ]
    }
  ],
  "type": "segmentation"
}

@william-silversmith
Copy link
Contributor

Thank you for the bug report! I found a bug in the unsharded multi-lod mesh generation. I'll let you know when it's fixed.

@william-silversmith
Copy link
Contributor

Actually, nevermind. I just messed up the command. This works for me:

igneous mesh forge output/phantom.precomputed --mip 0  --fill-missing
igneous mesh merge output/phantom.precomputed --nlod 2 --magnitude 1

@chourroutm
Copy link
Author

Indeed, the commands worked! What is the equivalent as a script to these two commands?

@william-silversmith
Copy link
Contributor

import igneous.task_creation as tc
from taskqueue import LocalTaskQueue

cloudpath = "file://./output/phantom.precomputed"
tq = LocalTaskQueue(parallel=1)

tasks = tc.create_meshing_tasks(cloudpath, mip=0, fill_missing=True)
tq.insert_all(tasks)

tasks = tc.create_unsharded_multires_mesh_tasks(cloudpath, num_lod=2, magnitude=1)
tq.insert_all(tasks)

Something like this should do it. For larger jobs, you should use TaskQueue instead of LocalTaskQueue. See https://github.com/seung-lab/python-task-queue/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants