nettracer3d 0.6.1__py3-none-any.whl → 0.6.2__py3-none-any.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.
nettracer3d/segmenter.py CHANGED
@@ -1290,41 +1290,99 @@ class InteractiveSegmenter:
1290
1290
  #Change the above chunk size to None to have it auto-compute largest chunks (not sure which is faster, 64 seems reasonable in test cases)
1291
1291
 
1292
1292
  if self.mem_lock:
1293
- chunk_size = 64 #memory efficient chunk
1293
+ chunk_size = 32 #memory efficient chunk
1294
1294
 
1295
1295
 
1296
1296
  def create_2d_chunks():
1297
1297
  """
1298
1298
  Create chunks by z-slices for 2D processing.
1299
- Each chunk is a complete z-slice with all y,x coordinates.
1299
+ Each chunk is a complete z-slice with all y,x coordinates,
1300
+ unless the slice exceeds 32768 pixels, in which case it's divided into subchunks.
1300
1301
 
1301
1302
  Returns:
1302
- List of chunks, where each chunk contains the coordinates for one z-slice
1303
+ List of chunks, where each chunk contains the coordinates for one z-slice or subchunk
1303
1304
  """
1304
- # Pre-calculate the number of coordinates per z-slice
1305
- coords_per_slice = self.image_3d.shape[1] * self.image_3d.shape[2]
1306
-
1307
- # Create all coordinates at once
1305
+ MAX_CHUNK_SIZE = 32768000
1308
1306
  chunks = []
1307
+
1309
1308
  for z in range(self.image_3d.shape[0]):
1310
- # Create y, x meshgrid once
1311
- y_coords, x_coords = np.meshgrid(
1312
- np.arange(self.image_3d.shape[1]),
1313
- np.arange(self.image_3d.shape[2]),
1314
- indexing='ij'
1315
- )
1309
+ # Get the dimensions of this z-slice
1310
+ y_dim = self.image_3d.shape[1]
1311
+ x_dim = self.image_3d.shape[2]
1312
+ total_pixels = y_dim * x_dim
1316
1313
 
1317
- # Create the slice coordinates more efficiently
1318
- slice_coords = np.column_stack((
1319
- np.full(coords_per_slice, z),
1320
- y_coords.ravel(),
1321
- x_coords.ravel()
1322
- ))
1323
-
1324
- # Convert to list of tuples
1325
- chunks.append(list(map(tuple, slice_coords)))
1326
-
1314
+ # If the slice is small enough, do not subchunk
1315
+ if total_pixels <= MAX_CHUNK_SIZE or not self.mem_lock:
1316
+ y_coords, x_coords = np.meshgrid(
1317
+ np.arange(y_dim),
1318
+ np.arange(x_dim),
1319
+ indexing='ij'
1320
+ )
1321
+
1322
+ slice_coords = np.column_stack((
1323
+ np.full(total_pixels, z),
1324
+ y_coords.ravel(),
1325
+ x_coords.ravel()
1326
+ ))
1327
+
1328
+ chunks.append(list(map(tuple, slice_coords)))
1329
+ else:
1330
+ # Determine which dimension to divide (the largest one)
1331
+ largest_dim = 'y' if y_dim >= x_dim else 'x'
1332
+
1333
+ # Calculate how many divisions we need
1334
+ num_divisions = int(np.ceil(total_pixels / MAX_CHUNK_SIZE))
1335
+
1336
+ # Calculate the approx size of each division along the largest dimension
1337
+ if largest_dim == 'y':
1338
+ div_size = int(np.ceil(y_dim / num_divisions))
1339
+ # Create subchunks by dividing the y-dimension
1340
+ for i in range(0, y_dim, div_size):
1341
+ end_i = min(i + div_size, y_dim)
1342
+ y_subrange = np.arange(i, end_i)
1343
+
1344
+ # Create meshgrid for this subchunk
1345
+ y_sub, x_sub = np.meshgrid(
1346
+ y_subrange,
1347
+ np.arange(x_dim),
1348
+ indexing='ij'
1349
+ )
1350
+
1351
+ # Create coordinates for this subchunk
1352
+ subchunk_size = len(y_subrange) * x_dim
1353
+ subchunk_coords = np.column_stack((
1354
+ np.full(subchunk_size, z),
1355
+ y_sub.ravel(),
1356
+ x_sub.ravel()
1357
+ ))
1358
+
1359
+ chunks.append(list(map(tuple, subchunk_coords)))
1360
+ else: # largest_dim == 'x'
1361
+ div_size = int(np.ceil(x_dim / num_divisions))
1362
+ # Create subchunks by dividing the x-dimension
1363
+ for i in range(0, x_dim, div_size):
1364
+ end_i = min(i + div_size, x_dim)
1365
+ x_subrange = np.arange(i, end_i)
1366
+
1367
+ # Create meshgrid for this subchunk
1368
+ y_sub, x_sub = np.meshgrid(
1369
+ np.arange(y_dim),
1370
+ x_subrange,
1371
+ indexing='ij'
1372
+ )
1373
+
1374
+ # Create coordinates for this subchunk
1375
+ subchunk_size = y_dim * len(x_subrange)
1376
+ subchunk_coords = np.column_stack((
1377
+ np.full(subchunk_size, z),
1378
+ y_sub.ravel(),
1379
+ x_sub.ravel()
1380
+ ))
1381
+
1382
+ chunks.append(list(map(tuple, subchunk_coords)))
1383
+
1327
1384
  return chunks
