cellprofiler-library-nightly 5.0.0.dev243__tar.gz → 5.0.0.dev259__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 (41) hide show
  1. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/PKG-INFO +1 -1
  2. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/_version.py +2 -2
  3. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/functions/measurement.py +221 -0
  4. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/modules/__init__.py +1 -0
  5. cellprofiler_library_nightly-5.0.0.dev259/cellprofiler_library/modules/_measureobjectsizeshape.py +160 -0
  6. cellprofiler_library_nightly-5.0.0.dev259/cellprofiler_library/opts/objectsizeshapefeatures.py +191 -0
  7. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library_nightly.egg-info/PKG-INFO +1 -1
  8. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library_nightly.egg-info/SOURCES.txt +2 -0
  9. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/LICENSE +0 -0
  10. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/README.md +0 -0
  11. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/__init__.py +0 -0
  12. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/functions/__init__.py +0 -0
  13. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/functions/file_processing.py +0 -0
  14. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/functions/image_processing.py +0 -0
  15. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/functions/object_processing.py +0 -0
  16. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/functions/segmentation.py +0 -0
  17. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/modules/_closing.py +0 -0
  18. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/modules/_combineobjects.py +0 -0
  19. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/modules/_enhanceedges.py +0 -0
  20. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/modules/_expandorshrinkobjects.py +0 -0
  21. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/modules/_fillobjects.py +0 -0
  22. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/modules/_gaussianfilter.py +0 -0
  23. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/modules/_measureimageoverlap.py +0 -0
  24. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/modules/_medialaxis.py +0 -0
  25. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/modules/_medianfilter.py +0 -0
  26. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/modules/_morphologicalskeleton.py +0 -0
  27. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/modules/_opening.py +0 -0
  28. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/modules/_overlayobjects.py +0 -0
  29. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/modules/_reducenoise.py +0 -0
  30. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/modules/_savecroppedobjects.py +0 -0
  31. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/modules/_threshold.py +0 -0
  32. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/modules/_watershed.py +0 -0
  33. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/opts/__init__.py +0 -0
  34. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/opts/measureimageoverlap.py +0 -0
  35. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library/py.typed +0 -0
  36. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library_nightly.egg-info/dependency_links.txt +0 -0
  37. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library_nightly.egg-info/requires.txt +0 -0
  38. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/cellprofiler_library_nightly.egg-info/top_level.txt +0 -0
  39. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/environment.yml +0 -0
  40. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/pyproject.toml +0 -0
  41. {cellprofiler_library_nightly-5.0.0.dev243 → cellprofiler_library_nightly-5.0.0.dev259}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cellprofiler-library-nightly
3
- Version: 5.0.0.dev243
3
+ Version: 5.0.0.dev259
4
4
  Summary: cellprofiler-library implements CellProfiler's image processing and mathematical code, and is usable as a standalone library
5
5
  Author: Anne Carpenter, Thouis (Ray) Jones, Lee Kamentsky, Vebjorn Ljosa, David Logan, Mark Bray, Madison Swain-Bowden, Allen Goodman, Claire McQuinn, Alice Lucas, Callum Tromans-Coia
6
6
  Author-email: Beth Cimini <bcimini@broadinstitute.org>, David Stirling <dstirling@glencoesoftware.com>, Nodar Gogoberidze <ngogober@broadinstitute.org>
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '5.0.0.dev243'
21
- __version_tuple__ = version_tuple = (5, 0, 0, 'dev243')
20
+ __version__ = version = '5.0.0.dev259'
21
+ __version_tuple__ = version_tuple = (5, 0, 0, 'dev259')
@@ -6,6 +6,9 @@ import centrosome.filter
6
6
  import centrosome.propagate
7
7
  import centrosome.fastemd
8
8
  from sklearn.cluster import KMeans
9
+ from typing import Tuple
10
+ import numpy
11
+ import skimage
9
12
 
10
13
  from cellprofiler_library.opts import measureimageoverlap as mio
11
14
  from cellprofiler_library.functions.segmentation import convert_labels_to_ijv
@@ -14,6 +17,8 @@ from cellprofiler_library.functions.segmentation import count_from_ijv
14
17
  from cellprofiler_library.functions.segmentation import areas_from_ijv
15
18
  from cellprofiler_library.functions.segmentation import cast_labels_to_label_set
16
19
 
20
+ from cellprofiler_library.opts.objectsizeshapefeatures import ObjectSizeShapeFeatures
21
+
17
22
 
