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):