@@ -534,16 +534,31 @@ auto statDensity2D(AES)( AES aesRaw )
534534 (a,b) => safeMax(a,b.y.to! double ),
535535 )(tuple(double .init,double .init,double .init,double .init), aes);
536536
537+ if (minmax[0 ] == minmax[1 ]) {
538+ minmax[0 ] -= 0.5 ;
539+ minmax[1 ] += 0.5 ;
540+ }
541+ if (minmax[2 ] == minmax[3 ]) {
542+ minmax[2 ] -= 0.5 ;
543+ minmax[3 ] += 0.5 ;
544+ }
545+
537546 return aes.group! (Erase! (" colour" ,DefaultGroupFields)).map! ((g) {
538547 auto xs = g.map! ((t) => t.x.to! double );
539548 auto ys = g.map! ((t) => t.y.to! double );
540549
550+ import std.math : isFinite;
541551 // Calculate the kernel width (using scott thing in dstats)
542552 // Initialize kernel with normal distribution.
543553 import dstats.kerneldensity : scottBandwidth, KernelDensity;
544554 import dstats.random : normalPDF;
545555 auto sigmaX = scottBandwidth(xs);
556+ if (! isFinite(sigmaX) || sigmaX <= 0 )
557+ sigmaX = 1e-5 ;
546558 auto sigmaY = scottBandwidth(ys);
559+ if (! isFinite(sigmaY) || sigmaY <= 0 )
560+ sigmaY = 1e-5 ;
561+
547562 auto kernel = (double x, double y) { return normalPDF(x, 0.0 , sigmaX)*
548563 normalPDF(y, 0.0 , sigmaY); };
549564 auto density = KernelDensity.fromCallable(kernel, xs, ys);
@@ -603,4 +618,12 @@ unittest
603618 assertGreaterThan( sD.walkLength, 1150 );
604619 assertLessThan( sD.walkLength, 1450 );
605620 assertEqual( sD.front.walkLength, 3 );
621+
622+ // One value
623+ xs = [1 ];
624+ ys = [2 ];
625+ aes = Aes! (typeof (xs), " x" , typeof (ys), " y" )( xs, ys);
626+
627+ sD = statDensity2D( aes );
628+ assertGreaterThan(sD.walkLength, 0 );
606629}
0 commit comments