2d2280e95cbe331ebb8411fcb9ec600ac8200898
max
  Fri Jun 20 10:35:37 2025 -0700
comments

diff --git src/cbPyLib/cellbrowser/cellbrowser.py src/cbPyLib/cellbrowser/cellbrowser.py
index d0905fd..ebd6d0a 100755
--- src/cbPyLib/cellbrowser/cellbrowser.py
+++ src/cbPyLib/cellbrowser/cellbrowser.py
@@ -72,32 +72,35 @@
 dataDir = None
 
 # the default html dir, used if the --htmlDir option is set but empty
 # this variable is initialized below (no forward declaration in Python)
 # just before cbBuild_parseArgs
 defOutDir = None
 
 CBHOMEURL = "https://cells.ucsc.edu/downloads/cellbrowserData/"
 CBHOMEURL_TEST = "https://cells-test.gi.ucsc.edu/downloads/cellbrowserData/"
 
 # a special value that is used for both x and y to indicate that the cell should not be shown
 # must match the same value in maxPlot.js
 HIDDENCOORD = 12345
 
 # special value representing NaN in floating point arrays
+# sorting is used everywhere in the code, and sorting is fast, so we replace all NaNs with -inf
+# This means that all arrays can be sorted with the normal, fast javascript functions
 # must match the same value in cellBrowser.js
-FLOATNAN = float('-inf') # NaN and sorting does not work. we want NaN always to be first, so encode as -inf
+FLOATNAN = float('-inf')
+
 # special value representing NaN in integer arrays, again, we want this to be first after sorting
 # must match the same value in cellBrowser.js
 INTNAN = -2**16
 
 # how many md5 characters to keep in version identifiers. We load all files using their md5 to get around
 # internet browser caching
 MD5LEN = 10
 
 # list of tags that are required:
 # for cellbrowser.conf of a dataset
 reqTagsDataset =['coords', 'meta']
 # for cellbrowser.conf of a collection
 reqTagsColl =['shortLabel']
 
 coordLabels = {
@@ -976,31 +979,31 @@
     mode where the first bin is reserved for NaNs (encoded as -inf)
     >>> findBins([1,1,1,2,2,2,3,3,4,4,5,5,6,6], [1, 2,3,5,6])
     ([0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 2, 2, 3, 3], [6, 2, 4, 2])
     """
     bArr = []
     binCounts = [0]*(len(breakVals)-1)
 
     # NaNs mean that the non-NaN bins are all +1
     if hasNan:
         breaks = breakVals[2:]
     else:
         breaks = breakVals[1:]
 
     if hasNan:
         for x in numVals:
-            # we use -inf for the NaN value everywhere, sorting is undefined in lists that contain NaN
+            # we use -inf for the NaN value everywhere, because sorting is undefined in lists that contain NaN
             if math.isinf(x):
                 binIdx = 0
             else:
                 binIdx = bisect.bisect_left(breaks, x)+1
             bArr.append(binIdx)
             binCounts[binIdx]+=1
     else:
         for x in numVals:
             binIdx = bisect.bisect_left(breaks, x) # comparison operator is <=
             bArr.append(binIdx)
             binCounts[binIdx]+=1
 
     return bArr, binCounts
 
 def countBinsBetweenBreaks(numVals, breakVals):