1385
+
1328
1386
  try:
1329
1387
  from cuml.ensemble import RandomForestClassifier as cuRandomForestClassifier
1330
1388
  except:
@@ -1415,6 +1473,7 @@ class InteractiveSegmenter:
1415
1473
  fore, back = self.process_chunk(chunk)
1416
1474
  foreground_coords.update(fore)
1417
1475
  background_coords.update(back)
1476
+ chunk[i] = None #Help garbage collection
1418
1477
  print(f"Processed {i}/{len(chunks)} chunks")
1419
1478
 
1420
1479
  return foreground_coords, background_coords
@@ -447,11 +447,11 @@ def compute_distance_transform(nodes):
447
447
 
448
448
  if is_pseudo_3d:
449
449
  # For 2D input, we get (2, H, W) but need (3, 1, H, W)
450
- H, W = nearest_label_indices_np[0].shape
451
- indices_4d = np.zeros((3, 1, H, W), dtype=nearest_label_indices_np.dtype)
452
- indices_4d[1:, 0] = nearest_label_indices_np # Copy Y and X coordinates
450
+ H, W = nearest_label_indices[0].shape
451
+ indices_4d = np.zeros((3, 1, H, W), dtype=nearest_label_indices.dtype)
452
+ indices_4d[1:, 0] = nearest_label_indices # Copy Y and X coordinates
453
453
  # indices_4d[0] stays 0 for all Z coordinates
454
- nearest_label_indices_np = indices_4d
454
+ nearest_label_indices = indices_4d
455
455
 
456
456
  return nearest_label_indices
457
457
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: nettracer3d
3
- Version: 0.6.1
3
+ Version: 0.6.2
4
4
  Summary: Scripts for intializing and analyzing networks from segmentations of three dimensional images.
5
5
  Author-email: Liam McLaughlin <mclaughlinliam99@gmail.com>
6
6
  Project-URL: User_Tutorial, https://www.youtube.com/watch?v=cRatn5VTWDY
@@ -44,10 +44,8 @@ NetTracer3D is free to use/fork for academic/nonprofit use so long as citation i
44
44
 
45
45
  NetTracer3D was developed by Liam McLaughlin while working under Dr. Sanjay Jain at Washington University School of Medicine.
46
46
 
47
- -- Version 0.6.1 updates --
47
+ -- Version 0.6.2 updates --
48
48
 
