def testDdsCopyCreate(self): """ Test the :func:`mango.copy` method. """ dds0 = mango.ones(shape=self.shape, dtype="uint8") dds1 = mango.copy(dds0, dtype="uint16") self.assertEqual(dds0[0], dds1[0]) self.assertEqual(dds0[0, 0, 0], dds1[0, 0, 0]) self.assertEqual(dds0[(0, 0, 0)], dds1[(0, 0, 0)])
def testDdsSetGlobalOrigin(self): """ Test the :attr:`mango.Dds.origin` attribute for read/write access. """ origin = (5, 3, 1) dds0 = mango.ones(shape=self.shape, dtype="uint8", origin=origin) self.assertTrue(sp.all(origin == dds0.origin)) dds1 = mango.copy(dds0, dtype="uint16") self.assertTrue(sp.all(origin == dds1.origin)) newOrigin = sp.array((8, 16, 2), dtype="int32") dds0.origin = newOrigin self.assertTrue(sp.all(newOrigin == dds0.origin)) self.assertTrue( sp.all(dds1.subd.origin + (newOrigin - origin) == dds0.subd.origin))
def testDdsResizeHalo(self): for ddsH in [(0, 0, 0), (4, 4, 4), [2, 1, 0], sp.array([3, 6, 7]), [6, 9, 8]]: for h in [1, sp.array([1, 1, 1]), sp.array([2, 1, 0]), [3, 6, 7]]: for s in [False, True]: dds = \ mango.data.gaussian_noise( shape=2*sp.array(self.shape), mean = 32000.0, stdd = 100.0, mtype="tomo", origin=(5,-11,7), halo=ddsH ) ddsResz = mango.copy(dds) dds.updateHaloRegions() dds.mirrorOuterLayersToBorder(True) ddsResz.updateOverlapRegions() ddsResz.mirrorOuterLayersToBorder(True) ddsResz.resizeHalo(h, s) if (not hasattr(h, "__len__")): h = sp.array([ h, ] * 3) h = sp.array(h) self.assertListEqual(list(ddsResz.halo), list(h)) self.assertListEqual(list(dds.shape), list(ddsResz.shape)) self.assertListEqual(list(dds.origin), list(ddsResz.origin)) self.assertListEqual(list(dds.subd.shape), list(ddsResz.subd.shape)) self.assertListEqual(list(dds.subd.origin), list(ddsResz.subd.origin)) self.assertListEqual( list(dds.subd_h.shape - 2 * (dds.subd_h.halo - h)), list(ddsResz.subd_h.shape)) self.assertListEqual( list(dds.subd_h.origin + dds.subd_h.halo - h), list(ddsResz.subd_h.origin)) self.assertTrue( sp.all(dds.subd.asarray() == ddsResz.subd.asarray())) slc = [] slcResz = [] for i in range(0, 3): if (dds.halo[i] > h[i]): slc.append( slice(dds.halo[i] - h[i], -(dds.halo[i] - h[i]))) slcResz.append(slice(None)) elif (dds.halo[i] < h[i]): slc.append(slice(None)) slcResz.append( slice(h[i] - dds.halo[i], -(h[i] - dds.halo[i]))) else: slc.append(slice(None)) slcResz.append(slice(None)) self.assertListEqual( list(dds.subd_h.asarray()[slc].shape), list(ddsResz.subd_h.asarray()[slcResz].shape)) self.assertTrue( sp.all(dds.subd_h.asarray()[slc] == ddsResz.subd_h.asarray()[slcResz]))
def testDdsSetGlobalFaceValue(self): """ Test the :meth:`mango.Dds.setFacesToValue` method. """ outDir = self.createTmpDir("testDdsSetGlobalFaceValue") ddsorig = mango.zeros(shape=self.shape, mtype="tomo", origin=(-8, 5, -32)) for depth in (1, int(np.min(ddsorig.shape) // 2)): for axis in (0, 1, 2): dds = mango.copy(ddsorig) vallo = 16 + axis rootLogger.info("LO: axis=%s, val=%s, depth=%s" % (axis, vallo, depth)) dds.setFacesToValue(vallo, axislo=axis, depth=depth) #mango.io.writeDds(os.path.join(outDir, "tomoLoFaceAxis%s.nc" % axis), dds) shpFace = dds.shape shpFace[axis] = depth mpidimsFace = [0, 0, 0] mpidimsFace[axis] = 1 rootLogger.info("LO: shpFace=%s, mpidimsFace=%s" % (shpFace, mpidimsFace)) ddsFace = mango.copy(dds, shape=shpFace, mpidims=mpidimsFace) self.assertTrue(sp.all(ddsFace.subd.asarray() == vallo)) shpNotFace = dds.shape shpNotFace[axis] = dds.shape[axis] - depth orgNotFace = dds.origin orgNotFace[axis] = dds.origin[axis] + depth mpidimsNotFace = [0, 0, 0] mpidimsNotFace[axis] = 1 rootLogger.info( "LO: shpNotFace=%s, mpidimsNotFace=%s, orgNotFace=%s" % (shpNotFace, mpidimsNotFace, orgNotFace)) ddsNotFace = mango.copy(dds, origin=orgNotFace, shape=shpNotFace, mpidims=mpidimsNotFace) self.assertTrue(sp.all(ddsNotFace.subd.asarray() == 0)) dds = mango.copy(ddsorig) valhi = 2 * vallo rootLogger.info("HI: axis=%s, val=%s, depth=%s" % (axis, valhi, depth)) dds.setFacesToValue(valhi, axishi=axis, depth=depth) #mango.io.writeDds(os.path.join(outDir, "tomoLoFaceAxis%s.nc" % axis), dds) shpFace = dds.shape shpFace[axis] = depth mpidimsFace = [0, 0, 0] mpidimsFace[axis] = 1 orgFace = dds.origin orgFace[axis] = dds.origin[axis] + dds.shape[axis] - depth rootLogger.info("HI: shpFace=%s, mpidimsFace=%s, orgFace=%s" % (shpFace, mpidimsFace, orgFace)) ddsFace = mango.copy(dds, origin=orgFace, shape=shpFace, mpidims=mpidimsFace) self.assertTrue(sp.all(ddsFace.subd.asarray() == valhi)) shpNotFace = dds.shape shpNotFace[axis] = dds.shape[axis] - depth mpidimsNotFace = [0, 0, 0] mpidimsNotFace[axis] = 1 rootLogger.info( "HI: shpNotFace=%s, mpidimsNotFace=%s, orgNotFace=%s" % (shpNotFace, mpidimsNotFace, orgNotFace)) ddsNotFace = mango.copy(dds, shape=shpNotFace, mpidims=mpidimsNotFace) self.assertTrue(sp.all(ddsNotFace.subd.asarray() == 0))
def calcSphericalCavityLabels(self, dds): mpidims = dds.mpi.shape if (dds.mpi.comm != None): mpidims = (dds.mpi.comm.Get_size(), 1, 1) dds = mango.copy(dds, mpidims=mpidims) rootLogger.info("Calculating neighbourhood mean image...") fltDds = mango.copy(dds, mtype="tomo_float", halo=self.se.getHaloSize()) nMeanDds = mango.image.mean_filter(fltDds, self.se) nMeanDds = mango.copy(nMeanDds, halo=(0, 0, 0)) rootLogger.info("Calculating neighbourhood stdd image...") nStddDds = mango.image.stdd_filter(fltDds, self.se) nStddDds = mango.copy(nStddDds, halo=(0, 0, 0)) del fltDds self.maskLowStddVoxels(dds, nMeanDds, nStddDds) rootLogger.info("Calculating mean vs stdd histogram...") h2d, edges = mango.image.histogramdd([nMeanDds, nStddDds], bins=(1024, 8192)) h2d = h2d[:, :-2] rootLogger.info( "h2d.shape = %s, edges[0].shape=%s, edges[1].shape=%s" % (h2d.shape, edges[0].shape, edges[1].shape)) rootLogger.info("Done calculating mean vs stdd histogram...") maxIdx = np.unravel_index(np.argmax(h2d), h2d.shape) rootLogger.info("np.argmax(h2d) = %s" % (maxIdx, )) backgroundMean = 0.5 * (edges[0][maxIdx[0]] + edges[0][maxIdx[0] + 1]) backgroundStdd = 0.5 * (edges[1][maxIdx[1]] + edges[1][maxIdx[1] + 1]) mskDds = mango.copy(dds) rootLogger.info("Background (mean,stdd) = (%s, %s)." % (backgroundMean, backgroundStdd)) mskDds.subd.asarray()[...] = \ sp.where( sp.logical_or( nStddDds.subd.asarray() < (8 * backgroundStdd), nMeanDds.subd.asarray() < (backgroundMean + 3 * backgroundStdd), ), mskDds.mtype.maskValue(), mskDds.subd.asarray() ) del nMeanDds, nStddDds self.writeIntermediateDds("_AaaPrePercentileTailMask", mskDds) self.eliminatePercentileTails(mskDds, 1.0, 92.5) rootLogger.info("Calculating neighbourhood stdd image...") nStddDds = mango.image.stdd_filter(mskDds, self.se) self.eliminatePercentileTails(nStddDds, 33.0, 100.0) rootLogger.info("Copying stdd percentile tail mask to mskDds...") mango.copy_masked(nStddDds, mskDds) rootLogger.info("Done copying stdd percentile tail mask to mskDds.") self.writeIntermediateDds("_AaaPstPercentileTailMask", mskDds) rootLogger.info("Eliminating small clusters from mskDds...") self.eliminateSmallClusters(mskDds, 0.1) rootLogger.info("Done eliminating small clusters from mskDds.") self.writeIntermediateDds("_AaaPstSmallClusterMask", mskDds) del nStddDds segEdtDds = mango.zeros_like(mskDds, mtype="segmented") segEdtDds.asarray()[...] = sp.where( mskDds.asarray() == mskDds.mtype.maskValue(), 0, 1) self.writeIntermediateDds("_AaaPreCvxHullMask", segEdtDds) rootLogger.info("Calculating convex hull...") cvxHullMsk = mango.image.convex_hull_3d( segEdtDds, inputmsk=0, outhull=segEdtDds.mtype.maskValue(), inhull=1) segEdtDds.asarray()[...] = sp.where( cvxHullMsk.asarray() == cvxHullMsk.mtype.maskValue(), 1, segEdtDds.asarray()) rootLogger.info("Done calculating convex hull.") self.writeIntermediateDds("_AaaPstCvxHullMask", segEdtDds) segEdtDds.setFacesToValue(1) rootLogger.info("Calculating EDT image...") edtDds = mango.image.distance_transform_edt(segEdtDds, val=0) self.writeIntermediateDds("_AaaPstCvxHullMaskEdt", edtDds) rootLogger.info("Calculating MCR image...") mcrDds = mango.image.max_covering_radius(edtDds, maxdist=0.5 * (np.min(edtDds.shape)), filecache=True) mango.copy_masked(cvxHullMsk, mcrDds) rootLogger.info("Calculating (min,max) MCR values...") mcrMin, mcrMax = mango.minmax(mcrDds) rootLogger.info("Masking small MCR values...") mcrDds.asarray()[...] = sp.where(mcrDds.asarray() >= 0.05 * mcrMax, mcrDds.asarray(), mcrDds.mtype.maskValue()) self.writeIntermediateDds("_AaaPstCvxHullMaskMcr", mcrDds) del cvxHullMsk, edtDds # # Normalise the intensities so that a relative-gradient is computed for the largest # MCR radii. rootLogger.info("Normalising MCR image...") mnmx = mango.minmax(mcrDds) tmpDds = mango.copy(mcrDds) tmpDds.asarray()[...] -= mnmx[1] tmpDds.asarray()[...] *= tmpDds.asarray() tmpDds.asarray()[...] = 1 + mnmx[1] * np.exp(-(tmpDds.asarray()) / (2 * 0.133 * 0.133 * (mnmx[1] * mnmx[1]))) mcrDds.asarray()[...] = sp.where(mcrDds.asarray() > 0, mcrDds.asarray() / tmpDds.asarray(), mcrDds.asarray()) rootLogger.info("Calculating MCR image gradient...") grdMcrDds = mango.image.discrete_gaussian_gradient_magnitude( mcrDds, 0.65, errtol=0.01) grdMcrDds.asarray()[...] = sp.where(grdMcrDds.asarray() <= 3.0e-2, mcrDds.asarray(), mcrDds.mtype.maskValue()) rootLogger.info("Calculating unique MCR low-gradient values...") u = mango.unique(grdMcrDds) rootLogger.info( "Converting low gradient MCR image to binary segmentation...") segDds = mango.map_element_values(grdMcrDds, lambda x: x in u, mtype="segmented") rootLogger.info("Labeling low gradient MCR regions...") mango.copy_masked(mcrDds, segDds) lblDds = mango.image.label(segDds, val=1, connectivity=26, dosort=True) self.writeIntermediateDds("_AaaPstCvxHullMaskMcrGrdLbl", lblDds) del segDds, grdMcrDds rootLogger.info("Calculating Principal Moment of Inertia...") self.pmoi, self.pmoi_axes, self.com = mango.image.moment_of_inertia( mskDds) rootLogger.info("Done calculating Principal Moment of Inertia.") return lblDds, mcrDds, segEdtDds
def calcSphericalCavityLabels(self, dds): mpidims = dds.mpi.shape if (dds.mpi.comm != None): mpidims = (dds.mpi.comm.Get_size(), 1, 1) dds = mango.copy(dds, mpidims=mpidims) rootLogger.info("Calculating neighbourhood mean image...") fltDds = mango.copy(dds, mtype="tomo_float", halo=self.se.getHaloSize()) nMeanDds = mango.image.mean_filter(fltDds, self.se) nMeanDds = mango.copy(nMeanDds, halo=(0,0,0)) rootLogger.info("Calculating neighbourhood stdd image...") nStddDds = mango.image.stdd_filter(fltDds, self.se) nStddDds = mango.copy(nStddDds, halo=(0,0,0)) del fltDds self.maskLowStddVoxels(dds, nMeanDds, nStddDds) rootLogger.info("Calculating mean vs stdd histogram...") h2d, edges = mango.image.histogramdd([nMeanDds, nStddDds], bins=(1024, 8192)) h2d = h2d[:, :-2] rootLogger.info("h2d.shape = %s, edges[0].shape=%s, edges[1].shape=%s" % (h2d.shape, edges[0].shape, edges[1].shape)) rootLogger.info("Done calculating mean vs stdd histogram...") maxIdx = np.unravel_index(np.argmax(h2d), h2d.shape) rootLogger.info("np.argmax(h2d) = %s" % (maxIdx,)) backgroundMean = 0.5 * (edges[0][maxIdx[0]] + edges[0][maxIdx[0] + 1]) backgroundStdd = 0.5 * (edges[1][maxIdx[1]] + edges[1][maxIdx[1] + 1]) mskDds = mango.copy(dds) rootLogger.info("Background (mean,stdd) = (%s, %s)." % (backgroundMean, backgroundStdd)) mskDds.subd.asarray()[...] = \ sp.where( sp.logical_or( nStddDds.subd.asarray() < (8 * backgroundStdd), nMeanDds.subd.asarray() < (backgroundMean + 3 * backgroundStdd), ), mskDds.mtype.maskValue(), mskDds.subd.asarray() ) del nMeanDds, nStddDds self.writeIntermediateDds("_AaaPrePercentileTailMask", mskDds) self.eliminatePercentileTails(mskDds, 1.0, 92.5) rootLogger.info("Calculating neighbourhood stdd image...") nStddDds = mango.image.stdd_filter(mskDds, self.se) self.eliminatePercentileTails(nStddDds, 33.0, 100.0) rootLogger.info("Copying stdd percentile tail mask to mskDds...") mango.copy_masked(nStddDds, mskDds) rootLogger.info("Done copying stdd percentile tail mask to mskDds.") self.writeIntermediateDds("_AaaPstPercentileTailMask", mskDds) rootLogger.info("Eliminating small clusters from mskDds...") self.eliminateSmallClusters(mskDds, 0.1) rootLogger.info("Done eliminating small clusters from mskDds.") self.writeIntermediateDds("_AaaPstSmallClusterMask", mskDds) del nStddDds segEdtDds = mango.zeros_like(mskDds, mtype="segmented") segEdtDds.asarray()[...] = sp.where(mskDds.asarray() == mskDds.mtype.maskValue(), 0, 1) self.writeIntermediateDds("_AaaPreCvxHullMask", segEdtDds) rootLogger.info("Calculating convex hull...") cvxHullMsk = mango.image.convex_hull_3d(segEdtDds, inputmsk=0, outhull=segEdtDds.mtype.maskValue(), inhull=1) segEdtDds.asarray()[...] = sp.where(cvxHullMsk.asarray() == cvxHullMsk.mtype.maskValue(), 1, segEdtDds.asarray()) rootLogger.info("Done calculating convex hull.") self.writeIntermediateDds("_AaaPstCvxHullMask", segEdtDds) segEdtDds.setFacesToValue(1) rootLogger.info("Calculating EDT image...") edtDds = mango.image.distance_transform_edt(segEdtDds, val=0) self.writeIntermediateDds("_AaaPstCvxHullMaskEdt", edtDds) rootLogger.info("Calculating MCR image...") mcrDds = mango.image.max_covering_radius(edtDds, maxdist=0.5*(np.min(edtDds.shape)), filecache=True) mango.copy_masked(cvxHullMsk, mcrDds) rootLogger.info("Calculating (min,max) MCR values...") mcrMin, mcrMax = mango.minmax(mcrDds) rootLogger.info("Masking small MCR values...") mcrDds.asarray()[...] = sp.where(mcrDds.asarray() >= 0.05*mcrMax, mcrDds.asarray(), mcrDds.mtype.maskValue()) self.writeIntermediateDds("_AaaPstCvxHullMaskMcr", mcrDds) del cvxHullMsk, edtDds # # Normalise the intensities so that a relative-gradient is computed for the largest # MCR radii. rootLogger.info("Normalising MCR image...") mnmx = mango.minmax(mcrDds) tmpDds = mango.copy(mcrDds) tmpDds.asarray()[...] -= mnmx[1] tmpDds.asarray()[...] *= tmpDds.asarray() tmpDds.asarray()[...] = 1+mnmx[1]*np.exp(-(tmpDds.asarray())/(2*0.133*0.133*(mnmx[1]*mnmx[1]))) mcrDds.asarray()[...] = sp.where(mcrDds.asarray() > 0, mcrDds.asarray()/tmpDds.asarray(), mcrDds.asarray()) rootLogger.info("Calculating MCR image gradient...") grdMcrDds = mango.image.discrete_gaussian_gradient_magnitude(mcrDds, 0.65, errtol=0.01) grdMcrDds.asarray()[...] = sp.where(grdMcrDds.asarray() <= 3.0e-2, mcrDds.asarray(), mcrDds.mtype.maskValue()) rootLogger.info("Calculating unique MCR low-gradient values...") u = mango.unique(grdMcrDds) rootLogger.info("Converting low gradient MCR image to binary segmentation...") segDds = mango.map_element_values(grdMcrDds, lambda x: x in u, mtype="segmented") rootLogger.info("Labeling low gradient MCR regions...") mango.copy_masked(mcrDds, segDds) lblDds = mango.image.label(segDds, val=1, connectivity=26, dosort=True) self.writeIntermediateDds("_AaaPstCvxHullMaskMcrGrdLbl", lblDds) del segDds, grdMcrDds rootLogger.info("Calculating Principal Moment of Inertia...") self.pmoi, self.pmoi_axes, self.com = mango.image.moment_of_inertia(mskDds) rootLogger.info("Done calculating Principal Moment of Inertia.") return lblDds, mcrDds, segEdtDds
def cylinder_fit_multi_res( input, numcyl, retcylimg=False, resolutions=[128, 256, 1024], metric = None, radius_range_percent = (50.0, 100.0), centre_range_percent = (-8.0, 8.0), metricThreshRelTol = 0.25 ): """ Multi-resolution version of :func:`cylinder_fit`. :type input: :obj:`mango.Dds` :param input: Search for cylinder boundaries in the gradient-vector image of this :samp:`{input}` image. :type numcyl: :obj:`mango.Dds` :param numcyl: Number of cylinders to find. :type retcylimg: :obj:`bool` :param retcylimg: If :samp:`True`, additionally returns a segmented image with the boundary of the cylinder fits labeled from :samp:`0` to :samp:`{numcyl}-1`. :type resolutions: sequence of :obj:`int` :param resolutions: The sequence of image shapes for each cylinder fit resolution. Exhaustive search and refinement is performed at the lowest resolution, just refinement at the higher resolutions. :type metric: :obj:`CylinderFitGradientMetric` :param metric: Metric object used to identify cylinder parameters which indicate the presence of a cylindrical boundary in the :samp:`input` image. :type radius_range_percent: 2 or 3 sequence of :obj:`float` :param radius_range_percent: Indicates the cylinder-radius exhaustive search grid as :samp:`(min_percent, max_percent, percent_step)`. This is a percentage of the minimum :samp:`{input}.shape` component (i.e. :samp:`numpy.min({input}.shape)`). If the percent step size is omitted, then a percent equivalent of 2-voxels is chosen as the step-size. :type centre_range_percent: 2 or 3 sequence of :obj:`float` :param centre_range_percent: Indicates the cylinder-centre exhaustive search grid as :samp:`(min_percent, max_percent, percent_step)`. This is a percentage of the minimum :samp:`{input}.shape` component (i.e. :samp:`numpy.min({input}.shape)`). If the percent step size is omitted, then a percent equivalent of 2-voxels is chosen as the step-size. :type metricThreshRelTol: :obj:`float` :param metricThreshRelTol: Relative tolerance for truncating the exhaustive search metric values. Ignore exhaustive search parameters which give metric values that have relative difference greater than :samp:`{metricThreshRelTol}` of the best (lowest) metric value in the entire search. :rtype: :obj:`list` of :samp:`[metricVal, cylinderParameters]` pairs :return: List of pairs :samp:`pairList = [[metricVal0, cylPrms0], [metricVal1, cylPrms1], ...]` where :samp:`cylPrms0=[[centrez0, centrey0, centrex0], radius0, axisLength0, [axisz0, axisy0, axisx0]]`, :samp:`cylPrms1=[[centrez1, centrey1, centrex1], radius1, axisLength1, [axisz1, axisy1, axisx1]]`, etc. If :samp:`{retcylimg}` is :samp:`True`, additionally returns segmented :obj:`mango.Dds` image labeled with cylinder boundaries (i.e. returns :samp:`pairList, segDds`). """ resolutions = list(resolutions) resolutions.sort() dsFactors = np.min(input.shape)/sp.array(resolutions, dtype="float64") if (dsFactors[-1] < 1): dsFactors[-1] = 1.0 dsFactors = sp.array([dsFactor for dsFactor in dsFactors if dsFactor >= 1], dtype=dsFactors.dtype) i = 0 rootLogger.info("Downsample factors = %s." % (dsFactors,)) rootLogger.info("Downsampling (resolution=%s) input.shape=%s to shape=%s..." % (resolutions[i], input.shape, input.shape/dsFactors[i])) input.updateOverlapRegions() input.mirrorOuterLayersToBorder(False) dsInput = mango.image.gaussian_downsample(input, factor=[1.0/dsFactors[0],]*3) dsInput.updateHaloRegions() dsInput.mirrorOuterLayersToBorder(False) # Do data-parallel parallelism for all resolutions, having a copy of # the global downsampled gradient-vector image on all processes tends # to be too memory hungary. distributedMetricEvaluation = True rootLogger.info("Done downsampling, new shape=%s." % (dsInput.shape, )) cylPrmList = \ cylinder_fit( input = dsInput, numcyl=numcyl, retcylimg = False, distributedMetricEvaluation = distributedMetricEvaluation, metric = metric, radius_range_percent = radius_range_percent, centre_range_percent = centre_range_percent, metricThreshRelTol = metricThreshRelTol ) rootLogger.info("Lowest resolution fit cylinders=:\n%s" % ("\n".join(map(str, cylPrmList)))) del dsInput dsInput = None fitter = None distributedMetricEvaluation = True i = 1 if (metric == None): metric = cylinder_fit_gradient_metric() for dsFactor in dsFactors[1:]: metric.setNumSlices(metric.getNumSlices() + 10) metric.setNumPointsPerSlice(int(metric.getNumPointsPerSlice()*1.25)) if (dsFactor > 1): rootLogger.info("Downsampling (resolution=%s) input.shape=%s to shape=%s..." % (resolutions[i], input.shape, input.shape/dsFactor)) dsInput = mango.image.gaussian_downsample(input, factor=[1.0/dsFactor,]*3) rootLogger.info("Done downsampling, new shape=%s." % (dsInput.shape, )) else: rootLogger.info("Full resolution refinement input.shape=%s..." % (input.shape,)) dsInput = input if (input.mpi.comm != None): input.mpi.comm.barrier() dsInput.updateHaloRegions() dsInput.mirrorOuterLayersToBorder(False) rootLogger.info("Cylinder-fit refinement for resolution image shape=%s." % (dsInput.shape,)) fitter = \ _CylinderFitter( input = dsInput, numcyl = numcyl, distributedMetricEvaluation = distributedMetricEvaluation, metric = metric, radius_range_percent = radius_range_percent, centre_range_percent = centre_range_percent, axis_range_degrees = None, metricThreshRelTol = metricThreshRelTol ) if (i >= (len(dsFactors)-1)): fitter.minimize_options['xtol'] = 1.0e-4 fitter.minimize_options['ftol'] = (fitter.minimize_options['xtol'])**2 cylPrmList = fitter.refineFit(cylPrmList) rootLogger.info("Done cylinder-fit refinement for resolution image shape=%s." % (dsInput.shape,)) rootLogger.info("Fit cylinders=:\n%s" % ("\n".join(map(str, cylPrmList)))) i+=1 del dsInput, fitter dsInput = None fitter = None retVal = cylPrmList if (retcylimg): cylPrmList = [cylfit[1] for cylfit in cylPrmList] cylImg = mango.copy(input, mtype="segmented") cylImg.setAllToValue(cylImg.mtype.maskValue()) cylImg = fill_cylinder_boundaries(cylPrmList, cylImg) retVal = [retVal, cylImg] return retVal