18
23
  def measure_image_overlap_statistics(
19
24
  ground_truth_image,
@@ -456,3 +461,219 @@ def get_weights(i, j, labels_mask):
456
461
  bc = np.bincount(total_skel[ii, jj])[1:]
457
462
  result[: len(bc)] = bc
458
463
  return result
464
+
465
+
466
+ def measure_object_size_shape(
467
+ labels,
468
+ desired_properties,
469
+ calculate_zernikes: bool = True,
470
+ calculate_advanced: bool = True,
471
+ spacing: Tuple = None
472
+ ):
473
+ label_indices = numpy.unique(labels[labels != 0])
474
+ nobjects = len(label_indices)
475
+
476
+ if spacing is None:
477
+ spacing = (1.0,) * labels.ndim
478
+
479
+ if len(labels.shape) == 2:
480
+ # 2D
481
+ props = skimage.measure.regionprops_table(labels, properties=desired_properties)
482
+
483
+ formfactor = 4.0 * numpy.pi * props["area"] / props["perimeter"] ** 2
484
+ denom = [max(x, 1) for x in 4.0 * numpy.pi * props["area"]]
485
+ compactness = props["perimeter"] ** 2 / denom
486
+
487
+ max_radius = numpy.zeros(nobjects)
488
+ median_radius = numpy.zeros(nobjects)
489
+ mean_radius = numpy.zeros(nobjects)
490
+ min_feret_diameter = numpy.zeros(nobjects)
491
+ max_feret_diameter = numpy.zeros(nobjects)
492
+ zernike_numbers = centrosome.zernike.get_zernike_indexes(ObjectSizeShapeFeatures.ZERNIKE_N.value + 1)
493
+
494
+ zf = {}
495
+ for n, m in zernike_numbers:
496
+ zf[(n, m)] = numpy.zeros(nobjects)
497
+
498
+ for index, mini_image in enumerate(props["image"]):
499
+ # Pad image to assist distance tranform
500
+ mini_image = numpy.pad(mini_image, 1)
501
+ distances = scipy.ndimage.distance_transform_edt(mini_image)
502
+ max_radius[index] = centrosome.cpmorphology.fixup_scipy_ndimage_result(
503
+ scipy.ndimage.maximum(distances, mini_image)
504
+ )
505
+ mean_radius[index] = centrosome.cpmorphology.fixup_scipy_ndimage_result(
506
+ scipy.ndimage.mean(distances, mini_image)
507
+ )
508
+ median_radius[index] = centrosome.cpmorphology.median_of_labels(
509
+ distances, mini_image.astype("int"), [1]
510
+ )
511
+
512
+ #
513
+ # Zernike features
514
+ #
515
+ if calculate_zernikes:
516
+ zf_l = centrosome.zernike.zernike(zernike_numbers, labels, label_indices)
517
+ for (n, m), z in zip(zernike_numbers, zf_l.transpose()):
518
+ zf[(n, m)] = z
519
+
520
+ if nobjects > 0:
521
+ chulls, chull_counts = centrosome.cpmorphology.convex_hull(
522
+ labels, label_indices
523
+ )
524
+ #
525
+ # Feret diameter
526
+ #
527
+ (
528
+ min_feret_diameter,
529
+ max_feret_diameter,
530
+ ) = centrosome.cpmorphology.feret_diameter(
531
+ chulls, chull_counts, label_indices
532
+ )
533
+
534
+ features_to_record = {
535
+ ObjectSizeShapeFeatures.F_AREA.value: props["area"],
536
+ ObjectSizeShapeFeatures.F_PERIMETER.value: props["perimeter"],
537
+ ObjectSizeShapeFeatures.F_MAJOR_AXIS_LENGTH.value: props["major_axis_length"],
538
+ ObjectSizeShapeFeatures.F_MINOR_AXIS_LENGTH.value: props["minor_axis_length"],
539
+ ObjectSizeShapeFeatures.F_ECCENTRICITY.value: props["eccentricity"],
540
+ ObjectSizeShapeFeatures.F_ORIENTATION.value: props["orientation"] * (180 / numpy.pi),
541
+ ObjectSizeShapeFeatures.F_CENTER_X.value: props["centroid-1"],
542
+ ObjectSizeShapeFeatures.F_CENTER_Y.value: props["centroid-0"],
543
+ ObjectSizeShapeFeatures.F_BBOX_AREA.value: props["bbox_area"],
544
+ ObjectSizeShapeFeatures.F_MIN_X.value: props["bbox-1"],
545
+ ObjectSizeShapeFeatures.F_MAX_X.value: props["bbox-3"],
546
+ ObjectSizeShapeFeatures.F_MIN_Y.value: props["bbox-0"],
547
+ ObjectSizeShapeFeatures.F_MAX_Y.value: props["bbox-2"],
548
+ ObjectSizeShapeFeatures.F_FORM_FACTOR.value: formfactor,
549
+ ObjectSizeShapeFeatures.F_EXTENT.value: props["extent"],
550
+ ObjectSizeShapeFeatures.F_SOLIDITY.value: props["solidity"],
551
+ ObjectSizeShapeFeatures.F_COMPACTNESS.value: compactness,
552
+ ObjectSizeShapeFeatures.F_EULER_NUMBER.value: props["euler_number"],
553
+ ObjectSizeShapeFeatures.F_MAXIMUM_RADIUS.value: max_radius,
554
+ ObjectSizeShapeFeatures.F_MEAN_RADIUS.value: mean_radius,
555
+ ObjectSizeShapeFeatures.F_MEDIAN_RADIUS.value: median_radius,
556
+ ObjectSizeShapeFeatures.F_CONVEX_AREA.value: props["convex_area"],
557
+ ObjectSizeShapeFeatures.F_MIN_FERET_DIAMETER.value: min_feret_diameter,
558
+ ObjectSizeShapeFeatures.F_MAX_FERET_DIAMETER.value: max_feret_diameter,
559
+ ObjectSizeShapeFeatures.F_EQUIVALENT_DIAMETER.value: props["equivalent_diameter"],
560
+ }
561
+ if calculate_advanced:
562
+ features_to_record.update(
563
+ {
564
+ ObjectSizeShapeFeatures.F_SPATIAL_MOMENT_0_0.value: props["moments-0-0"],
565
+ ObjectSizeShapeFeatures.F_SPATIAL_MOMENT_0_1.value: props["moments-0-1"],
566
+ ObjectSizeShapeFeatures.F_SPATIAL_MOMENT_0_2.value: props["moments-0-2"],
567
+ ObjectSizeShapeFeatures.F_SPATIAL_MOMENT_0_3.value: props["moments-0-3"],
568
+ ObjectSizeShapeFeatures.F_SPATIAL_MOMENT_1_0.value: props["moments-1-0"],
569
+ ObjectSizeShapeFeatures.F_SPATIAL_MOMENT_1_1.value: props["moments-1-1"],
570
+ ObjectSizeShapeFeatures.F_SPATIAL_MOMENT_1_2.value: props["moments-1-2"],
571
+ ObjectSizeShapeFeatures.F_SPATIAL_MOMENT_1_3.value: props["moments-1-3"],
572
+ ObjectSizeShapeFeatures.F_SPATIAL_MOMENT_2_0.value: props["moments-2-0"],
573
+ ObjectSizeShapeFeatures.F_SPATIAL_MOMENT_2_1.value: props["moments-2-1"],
574
+ ObjectSizeShapeFeatures.F_SPATIAL_MOMENT_2_2.value: props["moments-2-2"],
575
+ ObjectSizeShapeFeatures.F_SPATIAL_MOMENT_2_3.value: props["moments-2-3"],
576
+ ObjectSizeShapeFeatures.F_CENTRAL_MOMENT_0_0.value: props["moments_central-0-0"],
577
+ ObjectSizeShapeFeatures.F_CENTRAL_MOMENT_0_1.value: props["moments_central-0-1"],
578
+ ObjectSizeShapeFeatures.F_CENTRAL_MOMENT_0_2.value: props["moments_central-0-2"],
579
+ ObjectSizeShapeFeatures.F_CENTRAL_MOMENT_0_3.value: props["moments_central-0-3"],
580
+ ObjectSizeShapeFeatures.F_CENTRAL_MOMENT_1_0.value: props["moments_central-1-0"],
581
+ ObjectSizeShapeFeatures.F_CENTRAL_MOMENT_1_1.value: props["moments_central-1-1"],
582
+ ObjectSizeShapeFeatures.F_CENTRAL_MOMENT_1_2.value: props["moments_central-1-2"],
583
+ ObjectSizeShapeFeatures.F_CENTRAL_MOMENT_1_3.value: props["moments_central-1-3"],
584
+ ObjectSizeShapeFeatures.F_CENTRAL_MOMENT_2_0.value: props["moments_central-2-0"],
585
+ ObjectSizeShapeFeatures.F_CENTRAL_MOMENT_2_1.value: props["moments_central-2-1"],
586
+ ObjectSizeShapeFeatures.F_CENTRAL_MOMENT_2_2.value: props["moments_central-2-2"],
587
+ ObjectSizeShapeFeatures.F_CENTRAL_MOMENT_2_3.value: props["moments_central-2-3"],
588
+ ObjectSizeShapeFeatures.F_NORMALIZED_MOMENT_0_0.value: props["moments_normalized-0-0"],
589
+ ObjectSizeShapeFeatures.F_NORMALIZED_MOMENT_0_1.value: props["moments_normalized-0-1"],
590
+ ObjectSizeShapeFeatures.F_NORMALIZED_MOMENT_0_2.value: props["moments_normalized-0-2"],
591
+ ObjectSizeShapeFeatures.F_NORMALIZED_MOMENT_0_3.value: props["moments_normalized-0-3"],
592
+ ObjectSizeShapeFeatures.F_NORMALIZED_MOMENT_1_0.value: props["moments_normalized-1-0"],
593
+ ObjectSizeShapeFeatures.F_NORMALIZED_MOMENT_1_1.value: props["moments_normalized-1-1"],
594
+ ObjectSizeShapeFeatures.F_NORMALIZED_MOMENT_1_2.value: props["moments_normalized-1-2"],
595
+ ObjectSizeShapeFeatures.F_NORMALIZED_MOMENT_1_3.value: props["moments_normalized-1-3"],
596
+ ObjectSizeShapeFeatures.F_NORMALIZED_MOMENT_2_0.value: props["moments_normalized-2-0"],
597
+ ObjectSizeShapeFeatures.F_NORMALIZED_MOMENT_2_1.value: props["moments_normalized-2-1"],
598
+ ObjectSizeShapeFeatures.F_NORMALIZED_MOMENT_2_2.value: props["moments_normalized-2-2"],
599
+ ObjectSizeShapeFeatures.F_NORMALIZED_MOMENT_2_3.value: props["moments_normalized-2-3"],
600
+ ObjectSizeShapeFeatures.F_NORMALIZED_MOMENT_3_0.value: props["moments_normalized-3-0"],
601
+ ObjectSizeShapeFeatures.F_NORMALIZED_MOMENT_3_1.value: props["moments_normalized-3-1"],
602
+ ObjectSizeShapeFeatures.F_NORMALIZED_MOMENT_3_2.value: props["moments_normalized-3-2"],
603
+ ObjectSizeShapeFeatures.F_NORMALIZED_MOMENT_3_3.value: props["moments_normalized-3-3"],
604
+ ObjectSizeShapeFeatures.F_HU_MOMENT_0.value: props["moments_hu-0"],
605
+ ObjectSizeShapeFeatures.F_HU_MOMENT_1.value: props["moments_hu-1"],
606
+ ObjectSizeShapeFeatures.F_HU_MOMENT_2.value: props["moments_hu-2"],
607
+ ObjectSizeShapeFeatures.F_HU_MOMENT_3.value: props["moments_hu-3"],
608
+ ObjectSizeShapeFeatures.F_HU_MOMENT_4.value: props["moments_hu-4"],
609
+ ObjectSizeShapeFeatures.F_HU_MOMENT_5.value: props["moments_hu-5"],
610
+ ObjectSizeShapeFeatures.F_HU_MOMENT_6.value: props["moments_hu-6"],
611
+ ObjectSizeShapeFeatures.F_INERTIA_TENSOR_0_0.value: props["inertia_tensor-0-0"],
612
+ ObjectSizeShapeFeatures.F_INERTIA_TENSOR_0_1.value: props["inertia_tensor-0-1"],
613
+ ObjectSizeShapeFeatures.F_INERTIA_TENSOR_1_0.value: props["inertia_tensor-1-0"],
614
+ ObjectSizeShapeFeatures.F_INERTIA_TENSOR_1_1.value: props["inertia_tensor-1-1"],
615
+ ObjectSizeShapeFeatures.F_INERTIA_TENSOR_EIGENVALUES_0.value: props[
616
+ "inertia_tensor_eigvals-0"
617
+ ],
618
+ ObjectSizeShapeFeatures.F_INERTIA_TENSOR_EIGENVALUES_1.value: props[
619
+ "inertia_tensor_eigvals-1"
620
+ ],
621
+ }
622
+ )
623
+
624
+ if calculate_zernikes:
625
+ features_to_record.update(
626
+ {f"Zernike_{n}_{m}": zf[(n, m)] for n, m in zernike_numbers}
627
+ )
628
+
629
+ else:
630
+ # 3D
631
+ props = skimage.measure.regionprops_table(labels, properties=desired_properties)
632
+ # SurfaceArea
633
+ surface_areas = numpy.zeros(len(props["label"]))
634
+ for index, label in enumerate(props["label"]):
635
+ # this seems less elegant than you might wish, given that regionprops returns a slice,
636
+ # but we need to expand the slice out by one voxel in each direction, or surface area freaks out
637
+ volume = labels[
638
+ max(props["bbox-0"][index] - 1, 0) : min(
639
+ props["bbox-3"][index] + 1, labels.shape[0]
640
+ ),
641
+ max(props["bbox-1"][index] - 1, 0) : min(
642
+ props["bbox-4"][index] + 1, labels.shape[1]
643
+ ),
644
+ max(props["bbox-2"][index] - 1, 0) : min(
645
+ props["bbox-5"][index] + 1, labels.shape[2]
646
+ ),
647
+ ]
648
+ volume = volume == label
649
+ verts, faces, _normals, _values = skimage.measure.marching_cubes(
650
+ volume,
651
+ method="lewiner",
652
+ spacing=spacing,
653
+ level=0,
654
+ )
655
+ surface_areas[index] = skimage.measure.mesh_surface_area(verts, faces)
656
+
657
+ features_to_record = {
658
+ ObjectSizeShapeFeatures.F_VOLUME.value: props["area"],
659
+ ObjectSizeShapeFeatures.F_SURFACE_AREA.value: surface_areas,
660
+ ObjectSizeShapeFeatures.F_MAJOR_AXIS_LENGTH.value: props["major_axis_length"],
661
+ ObjectSizeShapeFeatures.F_MINOR_AXIS_LENGTH.value: props["minor_axis_length"],
662
+ ObjectSizeShapeFeatures.F_CENTER_X.value: props["centroid-2"],
663
+ ObjectSizeShapeFeatures.F_CENTER_Y.value: props["centroid-1"],
664
+ ObjectSizeShapeFeatures.F_CENTER_Z.value: props["centroid-0"],
665
+ ObjectSizeShapeFeatures.F_BBOX_VOLUME.value: props["bbox_area"],
666
+ ObjectSizeShapeFeatures.F_MIN_X.value: props["bbox-2"],
667
+ ObjectSizeShapeFeatures.F_MAX_X.value: props["bbox-5"],
668
+ ObjectSizeShapeFeatures.F_MIN_Y.value: props["bbox-1"],
669
+ ObjectSizeShapeFeatures.F_MAX_Y.value: props["bbox-4"],
670
+ ObjectSizeShapeFeatures.F_MIN_Z.value: props["bbox-0"],
671
+ ObjectSizeShapeFeatures.F_MAX_Z.value: props["bbox-3"],
672
+ ObjectSizeShapeFeatures.F_EXTENT.value: props["extent"],
673
+ ObjectSizeShapeFeatures.F_EULER_NUMBER.value: props["euler_number"],
674
+ ObjectSizeShapeFeatures.F_EQUIVALENT_DIAMETER.value: props["equivalent_diameter"],
675
+ }
676
+ if calculate_advanced:
677
+ features_to_record[ObjectSizeShapeFeatures.F_SOLIDITY.value] = props["solidity"]
678
+ return features_to_record, props["label"], nobjects
679
+
@@ -15,3 +15,4 @@ from ._reducenoise import reducenoise
15
15
  from ._watershed import watershed
16
16
  from ._measureimageoverlap import measureimageoverlap
17
17
  from ._gaussianfilter import gaussianfilter
18
+ from ._measureobjectsizeshape import measureobjectsizeshape
@@ -0,0 +1,160 @@
1
+ from typing import Tuple
2
+ import numpy
3
+ import skimage
4
+ import scipy
5
+
6
+ import centrosome
7
+ import centrosome.zernike
8
+
9
+ from cellprofiler_library.functions.measurement import measure_object_size_shape
10
+ from cellprofiler_library.opts.objectsizeshapefeatures import ObjectSizeShapeFeatures
11
+ from cellprofiler_library.functions.segmentation import (
12
+ _validate_dense,
13
+ convert_dense_to_label_set,
14
+ )
15
+
16
+ DEFAULT_INVALID_VALUE_DTYPE = {
17
+ numpy.float64: numpy.nan,
18
+ numpy.float32: numpy.nan,
19
+ numpy.float16: numpy.nan,
20
+ numpy.uint8: 0,
21
+ numpy.uint16: 0,
22
+ numpy.uint32: 0,
23
+ numpy.uint64: 0,
24
+ numpy.int8: 0,
25
+ numpy.int16: 0,
26
+ numpy.int32: 0,
27
+ numpy.int64: 0,
28
+ numpy.bool_: False,
29
+ numpy.object_: None,
30
+ numpy.str_: "",
31
+ }
32
+
33
+ def measureobjectsizeshape(
34
+ objects,
35
+ calculate_advanced: bool = True,
36
+ calculate_zernikes: bool = True,
37
+ volumetric: bool = False,
38
+ spacing: Tuple = None,
39
+ ):
40
+ """
41
+ Objects: dense, sparse, ijv, or label objects?
42
+ For now, we will assume dense
43
+ """
44
+ # _validate_dense(objects)
45
+
46
+ # Define the feature names
47
+ feature_names = list(ObjectSizeShapeFeatures.F_STANDARD.value)
48
+ if volumetric:
49
+ feature_names += list(ObjectSizeShapeFeatures.F_STD_3D.value)
50
+ if calculate_advanced:
51
+ feature_names += list(ObjectSizeShapeFeatures.F_ADV_3D.value)
52
+ else:
53
+ feature_names += list(ObjectSizeShapeFeatures.F_STD_2D.value)
54
+ if calculate_zernikes:
55
+ feature_names += [
56
+ f"Zernike_{index[0]}_{index[1]}"
57
+ for index in centrosome.zernike.get_zernike_indexes(
58
+ ObjectSizeShapeFeatures.ZERNIKE_N.value + 1
59
+ )
60
+ ]
61
+ if calculate_advanced:
62
+ feature_names += list(ObjectSizeShapeFeatures.F_ADV_2D.value)
63
+
64
+ if len(objects[objects != 0]) == 0:
65
+ data = dict(zip(feature_names, [None] * len(feature_names)))
66
+ for ft in feature_names:
67
+ data[ft] = numpy.zeros((0,))
68
+ return data
69
+
70
+ if not volumetric:
71
+ desired_properties = [
72
+ "label",
73
+ "image",
74
+ "area",
75
+ "perimeter",
76
+ "bbox",
77
+ "bbox_area",
78
+ "major_axis_length",
79
+ "minor_axis_length",
80
+ "orientation",
81
+ "centroid",
82
+ "equivalent_diameter",
83
+ "extent",
84
+ "eccentricity",
85
+ "convex_area",
86
+ "solidity",
87
+ "euler_number",
88
+ ]
89
+ if calculate_advanced:
90
+ desired_properties += [
91
+ "inertia_tensor",
92
+ "inertia_tensor_eigvals",
93
+ "moments",
94
+ "moments_central",
95
+ "moments_hu",
96
+ "moments_normalized",
97
+ ]
98
+ else:
99
+ desired_properties = [
100
+ "label",
101
+ "image",
102
+ "area",
103
+ "centroid",
104
+ "bbox",
105
+ "bbox_area",
106
+ "major_axis_length",
107
+ "minor_axis_length",
108
+ "extent",
109
+ "equivalent_diameter",
110
+ "euler_number",
111
+ ]
112
+ if calculate_advanced:
113
+ desired_properties += [
114
+ "solidity",
115
+ ]
116
+
117
+ labels = convert_dense_to_label_set(objects, validate=False)
118
+ labels = [i[0] for i in labels] # Just need the labelmaps, not indices
119
+
120
+ if len(labels) > 1:
121
+ # Overlapping labels
122
+ features_to_record = {}
123
+ for labelmap in labels:
124
+ buffer, measured_labels, nobjects = measure_object_size_shape(
125
+ labels=labelmap,
126
+ desired_properties=desired_properties,
127
+ calculate_zernikes=calculate_zernikes,
128
+ calculate_advanced=calculate_advanced,
129
+ spacing=spacing,
130
+ )
131
+ for f, m in buffer.items():
132
+ if f in features_to_record:
133
+ features_to_record[f] = numpy.concatenate(
134
+ (features_to_record[f], m)
135
+ )
136
+ else:
137
+ features_to_record[f] = m
138
+ else:
139
+ features_to_record, measured_labels, nobjects = measure_object_size_shape(
140
+ labels=labels[0],
141
+ desired_properties=desired_properties,
142
+ calculate_zernikes=calculate_zernikes,
143
+ calculate_advanced=calculate_advanced,
144
+ spacing=spacing,
145
+ )
146
+
147
+ # ensure that all objects (objects.indices) are represented in the
148
+ # output, even if they are not present in the label matrix. Fill with nan if missing
149
+ if len(measured_labels) < nobjects:
150
+ for i in objects.indices:
151
+ if i not in measured_labels:
152
+ for f in features_to_record:
153
+ features_to_record[f] = numpy.insert(
154
+ features_to_record[f], i-1, DEFAULT_INVALID_VALUE_DTYPE.get(
155
+ features_to_record[f].dtype.type, numpy.nan
156
+ )
157
+ )
158
+
159
+
160
+ return features_to_record
@@ -0,0 +1,191 @@
1
+ from enum import Enum
2
+
3
+
4
+ class ObjectSizeShapeFeatures(Enum):
5
+ """The category of the per-object measurements made by the MeasureObjectSizeShape module"""
6
+
7
+ AREA_SHAPE = "AreaShape"
8
+
9
+ ZERNIKE_N = 9
10
+
11
+ F_AREA = "Area"
12
+ F_PERIMETER = "Perimeter"
13
+ F_VOLUME = "Volume"
14
+ F_SURFACE_AREA = "SurfaceArea"
15
+ F_ECCENTRICITY = "Eccentricity"
16
+ F_SOLIDITY = "Solidity"
17
+ F_CONVEX_AREA = "ConvexArea"
18
+ F_EXTENT = "Extent"
19
+ F_CENTER_X = "Center_X"
20
+ F_CENTER_Y = "Center_Y"
21
+ F_CENTER_Z = "Center_Z"
22
+ F_BBOX_AREA = "BoundingBoxArea"
23
+ F_BBOX_VOLUME = "BoundingBoxVolume"
24
+ F_MIN_X = "BoundingBoxMinimum_X"
25
+ F_MAX_X = "BoundingBoxMaximum_X"
26
+ F_MIN_Y = "BoundingBoxMinimum_Y"
27
+ F_MAX_Y = "BoundingBoxMaximum_Y"
28
+ F_MIN_Z = "BoundingBoxMinimum_Z"
29
+ F_MAX_Z = "BoundingBoxMaximum_Z"
30
+ F_EULER_NUMBER = "EulerNumber"
31
+ F_FORM_FACTOR = "FormFactor"
32
+ F_MAJOR_AXIS_LENGTH = "MajorAxisLength"
33
+ F_MINOR_AXIS_LENGTH = "MinorAxisLength"
34
+ F_ORIENTATION = "Orientation"
35
+ F_COMPACTNESS = "Compactness"
36
+ F_INERTIA = "InertiaTensor"
37
+ F_MAXIMUM_RADIUS = "MaximumRadius"
38
+ F_MEDIAN_RADIUS = "MedianRadius"
39
+ F_MEAN_RADIUS = "MeanRadius"
40
+ F_MIN_FERET_DIAMETER = "MinFeretDiameter"
41
+ F_MAX_FERET_DIAMETER = "MaxFeretDiameter"
42
+
43
+ F_CENTRAL_MOMENT_0_0 = "CentralMoment_0_0"
44
+ F_CENTRAL_MOMENT_0_1 = "CentralMoment_0_1"
45
+ F_CENTRAL_MOMENT_0_2 = "CentralMoment_0_2"
46
+ F_CENTRAL_MOMENT_0_3 = "CentralMoment_0_3"
47
+ F_CENTRAL_MOMENT_1_0 = "CentralMoment_1_0"
48
+ F_CENTRAL_MOMENT_1_1 = "CentralMoment_1_1"
49
+ F_CENTRAL_MOMENT_1_2 = "CentralMoment_1_2"
50
+ F_CENTRAL_MOMENT_1_3 = "CentralMoment_1_3"
51
+ F_CENTRAL_MOMENT_2_0 = "CentralMoment_2_0"
52
+ F_CENTRAL_MOMENT_2_1 = "CentralMoment_2_1"
53
+ F_CENTRAL_MOMENT_2_2 = "CentralMoment_2_2"
54
+ F_CENTRAL_MOMENT_2_3 = "CentralMoment_2_3"
55
+ F_EQUIVALENT_DIAMETER = "EquivalentDiameter"
56
+ F_HU_MOMENT_0 = "HuMoment_0"
57
+ F_HU_MOMENT_1 = "HuMoment_1"
58
+ F_HU_MOMENT_2 = "HuMoment_2"
59
+ F_HU_MOMENT_3 = "HuMoment_3"
60
+ F_HU_MOMENT_4 = "HuMoment_4"
61
+ F_HU_MOMENT_5 = "HuMoment_5"
62
+ F_HU_MOMENT_6 = "HuMoment_6"
63
+ F_INERTIA_TENSOR_0_0 = "InertiaTensor_0_0"
64
+ F_INERTIA_TENSOR_0_1 = "InertiaTensor_0_1"
65
+ F_INERTIA_TENSOR_1_0 = "InertiaTensor_1_0"
66
+ F_INERTIA_TENSOR_1_1 = "InertiaTensor_1_1"
67
+ F_INERTIA_TENSOR_EIGENVALUES_0 = "InertiaTensorEigenvalues_0"
68
+ F_INERTIA_TENSOR_EIGENVALUES_1 = "InertiaTensorEigenvalues_1"
69
+ F_NORMALIZED_MOMENT_0_0 = "NormalizedMoment_0_0"
70
+ F_NORMALIZED_MOMENT_0_1 = "NormalizedMoment_0_1"
71
+ F_NORMALIZED_MOMENT_0_2 = "NormalizedMoment_0_2"
72
+ F_NORMALIZED_MOMENT_0_3 = "NormalizedMoment_0_3"
73
+ F_NORMALIZED_MOMENT_1_0 = "NormalizedMoment_1_0"
74
+ F_NORMALIZED_MOMENT_1_1 = "NormalizedMoment_1_1"
75
+ F_NORMALIZED_MOMENT_1_2 = "NormalizedMoment_1_2"
76
+ F_NORMALIZED_MOMENT_1_3 = "NormalizedMoment_1_3"
77
+ F_NORMALIZED_MOMENT_2_0 = "NormalizedMoment_2_0"
78
+ F_NORMALIZED_MOMENT_2_1 = "NormalizedMoment_2_1"
79
+ F_NORMALIZED_MOMENT_2_2 = "NormalizedMoment_2_2"
80
+ F_NORMALIZED_MOMENT_2_3 = "NormalizedMoment_2_3"
81
+ F_NORMALIZED_MOMENT_3_0 = "NormalizedMoment_3_0"
82
+ F_NORMALIZED_MOMENT_3_1 = "NormalizedMoment_3_1"
83
+ F_NORMALIZED_MOMENT_3_2 = "NormalizedMoment_3_2"
84
+ F_NORMALIZED_MOMENT_3_3 = "NormalizedMoment_3_3"
85
+ F_SPATIAL_MOMENT_0_0 = "SpatialMoment_0_0"
86
+ F_SPATIAL_MOMENT_0_1 = "SpatialMoment_0_1"
87
+ F_SPATIAL_MOMENT_0_2 = "SpatialMoment_0_2"
88
+ F_SPATIAL_MOMENT_0_3 = "SpatialMoment_0_3"
89
+ F_SPATIAL_MOMENT_1_0 = "SpatialMoment_1_0"
90
+ F_SPATIAL_MOMENT_1_1 = "SpatialMoment_1_1"
91
+ F_SPATIAL_MOMENT_1_2 = "SpatialMoment_1_2"
92
+ F_SPATIAL_MOMENT_1_3 = "SpatialMoment_1_3"
93
+ F_SPATIAL_MOMENT_2_0 = "SpatialMoment_2_0"
94
+ F_SPATIAL_MOMENT_2_1 = "SpatialMoment_2_1"
95
+ F_SPATIAL_MOMENT_2_2 = "SpatialMoment_2_2"
96
+ F_SPATIAL_MOMENT_2_3 = "SpatialMoment_2_3"
97
+
98
+ """The non-Zernike features"""
99
+ F_STD_2D = [
100
+ F_AREA,
101
+ F_PERIMETER,
102
+ F_MAXIMUM_RADIUS,
103
+ F_MEAN_RADIUS,
104
+ F_MEDIAN_RADIUS,
105
+ F_MIN_FERET_DIAMETER,
106
+ F_MAX_FERET_DIAMETER,
107
+ F_ORIENTATION,
108
+ F_ECCENTRICITY,
109
+ F_FORM_FACTOR,
110
+ F_SOLIDITY,
111
+ F_CONVEX_AREA,
112
+ F_COMPACTNESS,
113
+ F_BBOX_AREA,
114
+ ]
115
+ F_STD_3D = [
116
+ F_VOLUME,
117
+ F_SURFACE_AREA,
118
+ F_CENTER_Z,
119
+ F_BBOX_VOLUME,
120
+ F_MIN_Z,
121
+ F_MAX_Z,
122
+ ]
123
+ F_ADV_2D = [
124
+ F_SPATIAL_MOMENT_0_0,
125
+ F_SPATIAL_MOMENT_0_1,
126
+ F_SPATIAL_MOMENT_0_2,
127
+ F_SPATIAL_MOMENT_0_3,
128
+ F_SPATIAL_MOMENT_1_0,
129
+ F_SPATIAL_MOMENT_1_1,
130
+ F_SPATIAL_MOMENT_1_2,
131
+ F_SPATIAL_MOMENT_1_3,
132
+ F_SPATIAL_MOMENT_2_0,
133
+ F_SPATIAL_MOMENT_2_1,
134
+ F_SPATIAL_MOMENT_2_2,
135
+ F_SPATIAL_MOMENT_2_3,
136
+ F_CENTRAL_MOMENT_0_0,
137
+ F_CENTRAL_MOMENT_0_1,
138
+ F_CENTRAL_MOMENT_0_2,
139
+ F_CENTRAL_MOMENT_0_3,
140
+ F_CENTRAL_MOMENT_1_0,
141
+ F_CENTRAL_MOMENT_1_1,
142
+ F_CENTRAL_MOMENT_1_2,
143
+ F_CENTRAL_MOMENT_1_3,
144
+ F_CENTRAL_MOMENT_2_0,
145
+ F_CENTRAL_MOMENT_2_1,
146
+ F_CENTRAL_MOMENT_2_2,
147
+ F_CENTRAL_MOMENT_2_3,
148
+ F_NORMALIZED_MOMENT_0_0,
149
+ F_NORMALIZED_MOMENT_0_1,
150
+ F_NORMALIZED_MOMENT_0_2,
151
+ F_NORMALIZED_MOMENT_0_3,
152
+ F_NORMALIZED_MOMENT_1_0,
153
+ F_NORMALIZED_MOMENT_1_1,
154
+ F_NORMALIZED_MOMENT_1_2,
155
+ F_NORMALIZED_MOMENT_1_3,
156
+ F_NORMALIZED_MOMENT_2_0,
157
+ F_NORMALIZED_MOMENT_2_1,
158
+ F_NORMALIZED_MOMENT_2_2,
159
+ F_NORMALIZED_MOMENT_2_3,
160
+ F_NORMALIZED_MOMENT_3_0,
161
+ F_NORMALIZED_MOMENT_3_1,
162
+ F_NORMALIZED_MOMENT_3_2,
163
+ F_NORMALIZED_MOMENT_3_3,
164
+ F_HU_MOMENT_0,
165
+ F_HU_MOMENT_1,
166
+ F_HU_MOMENT_2,
167
+ F_HU_MOMENT_3,
168
+ F_HU_MOMENT_4,
169
+ F_HU_MOMENT_5,
170
+ F_HU_MOMENT_6,
171
+ F_INERTIA_TENSOR_0_0,
172
+ F_INERTIA_TENSOR_0_1,
173
+ F_INERTIA_TENSOR_1_0,
174
+ F_INERTIA_TENSOR_1_1,
175
+ F_INERTIA_TENSOR_EIGENVALUES_0,
176
+ F_INERTIA_TENSOR_EIGENVALUES_1,
177
+ ]
178
+ F_ADV_3D = [F_SOLIDITY]
179
+ F_STANDARD = [
180
+ F_EXTENT,
181
+ F_EULER_NUMBER,
182
+ F_EQUIVALENT_DIAMETER,
183
+ F_MAJOR_AXIS_LENGTH,
184
+ F_MINOR_AXIS_LENGTH,
185
+ F_CENTER_X,
186
+ F_CENTER_Y,
187
+ F_MIN_X,
188
+ F_MIN_Y,
189
+ F_MAX_X,
190
+ F_MAX_Y,
191
+ ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cellprofiler-library-nightly
3
- Version: 5.0.0.dev243
3
+ Version: 5.0.0.dev259
4
4
  Summary: cellprofiler-library implements CellProfiler's image processing and mathematical code, and is usable as a standalone library
5
5
  Author: Anne Carpenter, Thouis (Ray) Jones, Lee Kamentsky, Vebjorn Ljosa, David Logan, Mark Bray, Madison Swain-Bowden, Allen Goodman, Claire McQuinn, Alice Lucas, Callum Tromans-Coia
6
6
  Author-email: Beth Cimini <bcimini@broadinstitute.org>, David Stirling <dstirling@glencoesoftware.com>, Nodar Gogoberidze <ngogober@broadinstitute.org>
@@ -19,6 +19,7 @@ cellprofiler_library/modules/_expandorshrinkobjects.py
19
19
  cellprofiler_library/modules/_fillobjects.py
20
20
  cellprofiler_library/modules/_gaussianfilter.py
21
21
  cellprofiler_library/modules/_measureimageoverlap.py
22
+ cellprofiler_library/modules/_measureobjectsizeshape.py
22
23
  cellprofiler_library/modules/_medialaxis.py
23
24
  cellprofiler_library/modules/_medianfilter.py
24
25
  cellprofiler_library/modules/_morphologicalskeleton.py
@@ -30,6 +31,7 @@ cellprofiler_library/modules/_threshold.py
30
31
  cellprofiler_library/modules/_watershed.py
31
32
  cellprofiler_library/opts/__init__.py
32
33
  cellprofiler_library/opts/measureimageoverlap.py
34
+ cellprofiler_library/opts/objectsizeshapefeatures.py
33
35
  cellprofiler_library_nightly.egg-info/PKG-INFO
34
36
  cellprofiler_library_nightly.egg-info/SOURCES.txt
35
37
  cellprofiler_library_nightly.egg-info/dependency_links.txt