49
- 1. New feature for the machine learning segmenter. Now has a RAM lock mode which will always limit it to computing 1 chunk at a time, in both the interactive segmenter and the gross-segmenter. Feature map calculation within the chunk is made parallel to compensate which should allow this to function more optimally with RAM without really sacrificing performance. This should prevent the segmenter from majorly leaking memory in large arrays.
50
- 2. New function - 'Image' -> 'Select Objects'. Essentially just arbitrary selects/deselects lists of nodes or edges from the user in case there are some they are interested in but can't conveniently find. Allows imports from spreadsheets in case the user preorganizes some set of objects they want to select/deselect.
51
- 3. Brightness/Contrast now shades out of 65,535 instead of 255 which should allow better brightening options to images above 8bit depth.
52
- 4. Select all function updated to use the mini highlight overlay in larger images. Also reports the number of nodes/edges in the array in the cmd window when used.
53
- 5. Deleted the now unused 'hub_getter.py' script from the package.
49
+ 1. Fixed bug with performing 2D distance transforms on CPU
50
+
51
+ 2. Updated ram_lock mode in the segmenter to use smaller chunks and garbage collect better.
@@ -9,12 +9,12 @@ nettracer3d/network_draw.py,sha256=F7fw6Pcf4qWOhdKwLmhwqWdschbDlHzwCVolQC9imeU,1
9
9
  nettracer3d/node_draw.py,sha256=k3sCTfUCJs3aH1C1q1gTNxDz9EAQbBd1hsUIJajxRx8,9823
10
10
  nettracer3d/proximity.py,sha256=FnIiI_AzfXd22HwCIFIyQRZxKYJ8YscIDdPnIv-wsO4,10560
11
11
  nettracer3d/run.py,sha256=xYeaAc8FCx8MuzTGyL3NR3mK7WZzffAYAH23bNRZYO4,127
12
- nettracer3d/segmenter.py,sha256=YE4S2DJwLrvYpSzFkTKZLCyh14JKZmgDfGbB4_5EaU0,80163
12
+ nettracer3d/segmenter.py,sha256=ixx6rPprP5hMwObcwJDMJ-wVVpgUn6eTKiIJohg9KE4,83313
13
13
  nettracer3d/simple_network.py,sha256=fP1gkDdtQcHruEZpUdasKdZeVacoLOxKhR3bY0L1CAQ,15426
14
- nettracer3d/smart_dilate.py,sha256=Kekm6YIVlJniMvJMG6_AwwNmCqK2l4Qtvg9VzzqPKMw,24600
15
- nettracer3d-0.6.1.dist-info/LICENSE,sha256=gM207DhJjWrxLuEWXl0Qz5ISbtWDmADfjHp3yC2XISs,888
16
- nettracer3d-0.6.1.dist-info/METADATA,sha256=XNg9JY1EOoiZ8g5hqcfxe4kjy4_amS8JWWsAUZyK8do,4111
17
- nettracer3d-0.6.1.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
18
- nettracer3d-0.6.1.dist-info/entry_points.txt,sha256=Nx1rr_0QhJXDBHAQg2vcqCzLMKBzSHfwy3xwGkueVyc,53
19
- nettracer3d-0.6.1.dist-info/top_level.txt,sha256=zsYy9rZwirfCEOubolhee4TyzqBAL5gSUeFMzhFTX8c,12
20
- nettracer3d-0.6.1.dist-info/RECORD,,
14
+ nettracer3d/smart_dilate.py,sha256=6m03KHtRMv0zfJ2aHc1Om4Fhh2abPy-IqDzRCmIEHCY,24588
15
+ nettracer3d-0.6.2.dist-info/LICENSE,sha256=gM207DhJjWrxLuEWXl0Qz5ISbtWDmADfjHp3yC2XISs,888
16
+ nettracer3d-0.6.2.dist-info/METADATA,sha256=LxWDK4jsNYNErRWDsPUf_lY1rWt8y-83aB0R1cXqoOQ,3131
17
+ nettracer3d-0.6.2.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
18
+ nettracer3d-0.6.2.dist-info/entry_points.txt,sha256=Nx1rr_0QhJXDBHAQg2vcqCzLMKBzSHfwy3xwGkueVyc,53
19
+ nettracer3d-0.6.2.dist-info/top_level.txt,sha256=zsYy9rZwirfCEOubolhee4TyzqBAL5gSUeFMzhFTX8c,12
20
+ nettracer3d-0.6.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.2)
2
+ Generator: setuptools (76.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5