Skip to content

Commit

Permalink
hotloading of programs; fixed memory leak in preRender; fully functio…
Browse files Browse the repository at this point in the history
…nal (SLOW); black frame on image transition
  • Loading branch information
tbenst committed Nov 29, 2019
1 parent bd982d0 commit 4b0951a
Show file tree
Hide file tree
Showing 38 changed files with 345 additions and 138 deletions.
3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ COPY web/package-lock.json /www
RUN npm install --quiet
COPY web/src /www/src
COPY web/view /www/view
COPY .git /tmp/
RUN git -C /tmp rev-parse --verify HEAD > /www/git-sha
RUN rm -rf /tmp/.git
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ Or by using Image type, can just define in EPL preRenderFunc! See eyechart-sacca
## TODOs
replace koa-socket-session with something better supported (1.2.0 fails)
update to koa-socket-2
make sure I didn't break shuffle with new randint
- Chunk number of stimmuli returned

- Chunk number of stimmuli returned by server to lower number of requsets
- make preRenderFunc a generator, store images in localStorage
- render: read from localStorage

### video
- Always save video
Expand Down
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ web:
command: node --max-old-space-size=8192 --harmony src/app.js
volumes:
- /data/eye-candy:/data
- ./web/programs:/www/programs
links:
- redis
redis:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ r.shuffle(stimuli)

stimuli = flatten(stimuli)

