diff --git a/breath_plot.html b/breath_plot.html
index fb7eda9e7213c8a9312a78a05235ab4e97f62a9c..2c052288274c44fb6a3efe93912ddb9c3c64dadf 100644
--- a/breath_plot.html
+++ b/breath_plot.html
@@ -325,7 +325,7 @@ an interactive or static analysis of a respiration. It's primary purpose is
                   </div>
                 </div>
                 <div>
-                  <label for="taip">TAIP (ms): </label>
+                  <label for="taip">Rise Time (ms): </label>
                   <div class="value_and_fences">
                     <div class="calcnum">
                       <label id="taip"> </label>
@@ -343,7 +343,7 @@ an interactive or static analysis of a respiration. It&#39;s primary purpose is
                 </div>
               </div>
                 <div>
-                  <label for="taip">TRIP (ms): </label>
+                  <label for="taip">Fall Time (ms): </label>
                   <div class="value_and_fences">
                     <div class="calcnum">
                       <label id="trip"> </label>
@@ -359,6 +359,23 @@ an interactive or static analysis of a respiration. It&#39;s primary purpose is
                     </div>
                   </div>
                 </div>
+                <div>
+                  <label for="wob">W. of B. (J/L): </label>
+                  <div class="value_and_fences">
+                    <div class="calcnum">
+                      <label id="wob"> </label>
+                    </div>
+                    <div class="vertical_alarms">
+                      <div class="limit max">
+                        <label for="wob_h">H:</label>
+                        <input class="fence" id="wob_h" type='text'> </input>
+                    </div>
+                    <div class="limit min">
+                      <label for="wob_l">L:</label>
+                      <input class="fence" id="wob_l" type='text'> </input>
+                    </div>
+                  </div>
+                </div>
               </div>
             </div>
           </div>
@@ -370,11 +387,11 @@ an interactive or static analysis of a respiration. It&#39;s primary purpose is
   <div>
   Parameters:
   <div>
-        <label for="tarip_h">TAIP/TRIP High Pressure (cm H2O):</label>
+        <label for="tarip_h">Rise/Fall High Pressure (cm H2O):</label>
   <input class="fence" id="tarip_h" type='text'> </input>
   </div>
   <div>
-        <label for="tarip_l">TAIP/TRIP Low Pressure (cm H2O):</label>
+        <label for="tarip_l">Rise/Fall Low Pressure (cm H2O):</label>
   <input class="fence" id="tarip_l" type='text'> </input>
   </div>
 </div>
@@ -669,10 +686,30 @@ function plot(samples, trans, breaths) {
         ,0);
       var max_v = Math.max(max_inh,max_exh);
 
+      // not sure why I have null work, have to understand.
+      var max_work_per_liter = 0;
+      var work_per_liter = [];
+      for(var i = 0; i < breaths.length; i++) {
+        var b = breaths[i];
+        if (b.work != null) {
+          var wpl = b.work / b.vol_i;
+          if (wpl > max_work_per_liter)
+            max_work_per_liter = wpl;
+          var center = ((trans[b.trans_begin_inhale].ms + trans[b.trans_cross_zero].ms) - 2*min) / (2.0 * 1000.0);
+          work_per_liter.push({ wpl: wpl, center: center });
+        }
+      }
+
       var exh_v = unpack(breaths, 'vol_e').map(e => 100 * e / max_v);
       var t_exh_v =  unpack(breaths, 'vol_e').map(e => Math.round(e*1000.0)+"ml exh");
       var inh_v = unpack(breaths, 'vol_i').map(i => 100 * i / max_v);
       var t_inh_v = unpack(breaths, 'vol_i').map(e => Math.round(e*1000.0)+"ml inh");
+
+
+      var work_v = work_per_liter.map(w => (1/3) * (100 * w.wpl / max_work_per_liter));
+      var t_work = work_per_liter.map(w => w.wpl.toFixed(2)+"J/L");
+      var work_centers = unpack(work_per_liter, 'center');
+
       // now to graph properly, I must find the center of an inhalation.
       // I have packed these into the breaths...
       var inhale_centers = breaths.map(b => ((trans[b.trans_begin_inhale].ms + trans[b.trans_cross_zero].ms) - 2*min) / (2.0 * 1000.0));
@@ -700,6 +737,17 @@ function plot(samples, trans, breaths) {
                      text: t_exh_v,
 
                     };
