function brushed(skipTimer) {

        if (!skipTimer) {
            // set a timer to reset focus chart to real-time data
            clearTimeout(brushTimer);
            brushTimer = setTimeout(updateBrushToNow, BRUSH_TIMEOUT);
            brushInProgress = true;
        }

        var brushExtent = brush.extent();

        // ensure that brush extent is fixed at 3.5 hours
        if (brushExtent[1].getTime() - brushExtent[0].getTime() != FOCUS_DATA_RANGE_MS) {

            // ensure that brush updating is with the time range
            if (brushExtent[0].getTime() + FOCUS_DATA_RANGE_MS > d3.extent(data, dateFn)[1].getTime()) {
                d3.select('.brush')
                    .call(brush.extent([new Date(brushExtent[1].getTime() - FOCUS_DATA_RANGE_MS), brushExtent[1]]));
            } else {
                d3.select('.brush')
                    .call(brush.extent([brushExtent[0], new Date(brushExtent[0].getTime() + FOCUS_DATA_RANGE_MS)]));
            }
        }

        xScale.domain(brush.extent());

        // bind up the focus chart data to an array of circles
        var focusCircles = focus.selectAll('circle').data(data, dateFn);

        // if already existing then transition each circle to its new position
        focusCircles.transition()
            .duration(UPDATE_TRANS_MS)
            .attr('cx', function (d) { return xScale(d.date); })
            .attr('cy', function (d) { return yScale(d.sgv);  })
            .attr('fill', function (d) { return d.color;      });

        // if new circle then just display
        focusCircles.enter().append('circle')
            .attr('cx', function (d) { return xScale(d.date); })
            .attr('cy', function (d) { return yScale(d.sgv);  })
            .attr('fill', function (d) { return d.color;      })
            .attr('r', 3);

        focusCircles.exit()
            .remove();

        // remove all insulin/carb treatment bubbles so that they can be redrawn to correct location
        d3.selectAll('.path').remove();

        // add treatment bubbles
        var bubbleSize = prevChartWidth < 400 ? 4 : (prevChartWidth < 600 ? 3 : 2);
        focus.selectAll('circle')
            .data(treatments)
            .each(function (d) { drawTreatment(d, bubbleSize, true)});

        // transition open-top line to correct location
        focus.select('.open-top')
            .attr('x1', xScale2(brush.extent()[0]))
            .attr('y1', yScale(30))
            .attr('x2', xScale2(brush.extent()[1]))
            .attr('y2', yScale(30));

        // transition open-left line to correct location
        focus.select('.open-left')
            .attr('x1', xScale2(brush.extent()[0]))
            .attr('y1', focusHeight)
            .attr('x2', xScale2(brush.extent()[0]))
            .attr('y2', prevChartHeight);

        // transition open-right line to correct location
        focus.select('.open-right')
            .attr('x1', xScale2(brush.extent()[1]))
            .attr('y1', focusHeight)
            .attr('x2', xScale2(brush.extent()[1]))
            .attr('y2', prevChartHeight);

        focus.select('.now-line')
            .transition()
            .duration(UPDATE_TRANS_MS)
            .attr('x1', xScale(new Date(now)))
            .attr('y1', yScale(36))
            .attr('x2', xScale(new Date(now)))
            .attr('y2', yScale(420));

        // update x axis
        focus.select('.x.axis')
            .call(xAxis);

        // add clipping path so that data stays within axis
        focusCircles.attr('clip-path', 'url(#clip)');
    }
// function to call when context chart is brushed
function to call when context chart is brushed
function to call when context chart is brushed
function brushed(skipTimer) {
        if (!skipTimer) {
            clearTimeout(brushTimer);
            brushTimer = setTimeout(updateBrushToNow, BRUSH_TIMEOUT);
            brushInProgress = true;
        }
        var brushExtent = brush.extent();
        if (brushExtent[1].getTime() - brushExtent[0].getTime() != FOCUS_DATA_RANGE_MS) {
            if (brushExtent[0].getTime() + FOCUS_DATA_RANGE_MS > d3.extent(data, dateFn)[1].getTime()) {
                d3.select('.brush')
                    .call(brush.extent([new Date(brushExtent[1].getTime() - FOCUS_DATA_RANGE_MS), brushExtent[1]]));
            } else {
                d3.select('.brush')
                    .call(brush.extent([brushExtent[0], new Date(brushExtent[0].getTime() + FOCUS_DATA_RANGE_MS)]));
            }
        }
        xScale.domain(brush.extent());
        var focusCircles = focus.selectAll('circle').data(data, dateFn);
        focusCircles.transition()
            .duration(UPDATE_TRANS_MS)
            .attr('cx', function (d) { return xScale(d.date); })
            .attr('cy', function (d) { return yScale(d.sgv);  })
            .attr('fill', function (d) { return d.color;      });
        focusCircles.enter().append('circle')
            .attr('cx', function (d) { return xScale(d.date); })
            .attr('cy', function (d) { return yScale(d.sgv);  })
            .attr('fill', function (d) { return d.color;      })
            .attr('r', 3);
        focusCircles.exit()
            .remove();
        d3.selectAll('.path').remove();
        var bubbleSize = prevChartWidth < 400 ? 4 : (prevChartWidth < 600 ? 3 : 2);
        focus.selectAll('circle')
            .data(treatments)
            .each(function (d) { drawTreatment(d, bubbleSize, true)});
        focus.select('.open-top')
            .attr('x1', xScale2(brush.extent()[0]))
            .attr('y1', yScale(30))
            .attr('x2', xScale2(brush.extent()[1]))
            .attr('y2', yScale(30));
        focus.select('.open-left')
            .attr('x1', xScale2(brush.extent()[0]))
            .attr('y1', focusHeight)
            .attr('x2', xScale2(brush.extent()[0]))
            .attr('y2', prevChartHeight);
        focus.select('.open-right')
            .attr('x1', xScale2(brush.extent()[1]))
            .attr('y1', focusHeight)
            .attr('x2', xScale2(brush.extent()[1]))
            .attr('y2', prevChartHeight);
        focus.select('.now-line')
            .transition()
            .duration(UPDATE_TRANS_MS)
            .attr('x1', xScale(new Date(now)))
            .attr('y1', yScale(36))
            .attr('x2', xScale(new Date(now)))
            .attr('y2', yScale(420));
        focus.select('.x.axis')
            .call(xAxis);
        focusCircles.attr('clip-path', 'url(#clip)');
    }
