fee658e200a700b6ff336bcb5d449892021e5708 max Fri May 2 10:08:38 2025 -0700 adding one more drawing stage so when plotting gene expression zero values will not interfere with non zero values diff --git src/cbPyLib/cellbrowser/cbWeb/js/maxPlot.js src/cbPyLib/cellbrowser/cbWeb/js/maxPlot.js index 942da9a..94ffd6a 100644 --- src/cbPyLib/cellbrowser/cbWeb/js/maxPlot.js +++ src/cbPyLib/cellbrowser/cbWeb/js/maxPlot.js @@ -854,37 +854,69 @@ function drawRect(ctx, pxCoords, coordColors, colors, radius, alpha, selCells, fatIdx) { /* draw not circles but tiny rectangles. Maybe good enough for 2pixels sizes */ debug("Drawing "+coordColors.length+" rectangles, with fillRect"); ctx.save(); ctx.globalAlpha = alpha; var dblSize = 2*radius; var count = 0; if (selCells.size!==0 || fatIdx!==null) //colors = makeAllGreyHex(colors.length); colors = hexToGrey(colors); var fatCells = []; + // first draw all the cells with value 0. Poor mans approximation of a z index. + // (Should be faster than sorting by z and drawing afterwards.) for (var i = 0; i < pxCoords.length/2; i++) { var pxX = pxCoords[2*i]; var pxY = pxCoords[2*i+1]; if (isHidden(pxX, pxY)) continue; var valIdx = coordColors[i]; + // only plot color 0 + if (valIdx!==0) + continue; + + var col = colors[valIdx]; + if (fatIdx!==null) { + if (valIdx===fatIdx) { + // fattened cells must be overdrawn later, so just save their coords now + fatCells.push(pxX); + fatCells.push(pxY); + continue + } + } + ctx.fillStyle="#"+col; + ctx.fillRect(pxX-radius, pxY-radius, dblSize, dblSize); + count++; + } + + // then draw all the cells with value <> 0. + for (var i = 0; i < pxCoords.length/2; i++) { + var pxX = pxCoords[2*i]; + var pxY = pxCoords[2*i+1]; + if (isHidden(pxX, pxY)) + continue; + + var valIdx = coordColors[i]; + // only plot color != 0 + if (valIdx===0) + continue; + var col = colors[valIdx]; if (fatIdx!==null) { if (valIdx===fatIdx) { // fattened cells must be overdrawn later, so just save their coords now fatCells.push(pxX); fatCells.push(pxY); continue } //else //col = "DDDDDD"; //col = nonFatColorRect; } ctx.fillStyle="#"+col; ctx.fillRect(pxX-radius, pxY-radius, dblSize, dblSize); @@ -1284,47 +1316,73 @@ // //if (radius>=5) //ctx.drawImage(off, selImgId * tileWidth, 0, tileWidth, tileHeight, pxX - radius -1, pxY - radius-1, tileWidth, tileHeight); //} //return count; //} function blitAll(ctx, off, pxCoords, coordColors, tileWidth, tileHeight, radius, selCells, greyIdx, fatIdx, colors) { /* blit the circles onto the main canvas, using all colors */ var count = 0; var hasSelection = false; if (selCells.size!==0) hasSelection = true; var col = 0; + // first draw all the cells of the color 0 for (let i = 0; i < pxCoords.length/2; i++) { var pxX = pxCoords[2*i]; var pxY = pxCoords[2*i+1]; if (isHidden(pxX, pxY)) continue; // when a selection is active, draw everything in grey. This only works because the selection is overdrawn afterwards // (The selection must be overdrawn later, because otherwise circles shine through the selection) col = coordColors[i]; + count++; + // only draw the cells of entry 0 of the palette first. + // This is a poor approximation of a z-index, but a real z-index would take way too long. + // So we're just drawing twice. + if (col!==0) + continue + if (fatIdx===null) { + if (hasSelection) + col = greyIdx; + } + else if (!hasSelection && !(fatIdx!=null && fatIdx===col)) + col = greyIdx; + + ctx.drawImage(off, col * tileWidth, 0, tileWidth, tileHeight, pxX - radius - 1, pxY - radius - 1, tileWidth, tileHeight); + } + + // then draw all the cells with the colors != 0 + for (let i = 0; i < pxCoords.length/2; i++) { + var pxX = pxCoords[2*i]; + var pxY = pxCoords[2*i+1]; + if (isHidden(pxX, pxY)) + continue; + + col = coordColors[i]; + if (col===0) + continue if (fatIdx===null) { if (hasSelection) col = greyIdx; } else if (!hasSelection && !(fatIdx!=null && fatIdx===col)) col = greyIdx; - count++; ctx.drawImage(off, col * tileWidth, 0, tileWidth, tileHeight, pxX - radius - 1, pxY - radius - 1, tileWidth, tileHeight); } if (fatIdx!==null) { // do not fatten //radius = radius * 2; //let templates = makeCircleTemplates(radius, tileWidth, tileHeight, colors, fatIdx); //let off = templates.off; radius *= 1.5; for (let i = 0; i < pxCoords.length/2; i++) { col = coordColors[i]; if (fatIdx!==col) continue; var pxX = pxCoords[2*i]; var pxY = pxCoords[2*i+1];