function* stimulusGenerator(renderResults) {
function* stimulusGenerator() {
for (s of stimuli) {
yield s
}
Expand Down
98 changes: 51 additions & 47 deletions web/src/programs/acuity.js → web/programs/acuity.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,19 @@ function* measureIntegrity(stimuli,every=5*60) {

// special function for pre-rendering. This is passed as a string
// and run client-side
function preRenderFunc(binaryNoiseNframes, randomSeed) {
function* preRenderFunc(binaryNoiseNframes, randomSeed) {
console.log("In preRender...")

function renderFrame(flatPixelArray) {
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d")
canvas.width = WIDTH
canvas.height = HEIGHT
imageData = new ImageData(flatPixelArray, WIDTH, HEIGHT)
context.putImageData(imageData, 0, 0)
return canvas
}

console.assert(binaryNoiseNframes % 2 == 0)
// client-side
let r = new DeterministicRandom(randomSeed)
Expand All @@ -38,59 +48,53 @@ function preRenderFunc(binaryNoiseNframes, randomSeed) {
// let binaryNoiseNframes =14
let pixelArrays = []
let singlePixel = Uint8ClampedArray.from(Array(binaryNoiseNframes/2).fill(0).concat(Array(binaryNoiseNframes/2).fill(255)))
for (var p = 0; p < nPixels; p++) {
// benchmark: 50% of time is from shuffle
r.shuffle(singlePixel)
// ... allows for array copy
pixelArrays.push([...singlePixel])
if (p % 10000 == 0) {
console.log("pushed array for pixel: ", p)
}
}


// RGBA array https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas
let allFrames = new Uint8ClampedArray(binaryNoiseNframes*nPixels*4)
// values of single pixel over time
// TODO why does making this nPixels/2 leave only ~1/4 of pixels with value??
for (var p = 0; p < nPixels; p++) {
singlePixel = pixelArrays[p]
for (var n = 0; n < binaryNoiseNframes; n++) {
// For example, to read the blue component's value from the pixel at column 200, row 50 in the image, you would do the following:
// blueComponent = imageData.data[(50 * (imageData.width * 4)) + (200 * 4) + 2]
allFrames[p*4 + n*nPixels*4] = singlePixel[n] // red
allFrames[1+p*4 + n*nPixels*4] = singlePixel[n] // green
allFrames[2+p*4 + n*nPixels*4] = singlePixel[n] // blue
allFrames[3+p*4 + n*nPixels*4] = 255 // alpha
}
if (p % 10000 == 0) {
console.log("pushed array for pixel: ", p)
}

}

function renderFrame(flatPixelArray) {
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d")
canvas.width = WIDTH
canvas.height = HEIGHT
imageData = new ImageData(flatPixelArray, WIDTH, HEIGHT)
context.putImageData(imageData, 0, 0)
return canvas
}
// chunk N frame increments to avoid memory overflow
let chunkNframes = 100
let chunkFrames
for (var i = 0; i < binaryNoiseNframes; i = i + chunkNframes) {
// equal to chunkNframes except for final iteration
chunkNframes = Math.min(chunkNframes, binaryNoiseNframes-i)
chunkFrames = new Uint8ClampedArray(chunkNframes*nPixels*4)

// create balanced pixel assignments
pixelArrays = []
for (var p = 0; p < nPixels; p++) {
// benchmark: 50% of time is from shuffle
r.shuffle(singlePixel)
// ... allows for array copy
pixelArrays.push([...singlePixel])
if (p % 10000 == 0) {
console.log("pushed array for pixel: ", p)
}
}

let frames = []
for (var n = 0; n < binaryNoiseNframes; n++) {
frames.push(renderFrame(allFrames.slice(n*nPixels*4,(n+1)*nPixels*4)))
// assign values of each pixel over time
for (var p = 0; p < nPixels; p++) {
singlePixel = pixelArrays[p]
for (var n = 0; n < chunkNframes; n++) {
// For example, to read the blue component's value from the pixel at column 200, row 50 in the image, you would do the following:
// blueComponent = imageData.data[(50 * (imageData.width * 4)) + (200 * 4) + 2]
chunkFrames[p*4 + n*nPixels*4] = singlePixel[n] // red
chunkFrames[1+p*4 + n*nPixels*4] = singlePixel[n] // green
chunkFrames[2+p*4 + n*nPixels*4] = singlePixel[n] // blue
chunkFrames[3+p*4 + n*nPixels*4] = 255 // alpha
}
if (p % 10000 == 0) {
console.log("pushed array for pixel: ", p)
}
}
// yield each frame from chunk
for (var n = 0; n < chunkNframes; n++) {
yield renderFrame(chunkFrames.slice(n*nPixels*4,(n+1)*nPixels*4))
}
}
console.log("frames[0]", frames[0])

return {renders: frames,
yield: {}}
}

// special object for pre-rendering
const binaryNoiseDuration = 0.1*60
const binaryNoiseDuration = 5*60
const frameRate = 60
const hz = 5
const binaryNoiseLifespan = 1 / hz
Expand Down Expand Up @@ -197,7 +201,7 @@ r.shuffle(stimuli)
stimuli = measureIntegrity(flatten(stimuli))
stimuli = celltypeStimuli.concat(stimuli)

function* stimulusGenerator(renderResults) {
function* stimulusGenerator() {
for (s of stimuli) {
yield s
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ r.shuffle(stimuli)

stimuli = insertBreaks(measureIntegrity(flatten(stimuli)))

function* stimulusGenerator(renderResults) {
function* stimulusGenerator() {
for (s of stimuli) {
yield s
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ r.shuffle(stimuli)

stimuli = measureIntegrity(flatten(stimuli))

function* stimulusGenerator(renderResults) {
function* stimulusGenerator() {
for (s of stimuli) {
yield s
}
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ r.shuffle(stimuli)

stimuli = measureIntegrity(flatten(stimuli))

function* stimulusGenerator(renderResults) {
function* stimulusGenerator() {
for (s of stimuli) {
yield s
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ for (var i = 0; i < repetitions; i++) {
}


function* stimulusGenerator(renderResults) {
function* stimulusGenerator() {
for (s of stimuli) {
yield s
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ r.shuffle(stimuli)

stimuli = measureIntegrity(flatten(stimuli))

function* stimulusGenerator(renderResults) {
function* stimulusGenerator() {
for (s of stimuli) {
yield s
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ function twoLetterMatrices(nrows) {
for (var j = 0; j < ncols; j++) {
firstLetterMatrix[i][j] = newLetters[j]
secondLetterMatrix[i][j] = newLetters[j+5]

cohortMatrix[i][j] = cohortID
}
}
Expand Down Expand Up @@ -93,7 +93,7 @@ function calcFixationPoints(sizes, ncols) {
let rowWidth
for (var i = 0; i < nrows; i++) {
size = sizes[i]
y = y + 2*size
y = y + 2*size

rowWidth = (2*ncols+1) * size
if (i==0) {
Expand Down Expand Up @@ -186,14 +186,13 @@ function preRenderFunc(sizes, reps, ncols, color, letterTensor,

let nrows = sizes.length
let eyecharts = []

for (var i = 0; i < letterTensor.length; i++) {
// console.log("letterTensor[i]", letterTensor[i])
let image = renderEyechart(sizes, ncols, letterTensor[i], color)
eyecharts.push(image)
}
return {renders: eyecharts,
yield: {}}
return {renders: eyecharts}
}

// special object for pre-rendering
Expand Down Expand Up @@ -221,8 +220,8 @@ function* gen() {
}

// TODO add integrity
function* stimulusGenerator(renderResults) {
function* stimulusGenerator() {
for (let s of measureIntegrity(gen())) {
yield s
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ r.shuffle(stimuli)

stimuli = measureIntegrity(flatten(stimuli))

function* stimulusGenerator(renderResults) {
function* stimulusGenerator() {
for (s of stimuli) {
yield s
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ let meta = {}
stimuli.push!(new Video(1000, "black", DATADIR+"videos/cropped.mp4", meta))


function* stimulusGenerator(renderResults) {
function* stimulusGenerator() {
for (s of stimuli) {
yield s
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ r.shuffle(stimuli)

stimuli = insertBreaks(measureIntegrity(flatten(stimuli)))

function* stimulusGenerator(renderResults) {
function* stimulusGenerator() {
for (s of stimuli) {
yield s
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ r.shuffle(stimuli)

stimuli = measureIntegrity(flatten(stimuli))

function* stimulusGenerator(renderResults) {
function* stimulusGenerator() {
for (s of stimuli) {
yield s
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ r.shuffle(stimuli)

stimuli = insertBreaks(measureIntegrity(flatten(stimuli)))

function* stimulusGenerator(renderResults) {
function* stimulusGenerator() {
for (s of stimuli) {
yield s
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ r.shuffle(stimuli)

stimuli = measureIntegrity(flatten(stimuli))

function* stimulusGenerator(renderResults) {
function* stimulusGenerator() {
for (s of stimuli) {
yield s
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ r.shuffle(stimuli)

stimuli = measureIntegrity(flatten(stimuli))

function* stimulusGenerator(renderResults) {
function* stimulusGenerator() {
for (s of stimuli) {
yield s
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ r.shuffle(stimuli)

stimuli = measureIntegrity(flatten(stimuli))

function* stimulusGenerator(renderResults) {
function* stimulusGenerator() {
for (s of stimuli) {
yield s
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ r.shuffle(stimuli)

stimuli = measureIntegrity(flatten(stimuli))

function* stimulusGenerator(renderResults) {
function* stimulusGenerator() {
for (s of stimuli) {
yield s
}
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion web/src/programs/grating.js → web/programs/grating.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ r.shuffle(stimuli)

stimuli = measureIntegrity(flatten(stimuli))

function* stimulusGenerator(renderResults) {
function* stimulusGenerator() {
for (s of stimuli) {
yield s
}
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ r.shuffle(stimuli)

stimuli = measureIntegrity(flatten(stimuli))

function* stimulusGenerator(renderResults) {
function* stimulusGenerator() {
for (s of stimuli) {
yield s
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,7 @@ function preRenderFunc(sizes, letters, color) {
renderedLetters[idx] = image
}
}
return {renders: renderedLetters,
yield: {}}
return {renders: renderedLetters}
}

// special object for pre-rendering
Expand Down Expand Up @@ -121,7 +120,7 @@ r.shuffle(stimuli)

stimuli = measureIntegrity(flatten(stimuli))

function* stimulusGenerator(renderResults) {
function* stimulusGenerator() {
for (let s of stimuli) {
yield s
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ r.shuffle(stimuli)

stimuli = measureIntegrity(flatten(stimuli))

function* stimulusGenerator(renderResults) {
function* stimulusGenerator() {
for (s of stimuli) {
yield s
}
Expand Down
2 changes: 1 addition & 1 deletion web/src/programs/letters.js → web/programs/letters.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ r.shuffle(stimuli)

stimuli = measureIntegrity(flatten(stimuli))

function* stimulusGenerator(renderResults) {
function* stimulusGenerator() {
for (s of stimuli) {
yield s
}
Expand Down
Loading

0 comments on commit 4b0951a

Please sign in to comment.