function brushed ( skipTimer ) { if ( ! skipTimer ) { clearTimeout ( brushTimer ) ; brushTimer = setTimeout ( updateBrushToNow , BRUSH_TIMEOUT ) ; brushInProgress = true ; } var brushExtent = brush . extent ( ) ; if ( brushExtent [ 1 ] . getTime ( ) - brushExtent [ 0 ] . getTime ( ) != FOCUS_DATA_RANGE_MS ) { if ( brushExtent [ 0 ] . getTime ( ) + FOCUS_DATA_RANGE_MS > d3 . extent ( data , dateFn ) [ 1 ] . getTime ( ) ) { d3 . select ( '.brush' ) . call ( brush . extent ( [ new Date ( brushExtent [ 1 ] . getTime ( ) - FOCUS_DATA_RANGE_MS ) , brushExtent [ 1 ] ] ) ) ; } else { d3 . select ( '.brush' ) . call ( brush . extent ( [ brushExtent [ 0 ] , new Date ( brushExtent [ 0 ] . getTime ( ) + FOCUS_DATA_RANGE_MS ) ] ) ) ; } } xScale . domain ( brush . extent ( ) ) ; var focusCircles = focus . selectAll ( 'circle' ) . data ( data , dateFn ) ; focusCircles . transition ( ) . duration ( UPDATE_TRANS_MS ) . attr ( 'cx' , function ( d ) { return xScale ( d . date ) ; } ) . attr ( 'cy' , function ( d ) { return yScale ( d . sgv ) ; } ) . attr ( 'fill' , function ( d ) { return d . color ; } ) ; focusCircles . enter ( ) . append ( 'circle' ) . attr ( 'cx' , function ( d ) { return xScale ( d . date ) ; } ) . attr ( 'cy' , function ( d ) { return yScale ( d . sgv ) ; } ) . attr ( 'fill' , function ( d ) { return d . color ; } ) . attr ( 'r' , 3 ) ; focusCircles . exit ( ) . remove ( ) ; d3 . selectAll ( '.path' ) . remove ( ) ; var bubbleSize = prevChartWidth < 400 ? 4 : ( prevChartWidth < 600 ? 3 : 2 ) ; focus . selectAll ( 'circle' ) . data ( treatments ) . each ( function ( d ) { drawTreatment ( d , bubbleSize , true ) } ) ; focus . select ( '.open-top' ) . attr ( 'x1' , xScale2 ( brush . extent ( ) [ 0 ] ) ) . attr ( 'y1' , yScale ( 30 ) ) . attr ( 'x2' , xScale2 ( brush . extent ( ) [ 1 ] ) ) . attr ( 'y2' , yScale ( 30 ) ) ; focus . select ( '.open-left' ) . attr ( 'x1' , xScale2 ( brush . extent ( ) [ 0 ] ) ) . attr ( 'y1' , focusHeight ) . attr ( 'x2' , xScale2 ( brush . extent ( ) [ 0 ] ) ) . attr ( 'y2' , prevChartHeight ) ; focus . select ( '.open-right' ) . attr ( 'x1' , xScale2 ( brush . extent ( ) [ 1 ] ) ) . attr ( 'y1' , focusHeight ) . attr ( 'x2' , xScale2 ( brush . extent ( ) [ 1 ] ) ) . attr ( 'y2' , prevChartHeight ) ; focus . select ( '.now-line' ) . transition ( ) . duration ( UPDATE_TRANS_MS ) . attr ( 'x1' , xScale ( new Date ( now ) ) ) . attr ( 'y1' , yScale ( 36 ) ) . attr ( 'x2' , xScale ( new Date ( now ) ) ) . attr ( 'y2' , yScale ( 420 ) ) ; focus . select ( '.x.axis' ) . call ( xAxis ) ; focusCircles . attr ( 'clip-path' , 'url(#clip)' ) ; }
function to call when context chart is brushed
function to call when context chart is brushed
// set a timer to reset focus chart to real-time data // ensure that brush extent is fixed at 3.5 hours // ensure that brush updating is with the time range // bind up the focus chart data to an array of circles // if already existing then transition each circle to its new position // if new circle then just display // remove all insulin/carb treatment bubbles so that they can be redrawn to correct location // add treatment bubbles // transition open-top line to correct location // transition open-left line to correct location // transition open-right line to correct location // update x axis // add clipping path so that data stays within axis