+      var workPlot = {type: "scatter", mode: "markers+text",
+                     name: "WoB J",
+                     textposition: 'bottom center',
+                     x: work_centers,
+                     y: work_v,
+                     text: t_work,
+                     marker: { size: 8,
+                               color: 'blue',
+                               symbol: 'triangle-right'}
+                     };
+      event_graph.push(workPlot);
       event_graph.push(inhPlot);
       event_graph.push(exhPlot);
     }
@@ -738,22 +786,6 @@ function plot(samples, trans, breaths) {
                     };
       return plot;
 
-    }
-    function gen_clock_graph(selected,name,color, textposition) {
-      var millis = unpack(selected, 'ms');
-      var zeroed = millis.map(m =>(m-min)/1000.0);
-      var vs = selected.map( s => -30)
-      var vs_t = selected.map(v => v.buff);
-      var plot = {type: "scatter", mode: "markers+text",
-                     name: name,
-                     textposition: textposition,
-                     x: zeroed,
-                     y: vs,
-                     text: vs_t,
-                     marker: { size: 10, color: color }
-                    };
-      return plot;
-
     }
     function gen_message_events(samples,name,color, textposition) {
       var messages = samples.filter(s => s.event == 'E' && s.type == 'M');
@@ -763,7 +795,7 @@ function plot(samples, trans, breaths) {
       // Basically, we will show only the first of these in a "run"
       // This is rather difficult; we will instead just use 200 ms
       // as a window.
-      const time_window_ms = 200;
+      const TIME_WINDOW_MS = 400;
 
       var lows = [];
       var highs = [];
@@ -771,10 +803,10 @@ function plot(samples, trans, breaths) {
       for(var i = 0; i < messages.length; i++) {
         var m = messages[i];
         if (m.buff == FLOW_TOO_LOW) {
-          if ((lows.length == 0) || ((lows.length > 0) && (lows[lows.length-1].ms < (m.ms - time_window_ms))))
+          if ((lows.length == 0) || ((lows.length > 0) && (lows[lows.length-1].ms < (m.ms - TIME_WINDOW_MS))))
             lows.push(m);
         } else if (m.buff == FLOW_TOO_HIGH) {
-          if ((highs.length == 0) || ((highs.length > 0) && (highs[highs.length-1].ms < (m.ms - time_window_ms))))
+          if ((highs.length == 0) || ((highs.length > 0) && (highs[highs.length-1].ms < (m.ms - TIME_WINDOW_MS))))
             highs.push(m);
         } else {
           others.push(m);
@@ -797,20 +829,6 @@ function plot(samples, trans, breaths) {
                                  (v =>  v.buff));
       return [lowsPlot,highsPlot,othersPlot];
     }
-    function gen_clock_events(samples,name,color, textposition) {
-      var messages = samples.filter(s => s.event == 'E' && s.type == 'C');
-      const time_window_ms = 200;
-
-      var clocks = [];
-      for(var i = 0; i < messages.length; i++) {
-        var m = messages[i];
-         if ((clocks.length == 0) || ((clocks.length > 0) && (clocks[clocks.length-1].ms < (m.ms - time_window_ms))))
-            clocks.push(m);
-      }
-
-      var clocksPlot = gen_clock_graph(clocks,name,color,textposition);
-      return clocksPlot;
-    }
     {
       var fio2AirwayPlot = gen_graph_measurement_timed(samples,
                                                  "FiO2 (%)",
@@ -865,12 +883,6 @@ function plot(samples, trans, breaths) {
        event_graph.push(o);
      }
 
-     {
-       var cs = gen_clock_events(samples,"Wall Clock","black",'top center');
-
-       event_graph.push(cs);
-     }
-
 
 
     // The BME680 sensor detects VOC gases. I don't think has any clinical value
@@ -987,7 +999,13 @@ function compute_fio2_mean(secs,samples) {
   }
 }
 
-
+// returns:
+// [ respiration rate,
+// tidal volume (avg),
+// minute_volume
+// EIRatio,
+// Work-of-Breathing (avg)
+// ]
 function compute_respiration_rate(secs,samples,transitions,breaths) {
   // In order to compute the number of breaths
   // in the last s seconds, I compute those breaths
@@ -998,7 +1016,7 @@ function compute_respiration_rate(secs,samples,transitions,breaths) {
   var first_inhale_ms = -1;
   var last_inhale_ms = -1;
   if (breaths.length == 0) {
-    return [0,0,0,"NA"];
+    return [0,0,0,"NA","NA"];
   } else {
     const recent_ms = samples[samples.length - 1].ms;
     var cur_ms = recent_ms;
@@ -1013,6 +1031,9 @@ function compute_respiration_rate(secs,samples,transitions,breaths) {
     // divide by the inhlation_duration.
     var vol_ci = 0.0;
 
+    var wob = 0.0;
+    var wob_cnt = 0;
+
     while((i >=0) && (breaths[i].ms > (cur_ms - secs*1000))) {
       cnt++;
       vol_i += breaths[i].vol_i;
@@ -1029,6 +1050,11 @@ function compute_respiration_rate(secs,samples,transitions,breaths) {
       const zero_ms = transitions[breaths[i].trans_cross_zero].ms;
       time_inh += (zero_ms - inh_ms);
       time_exh += (exh_ms -  zero_ms);
+
+      if (breaths[i].work != null)  {
+        wob += breaths[i].work / breaths[i].vol_i;
+        wob_cnt++;
+      }
       i--;
     }
     if ((cnt > 1) && (first_inhale_ms != last_inhale_ms)) {
@@ -1044,16 +1070,18 @@ function compute_respiration_rate(secs,samples,transitions,breaths) {
       var tidal_volume = 1000.0 * vol_i / cnt;
 
       var EIratio = (time_inh == 0) ? null : time_exh / time_inh;
+      var WorkOfBreathing_J_per_L = wob / wob_cnt;
       return  [
         rr,
         tidal_volume,
         minute_volume,
-        EIratio];
+        EIratio,
+        WorkOfBreathing_J_per_L];
     } else {
-      return [0,0,0,"NA"];
+      return [0,0,0,"NA","NA"];
     }
   }
-      }
+}
 
 var LIMITS = {
   max: { h: 40,
@@ -1075,7 +1103,9 @@ var LIMITS = {
   taip: { h: 100, // These are in ms
          l: 0},
   trip: { h: 100, // These are in ms
-         l: 0},
+          l: 0},
+  wob: { h: 3,
+         l: 0.2},
 }
 
 function load_ui_with_defaults(limits) {
@@ -1121,13 +1151,19 @@ function process(samples) {
   var [transitions,breaths] = computeMovingWindowTrace(samples,t,v);
   plot(samples,transitions,breaths);
   // How many seconds backwards should we look? Perhaps 20?
-  var [bpm,tv,mv,EIratio,fio2] = compute_respiration_rate(RESPIRATION_RATE_WINDOW_SECONDS,samples,transitions,breaths);
+  var [bpm,tv,mv,EIratio,wob] = compute_respiration_rate(RESPIRATION_RATE_WINDOW_SECONDS,samples,transitions,breaths);
 
   var alarms = [];
 
   $("#bpm").text(bpm.toFixed(1));
   $("#tv").text(tv.toFixed(0));
-  $("#mv").text((mv).toFixed(2));
+  $("#mv").text(mv.toFixed(2));
+
+  if (wob == "NA") {
+    $("#wob").text("NA");
+  } else {
+    $("#wob").text(wob.toFixed(2));
+  }
   if (EIratio == "NA") {
     $("#ier").text("NA");
   } else {
@@ -1150,8 +1186,10 @@ function process(samples) {
 
   alarms = alarms.concat(check_high_and_low(LIMITS,"bpm",bpm.toFixed(1),b_ms));
   alarms = alarms.concat(check_high_and_low(LIMITS,"tv",tv.toFixed(0),b_ms));
-  alarms = alarms.concat(check_high_and_low(LIMITS,"mv",(mv).toFixed(2),b_ms));
+  alarms = alarms.concat(check_high_and_low(LIMITS,"mv",mv.toFixed(2),b_ms));
   alarms = alarms.concat(check_high_and_low(LIMITS,"ier",(1.0 / EIratio).toFixed(1),b_ms));
+  if (wob != "NA")
+    alarms = alarms.concat(check_high_and_low(LIMITS,"wob",wob.toFixed(2),b_ms));
 
   // These must be moved out; in fact,
   // they must be made configurable!
@@ -1236,26 +1274,34 @@ function retrieveAndPlot(){
               // WARNING: This is a hack...if the timestamp is negative,
               // we treat it as a limited (beyond range of sensor) measurement.
               // Our goal is to warn about this, but for now we will just
-              // ignore and correct.
+            // ignore and correct.
+            if (cur_sam == null) {
+              console.log("No return");
+              return;
+            }
             if (cur_sam && cur_sam.length == 0) {
               console.log("no samples; potential misconfiguration!");
             } else {
-              cur_sam = sanitize_samples(cur_sam);
-	      if (INITS_ONLY) {
-	        samples = cur_sam;
-	        INITS_ONLY = false;
-	      } else {
-                var discard = Math.max(0,
-                                       samples.length + cur_sam.length - MAX_SAMPLES_TO_STORE_S);
-	        samples = samples.slice(discard);
-	      }
-
-
-	      samples = samples.concat(cur_sam);
-	      // We are not guaranteeed to get samples in order
-	      // we sort them....
-	      samples = samples.sort((a,b) => a.ms - b.ms);
-              process(samples);
+              if (typeof(cur_sam) == "string") {
+                console.log(cur_sam);
+              } else {
+                cur_sam = sanitize_samples(cur_sam);
+	        if (INITS_ONLY) {
+	          samples = cur_sam;
+	          INITS_ONLY = false;
+	        } else {
+                  var discard = Math.max(0,
+                                         samples.length + cur_sam.length - MAX_SAMPLES_TO_STORE_S);
+	          samples = samples.slice(discard);
+	        }
+
+
+	        samples = samples.concat(cur_sam);
+	        // We are not guaranteeed to get samples in order
+	        // we sort them....
+	        samples = samples.sort((a,b) => a.ms - b.ms);
+                process(samples);
+              }
             }
           },
           error: function(xhr, ajaxOptions, thrownError) {
@@ -1457,49 +1503,198 @@ function compute_current_TRIP(TRIP_min,TRIP_max, samples)
     return TRIP_m;
   }
 }
-// A simple computation of a moving window trace
-// computing [A + -B], where A is volume to left
-// of sample int time window t, and B is volume to right
-// t is in milliseconds
-function computeMovingWindowTrace(samples,t,v) {
 
-  var flows = samples.filter(s => s.event == 'M' && s.type == 'F');
-  var first_time = flows[0].ms;
-  var last_time = flows[flows.length - 1].ms;
-  var duration = last_time - first_time;
 
-  // Here is an idea...
-  // We define you to be in one of three states:
-  // Inspiring, expiring, or neither.
-  // Every transition between these states is logged.
-  // Having two inspirations between an expiration is
-  // weird but could happen.
-  // We record transitions.
-  // When the time series crossed a fixed threshold
-  // or zero, it causes a transition. If you are inspiring,
-  // you have to cross zero to transition to neither,
-  // and you start expiring when you cross the treshold.
 
-  // This is measured in standard liters per minute.
-  const vm = 10; // previously used 4
+  // A routine to calculate work per breath
+function PressureVolumeWork(breath, transitions, samples) {
+  // -1 for quadilateral approximation
+  if (breath.vol_i == 0) {
+    return null;
+  } else {
+    var beginTransition = transitions[breath.trans_begin_inhale];
+    var beginTime_ms = beginTransition.ms;
+    var endTransition = transitions[breath.trans_cross_zero];
+    var endTime_ms = endTransition.ms;
+    var flows = samples.filter(s => s.event == 'M' && s.type == 'F' &&
+                               s.ms >= beginTime_ms && s.ms <= endTime_ms);
+    var pressures = samples.filter(s => s.event == 'M' && s.type == 'D' &&
+                                   s.loc == 'A'&& s.ms >= beginTime_ms && s.ms <= endTime_ms);
+
+    // Note: The algorithm below relies on the fact that there is
+    // only one flow or pressure with a single ms value; and that
+    // increvementing an index necessarily incremenst the .ms value.
+
+    // Without two samples, we have no duration and can't define
+    // work.
+    if (pressures.length < 2 || flows.length < 2) return null;
+
+    var ct = Math.min(flows[0].ms,pressures[0].ms);
+    var lfp = { val : flows[0].val, ms: flows[0].ms } ; // last flow point
+    var lpp = { val : pressures[0].val, ms: pressures[0].ms }; // last pressure_point
+    var fi = increment_past(flows,flows[0].ms,0); // Index of next flow sample
+    var pi = increment_past(pressures,pressures[0].ms,0); // Index of next pressure sample
+    var w = 0; // current work
+
+    // compute flow at time ms give index and last point
+    // This is just a simple linear interpolation
+    function f(ms,cur,last) {
+      var ms0 = last.ms;
+      var ms1 = cur.ms;
+      return last.val + (cur.val - last.val)*(ms - ms0)/(ms1 - ms0);
+    }
+    function increment_past(array,ms,index) {
+      var begin = index;
+      while(index < array.length && array[index].ms <= ms)
+        index++;
+      if (index == begin) debugger;
+      if (index >= array.length)
+        return null;
+      else
+        return index;
+    }
 
-  // We will model this as a list of transitions.
-  // A breath is any number of inspirations followed by
-  // any number of expirations. (I+)(E+)
+    // A fundamental invariant:
+    // pressures[pi].ms > lpp.ms
+    // flows[pi].ms > lfp.ms
+    while ((fi + pi) < (flows.length +  pressures.length)) {
+      // Invariant always increment fi or pi
+      // fi and pi point to unprocessed value
+      console.assert(pressures[pi].ms > lpp.ms);
+      console.assert(flows[fi].ms > lfp.ms);
+      var ms;
+      if (pressures[pi].ms <= flows[fi].ms) { // process pressure
+        ms = pressures[pi].ms;
+        pi = increment_past(pressures,ms,pi);
+        if (flows[fi].ms <= ms) {
+          fi = increment_past(flows,ms,fi);
+        }
+      } else {
+        ms = flows[fi].ms;
+        fi = increment_past(flows,ms,fi);
+        if (pressures[pi].ms <= ms) {
+          pi = increment_past(pressures,ms,pi);
+        }
+      }
+      if ((fi === null) || (pi === null))
+        break;
+      var dur_s = (ms - ct) / 1000;
+      console.assert(pressures[pi].ms > lpp.ms);
+      console.assert(flows[fi].ms > lfp.ms);
+      var nf = f(ms,flows[fi],lfp);
+      var np = f(ms,pressures[pi],lpp);
+      var f1 = (lfp.val + nf)/2;
+      var p1 = (lpp.val + np)/2;
+      // convert 10ths of cm H2O to pascals..
+      var p1_pa = (p1 * 98.0665) / 10;
+
+      // convert flows in lpm to cubic meters per seconds
+      var f1_m_cubed_per_s = f1 / (1000 * 1000 * 60);
+
+      // work is now in Joules!
+      w += dur_s * p1_pa * f1_m_cubed_per_s;
+      lfp = { val : f1, ms: ms };
+      lpp = { val : p1, ms: ms };
+      ct = ms;
+    }
+    return w;
+  }
+}
+
+// Let's first set up a perfectly square 1-second
+function generate_synthetic_trace() {
+  const SAMPLES_PER_PHASE = 1000;
+  const SAMPLES_MS_PER_SAMPLE = 1;
+  var trace = [];
+  var cur = 0;
+  // p is a probability of occuring.
+  function push_samples(start,num,d,f,pd,pf) {
+    for(var i = start; i < start+num; i++) {
+      if (Math.random() < pd) {
+        trace.push(
+          {
+            event: "M",
+            loc: "A",
+            ms: i,
+            num: 0,
+            type: "D",
+            val: d
+          });
+      }
+      if (Math.random() < pf) {
+        trace.push(
+          {
+            event: "M",
+            loc: "A",
+            ms: i,
+            num: 0,
+            type: "F",
+            val: f
+          });
+      }
+    }
+  }
+  const P1 = 1/2;
+  const P2 = 1/2;
+  push_samples(SAMPLES_PER_PHASE,SAMPLES_PER_PHASE,200,50000,P1,P2);
+  push_samples(0,SAMPLES_PER_PHASE,-200,-50000,P1,P2);
+  push_samples(SAMPLES_PER_PHASE,SAMPLES_PER_PHASE,200,50000,P1,P2);
+  push_samples(SAMPLES_PER_PHASE*2,SAMPLES_PER_PHASE,-200,-50000,P1,P2);
+  push_samples(SAMPLES_PER_PHASE*3,SAMPLES_PER_PHASE,200,50000,P1,P2);
+  return trace;
+}
+
+function nearp(x,y,d) {
+  return Math.abs(x - y) <= d;
+}
+
+function testWorkSynthetic(){ // breaths give us inspiration transition points
+  var samples = generate_synthetic_trace();
+
+  const JOULES_IN_BREATH = 1 * 1961.33 * 50000 / (60e+6);
 
+  var flows = samples.filter(s => s.event == 'M' && s.type == 'F');
+    var first_time = flows[0].ms;
+    var last_time = flows[flows.length - 1].ms;
+    var duration = last_time - first_time;
+    console.log(flows);
+
+
+  const vm = 10;
+  // There is a problem here that this does not create a transition at the beginning.
   var transitions = compute_transitions(vm,flows);
+    var breaths = compute_breaths_based_without_negative_flow(transitions,flows);
+    console.log(breaths);
+    for(i = 0; i<breaths.length; i++) {
+      var w = PressureVolumeWork(breaths[i], transitions, samples);
+      console.assert((w == null) || (nearp(w,JOULES_IN_BREATH),0.1));
+      console.log("final (Joules) = ",w);
+    }
+  return true;
+}
+
+
+  function testWork(samples){ // breaths give us inspiration transition points
+    var flows = samples.filter(s => s.event == 'M' && s.type == 'F');
+    var first_time = flows[0].ms;
+    var last_time = flows[flows.length - 1].ms;
+    var duration = last_time - first_time;
+    console.log(flows);
+
+    const vm = 10;
+    var transitions = compute_transitions(vm,flows);
+    var breaths = compute_breaths_based_without_negative_flow(transitions,flows);
+    console.log(breaths);
+    for(i = 0; i<breaths.length; i++) {
+      var w = PressureVolumeWork(breaths[i], transitions, samples);
+      console.log(w);
+    }
+   }
+
 
-  // Now that we have transitions, we can apply a
-  // diferrent algorithm to try to define "breaths".
-  // Because a breath is defined as an inspiration
-  // and then an expiration, we will define a breath
-  // as from the first inspiration, until there has
-  // been one expiration, until the next inspiration.
-  var breaths = [];
-  var expiring = false;
 
   // This should be in liters...
-  function integrateSamples(a,z) {
+  function integrateSamples(a,z,flows) {
     // -1 for quadilateral approximation
     var vol = 0;
     for(var j = a; j < z-1; j++) {
@@ -1520,16 +1715,34 @@ function computeMovingWindowTrace(samples,t,v) {
     return vol/(60*1000);
   }
 
-  function compute_breaths_based_on_exhalations(transitions) {
+  // This is based only on inhalations, and
+  // is therefore functional when there is a check valve
+  // in place. Such a system will rarely
+  // have negative flows, and we must mark
+  // the beginning of a breath from a transition to a "1"
+  // state from any other state.
+  // This algorithm is simple: A breath begins on a trasition
+  // to 1 from a not 1 state. This algorithm is susceptible
+  // to "stutter" near the boundary point, but if necessary
+  // a digital filter would sove that; we have not yet found
+  // that level of sophistication needed.
+  // We still want to track zeros, but now must strack them
+  // as a falling signal.
+
+  function compute_breaths_based_without_negative_flow(transitions,flows) {
     var beg = 0;
     var zero = 0;
     var last = 0;
     var voli = 0;
     var vole = 0;
 
+    var breaths = [];
+    var expiring = true;
+
     for(var i = 0; i < transitions.length; i++) {
       // We're looking for the end of the inhalation here!!
-      if (((i -1) >= 0) && transitions[i-1].state == 1 && (transitions[i].state == 0 || transitions[i].state == -1 )) {
+      if (((i -1) >= 0) && transitions[i-1].state == 1 &&
+          (transitions[i].state == 0 || transitions[i].state == -1 )) {
         zero = i;
       }
       if (expiring && transitions[i].state == 1) {
@@ -1542,45 +1755,74 @@ function computeMovingWindowTrace(samples,t,v) {
                        trans_end_exhale: i,
 		     }
 		    );
+        var w = PressureVolumeWork(breaths[breaths.length-1], transitions, samples);
+        breaths[breaths.length-1].work = w;
         beg = i;
         expiring = false;
-        vole = integrateSamples(last,transitions[i].sample);
+        vole = integrateSamples(last,transitions[i].sample,flows);
+
         last = transitions[i].sample;
       }
-      if (!expiring && transitions[i].state == -1) {
+      if (!expiring && ((transitions[i].state == -1) || (transitions[i].state == 0)))  {
         expiring = true;
-        voli = integrateSamples(last,transitions[i].sample);
+        voli = integrateSamples(last,transitions[i].sample,flows);
         last = transitions[i].sample;
       }
     }
+    return breaths;
   }
-  // This is based only on inhalations, and
-  // is therefore functional when there is a check valve
-  // in place. Such a system will rarely
-  // have negative flows, and we must mark
-  // the beginning of a breath from a transition to a "1"
-  // state from any other state.
-  // This algorithm is simple: A breath begins on a trasition
-  // to 1 from a not 1 state. This algorithm is susceptible
-  // to "stutter" near the boundary point, but if necessary
-  // a digital filter would sove that; we have not yet found
-  // that level of sophistication needed.
-  // We still want to track zeros, but now must strack them
-  // as a falling signal.
-  function compute_breaths_based_without_negative_flow(transitions) {
+
+// A simple computation of a moving window trace
+// computing [A + -B], where A is volume to left
+// of sample int time window t, and B is volume to right
+// t is in milliseconds
+function computeMovingWindowTrace(samples,t,v) {
+
+  var flows = samples.filter(s => s.event == 'M' && s.type == 'F');
+  var first_time = flows[0].ms;
+  var last_time = flows[flows.length - 1].ms;
+  var duration = last_time - first_time;
+
+  // Here is an idea...
+  // We define you to be in one of three states:
+  // Inspiring, expiring, or neither.
+  // Every transition between these states is logged.
+  // Having two inspirations between an expiration is
+  // weird but could happen.
+  // We record transitions.
+  // When the time series crossed a fixed threshold
+  // or zero, it causes a transition. If you are inspiring,
+  // you have to cross zero to transition to neither,
+  // and you start expiring when you cross the treshold.
+
+  // This is measured in standard liters per minute.
+  const vm = 10; // previously used 4
+
+  // We will model this as a list of transitions.
+  // A breath is any number of inspirations followed by
+  // any number of expirations. (I+)(E+)
+
+  var transitions = compute_transitions(vm,flows);
+
+  // Now that we have transitions, we can apply a
+  // diferrent algorithm to try to define "breaths".
+  // Because a breath is defined as an inspiration
+  // and then an expiration, we will define a breath
+  // as from the first inspiration, until there has
+  // been one expiration, until the next inspiration.
+  var breaths = [];
+  var expiring = false;
+
+  function compute_breaths_based_on_exhalations(transitions) {
     var beg = 0;
     var zero = 0;
     var last = 0;
     var voli = 0;
     var vole = 0;
 
-    var breaths = [];
-    var expiring = true;
-
     for(var i = 0; i < transitions.length; i++) {
       // We're looking for the end of the inhalation here!!
-      if (((i -1) >= 0) && transitions[i-1].state == 1 &&
-          (transitions[i].state == 0 || transitions[i].state == -1 )) {
+      if (((i -1) >= 0) && transitions[i-1].state == 1 && (transitions[i].state == 0 || transitions[i].state == -1 )) {
         zero = i;
       }
       if (expiring && transitions[i].state == 1) {
@@ -1593,22 +1835,22 @@ function computeMovingWindowTrace(samples,t,v) {
                        trans_end_exhale: i,
 		     }
 		    );
+        var w = PressureVolumeWork(breaths[0], transitions, samples);
+        breaths[0].work = w;
         beg = i;
         expiring = false;
-        vole = integrateSamples(last,transitions[i].sample);
-
+        vole = integrateSamples(last,transitions[i].sample,flows);
         last = transitions[i].sample;
       }
-      if (!expiring && ((transitions[i].state == -1) || (transitions[i].state == 0)))  {
+      if (!expiring && transitions[i].state == -1) {
         expiring = true;
-        voli = integrateSamples(last,transitions[i].sample);
+        voli = integrateSamples(last,transitions[i].sample,flows);
         last = transitions[i].sample;
       }
     }
-    return breaths;
   }
 
-  breaths = compute_breaths_based_without_negative_flow(transitions);
+  breaths = compute_breaths_based_without_negative_flow(transitions,flows);
 
   return [transitions,breaths];
 }