second try


Saves the 'blackbody' reflection at each wavelength
/*

This macro does a few things:
1) it separates out each wavelength based on the # of pulses per wavelength
2) it then subtracts the high 
2) it addresses LED heating by ignoring the first 2/3 of the pulses to reduce standard deviation caused by heating
3) it then tries to flatten the remining 1/3 of pulses
4) then it chooses the median, calculates standard deviation, # of bits for those pulses. 
5a) then saves the raw median to the device for the shiney (0 - 9) or black (10 - 19) values in the calibration version
5b) then it calculates the median, stdev and bits in the normal measurement version
6) note that bits_actual is the bits accounting for the actual range (max reflectance - min reflectance) as compared to bits which assumes the full 16 bit range.  bits_actual is a more accurate representation of the quality of the overall setup (hardware + case + optics)

*/

var data = json.data_raw;
var output = {};



////////////////**********************///////////////////
// Determine if this is a calibration measurement or not.  Calibration = 1 is for calibration shiney (userdef[0] - userdef[9]
// calibration = 2 is for calibration black (userdef[10] - userdef[19] )
var calibration = 0;
if (typeof json.recall == 'undefined') {
  calibration = 1;
  output["toDevice"] = "set_user_defined+";
}
else if (typeof json.recall["userdef[1]"] == 'undefined') {
  calibration = 2;
  output["toDevice"] = "set_user_defined+";
}
////////////////**********************///////////////////



////////////////**********************///////////////////
// Set the conditions of the measurement - which lights, # pulses, # of pulses to ignore due to heating. etc.
var wavelengths = [370, 395, 420, 530, 605, 650, 730, 850, 880, 940];
var pulses = 60;
var partPulses = (2/3);
var raw_array = [];
var raw_array_flat = [];
var trans_array = [];
var spad_array = [];
////////////////**********************///////////////////



////////////////**********************///////////////////
if (calibration === 0) {
  // get calibration information (min and max reflectance) from device
  var max_reflectance_High = [json.recall["userdef[0]"],json.recall["userdef[1]"],json.recall["userdef[2]"],json.recall["userdef[3]"],json.recall["userdef[4]"],json.recall["userdef[5]"],json.recall["userdef[6]"],json.recall["userdef[7]"],json.recall["userdef[8]"],json.recall["userdef[9]"]];
  var max_reflectance_Low = [json.recall["userdef[10]"],json.recall["userdef[11]"],json.recall["userdef[12]"],json.recall["userdef[13]"],json.recall["userdef[14]"],json.recall["userdef[15]"],json.recall["userdef[16]"],json.recall["userdef[17]"],json.recall["userdef[18]"],json.recall["userdef[19]"]];
  var max_reflectance = [];
  for (var j = 0; j < 10; j++) {
    max_reflectance[j] = max_reflectance_High[j] - max_reflectance_Low[j];
  }
}
////////////////**********************///////////////////



////////////////**********************///////////////////
// get the sample values from the raw trace, put them into an array
var sample_values_raw = [];
for (var j = 0; j < wavelengths.length; j++) {
  sample_values_raw[j] = json.data_raw.slice(pulses*j,pulses*(j+1));
}
// TEST
// output["sample_values_raw"] = sample_values_raw[0]
// TEST //
////////////////**********************///////////////////



////////////////**********************///////////////////
// Then, we choose the last few pulses to use to avoid the heating effect
for (var j = 0; j < wavelengths.length; j++) {
  sample_values_raw[j] = sample_values_raw[j].slice(pulses*partPulses, pulses);
}
// TEST
// output["sample_values_raw"] = sample_values_raw[0];
// TEST //
////////////////**********************///////////////////



////////////////**********************///////////////////
// And finally, we're going to straighten out the pulses to reduce our standard deviation using a linear regression and correction
// first we need a time array to plug into the regression formula (the x of y = mx + b)
var timeArray = [];
for (var z = 0; z < pulses - pulses*partPulses; z++) {
  timeArray[z] = z;
}
// Then we need to create the new variable to store the flattened values
var sample_values_flat = [];
for (var j = 0; j < wavelengths.length; j++) {
  var tmp_array = [];
  sample_values_flat[j] = tmp_array;
}
// now we can do the straightening via regression + correction
for (var j = 0; j < wavelengths.length; j++) {
  var reg = MathLINREG(timeArray,sample_values_raw[j]);
  // what is the center point of rotation for the line (halfway through the array) - that's the value from which we will adjust other values
  var centerPoint = reg.m*(pulses - pulses*partPulses)/2 + reg.b;
  for (var i = 0; i < sample_values_raw[j].length; i++ ) { 
    var adjustment = centerPoint - (reg.m*timeArray[i] + reg.b);
    sample_values_flat[j][i] = sample_values_raw[j][i] + adjustment;
// TEST //    output["adjustment_"+wavelengths[j]+"_"+i] = adjustment;
  }
}



////////////////**********************///////////////////
// now convert the data into a percentage (0 - 100) based on the min and max reflectance saved in the device.  (if it's a calibration, don't do that!)
var sample_values_perc = [];
for (var j = 0; j < wavelengths.length; j++) {
  var tmp_array = [];
  sample_values_perc[j] = tmp_array;
}
for (var j = 0; j < wavelengths.length; j++) {
  for (var i = 0; i < sample_values_flat[j].length; i++) { 
    if (calibration > 0) {
      sample_values_perc[j][i] = sample_values_flat[j][i];
    }
    else {
    sample_values_perc[j][i] = 100*( sample_values_flat[j][i] - max_reflectance_Low[j] ) / ( max_reflectance_High[j] - max_reflectance_Low[j] );
    }
  }
}
////////////////**********************///////////////////



////////////////**********************///////////////////
// TEST // Compare flattened, unflattened, and percentage values
/*
output["sample_values_flat"] = "";
output["sample_values_raw"] = "";
output["sample_values_perc"] = "";
for (var i = 0; i < sample_values_flat[0].length; i ++) {
 output["sample_values_flat"] += MathROUND(sample_values_flat[0][i],2) + ",";
 output["sample_values_raw"] += MathROUND(sample_values_raw[0][i],2) + ",";
 output["sample_values_perc"] += MathROUND(sample_values_perc[0][i],10) + ",";
}
*/
////////////////**********************///////////////////



////////////////**********************///////////////////
// Now we can pull the median, standard deviation, spad, and bits from these adjusted + corrected values
// Note - to calculate bits, we need to convert the median value back up to a 16 bit value to calculate bits, so there's some math to convert it back to a raw value there
var median = [];
var median_raw = [];
var spad = [];
var absorbance = [];
var stdev = [];
var stdev_raw = [];
var three_stdev = [];
var three_stdev_raw = [];
var bits = [];
var bits_actual = [];
for (var j = 0; j < wavelengths.length; j++) {
  median[j] = MathMEDIAN(sample_values_perc[j]);
  median_raw[j] = MathMEDIAN(sample_values_flat[j]);
  absorbance[j] = -1 * Math.log( median[j]/100);
  stdev[j] = MathSTDEV(sample_values_perc[j]);
  stdev_raw[j] = MathSTDEV(sample_values_flat[j]);
  three_stdev[j] = 3*stdev[j];
  three_stdev_raw[j] = 3*stdev_raw[j];
  bits[j] = ( 15 - MathLOG(stdev_raw[j]*2) / MathLOG(2) );
  if (calibration === 0) {
    bits_actual[j] = ( 15 - MathLOG((65536/max_reflectance[j])*stdev_raw[j]*2) / MathLOG(2) );
  }
}
for (var j = 0; j < wavelengths.length; j++) {
  spad[j] = 100 * Math.log( ( median[9]) / (median[j] ) );  // because we've already normalized values from 0 (black) to 100 (shiney), the max value is always 100 so just divide by 100
}
////////////////**********************///////////////////



////////////////**********************///////////////////
// now we need to pull out the values specific

////////////////**********************///////////////////
// TEST //
// Output a single set of values for a light
/*
var test_light = 2;
output["raw_range_"+test_light] = max_reflectance[test_light];
output["median_"+test_light] = median[test_light];
output["median_raw_"+test_light] = median_raw[test_light];
output["stdev_"+test_light] = stdev[test_light];
output["stdev_raw_"+test_light] = stdev_raw[test_light];
output["bits_"+test_light] = bits[test_light];
output["bits_actual_"+test_light] = bits_actual[test_light];
*/
////////////////**********************///////////////////



////////////////**********************///////////////////
// Now we output the values users should see both as individual numbers and as arrays
if (calibration === 0) {
  for (var j = 0; j < wavelengths.length; j++) {
    output["median_"+wavelengths[j]] = MathROUND(median[j],3);  
  }
  for (var j = 0; j < wavelengths.length; j++) {
    output["three_stdev_"+wavelengths[j]] = MathROUND(three_stdev[j],3);  
  }
  for (var j = 0; j < wavelengths.length; j++) {
    output["bits_actual_"+wavelengths[j]] = MathROUND(bits_actual[j],1);  
  }
  for (var j = 0; j < wavelengths.length; j++) {
    output["absorbance_"+wavelengths[j]] = MathROUND(absorbance[j],4);  
  }
  for (var j = 0; j < wavelengths.length; j++) {
    output["spad_"+wavelengths[j]] = MathROUND(spad[j],3);  
  }
}
else if (calibration == 1) {
  for (var j = 0; j < wavelengths.length; j++) {
    output["toDevice"] += j + "+" + MathROUND(median_raw[j],2) + "+";  
  }
  output["toDevice"] += "-1+";  
}
else if (calibration == 2) {
  for (var j = 0; j < wavelengths.length; j++) {
    output["toDevice"] += j + 10 + "+" + MathROUND(median_raw[j],2) + "+";  
  }
  output["toDevice"] += "-1+";  
}
for (var j = 0; j < wavelengths.length; j++) {
  output["median_raw_"+wavelengths[j]] = MathROUND(median_raw[j],2);  
}
for (var j = 0; j < wavelengths.length; j++) {
  output["stdev_raw_"+wavelengths[j]] = MathROUND(stdev_raw[j],2);  
}
for (var j = 0; j < wavelengths.length; j++) {
  output["bits_"+wavelengths[j]] = MathROUND(bits[j],1);  
}

if (calibration == 0) {
  output["median"] = median;
  output["stdev"] = stdev;
  output["three_stdev"] = three_stdev;
  output["absorbance"] = absorbance;
  output["spad"] = spad;
  output["bits_actual"] = bits_actual;
  output["reflectance_high"] = max_reflectance_High;
  output["reflectance_low"] = max_reflectance_Low;
}
output["median_raw"] = median_raw;
output["stdev_raw"] = stdev_raw;
output["bits"] = bits;
output["wavelengths"] = wavelengths;
////////////////**********************///////////////////



return output;
{
  "time_offset": 240,
  "time": 1507063803012,
  "device_name": "MultispeQ",
  "device_version": "1",
  "device_id": "03:22:01:96",
  "device_battery": 14,
  "device_firmware": 1.17,
  "sample": [
    {
      "time": 1507063803032,
      "protocol_id": 1,
      "averages": 5,
      "recall": {
        "time": 1507063807522,
        "userdef[0]": 40597
      },
      "data_raw": [
        31118,
        31108,
        31058,
        31019,
        30982,
        30943,
        30926,
        30908,
        30874,
        30857,
        30832,
        30822,
        30804,
        30788,
        30769,
        30759,
        30748,
        30739,
        30733,
        30713,
        30706,
        30700,
        30690,
        30684,
        30663,
        30666,
        30647,
        30653,
        30640,
        30630,
        30630,
        30620,
        30615,
        30610,
        30604,
        30595,
        30601,
        30602,
        30585,
        30591,
        30576,
        30576,
        30574,
        30569,
        30560,
        30564,
        30556,
        30555,
        30550,
        30544,
        30546,
        30548,
        30540,
        30537,
        30543,
        30521,
        30518,
        30518,
        30518,
        30512,
        30520,
        30514,
        30508,
        30502,
        30502,
        30500,
        30498,
        30493,
        30491,
        30490,
        30491,
        30492,
        30490,
        30479,
        30486,
        30478,
        30472,
        30467,
        30474,
        30462,
        30455,
        30458,
        30460,
        30460,
        30456,
        30446,
        30450,
        30447,
        30444,
        30450,
        30446,
        30438,
        30435,
        30435,
        30435,
        30434,
        30432,
        30431,
        30431,
        30433,
        30428,
        30418,
        30421,
        30424,
        30424,
        30423,
        30418,
        30413,
        30415,
        30409,
        30423,
        30417,
        30412,
        30412,
        30409,
        30404,
        30419,
        30408,
        30412,
        30405,
        30423,
        30416,
        30417,
        30414,
        30412,
        30408,
        30398,
        30401,
        30412,
        30404,
        30413,
        30402,
        30397,
        30401,
        30398,
        30398,
        30394,
        30395,
        30396,
        30392,
        30395,
        30394,
        30388,
        30394,
        30394,
        30390,
        30390,
        30389,
        30384,
        30388,
        30380,
        30386,
        30382,
        30382,
        30378,
        30376,
        30368,
        30370,
        30373,
        30377,
        30370,
        30373,
        30379,
        30373,
        30369,
        30362,
        30366,
        30360,
        30366,
        30358,
        30358,
        30363,
        30367,
        30362,
        30360,
        30366,
        30362,
        30364,
        30354,
        30364,
        25004,
        24976,
        24985,
        25000,
        25008,
        25011,
        25012,
        25019,
        25020,
        25029,
        25041,
        25032,
        25040,
        25047,
        25046,
        25052,
        25061,
        25064,
        25065,
        25064,
        25074,
        25074,
        25070,
        25070,
        25076,
        25069,
        25075,
        25077,
        25074,
        25073,
        25076,
        25082,
        25080,
        25080,
        25088,
        25078,
        25083,
        25082,
        25082,
        25086,
        25086,
        25088,
        25091,
        25092,
        25082,
        25084,
        25093,
        25090,
        25088,
        25092,
        25098,
        25098,
        25096,
        25092,
        25096,
        25098,
        25094,
        25094,
        25095,
        25098,
        23138,
        23133,
        23139,
        23142,
        23140,
        23142,
        23140,
        23148,
        23152,
        23147,
        23144,
        23149,
        23143,
        23151,
        23148,
        23150,
        23154,
        23165,
        23154,
        23159,
        23165,
        23164,
        23162,
        23155,
        23164,
        23167,
        23161,
        23164,
        23166,
        23169,
        23174,
        23165,
        23165,
        23167,
        23176,
        23174,
        23169,
        23174,
        23167,
        23170,
        23167,
        23166,
        23169,
        23169,
        23167,
        23175,
        23167,
        23170,
        23175,
        23176,
        23176,
        23174,
        23169,
        23180,
        23174,
        23173,
        23171,
        23174,
        23180,
        23176,
        18449,
        18410,
        18416,
        18418,
        18426,
        18430,
        18436,
        18437,
        18438,
        18441,
        18444,
        18453,
        18453,
        18456,
        18462,
        18465,
        18459,
        18462,
        18466,
        18470,
        18473,
        18468,
        18472,
        18475,
        18482,
        18477,
        18481,
        18481,
        18477,
        18474,
        18483,
        18473,
        18479,
        18479,
        18478,
        18484,
        18482,
        18474,
        18484,
        18487,
        18481,
        18482,
        18487,
        18492,
        18488,
        18488,
        18489,
        18488,
        18488,
        18487,
        18489,
        18492,
        18496,
        18487,
        18494,
        18491,
        18488,
        18490,
        18489,
        18489,
        18117,
        18115,
        18113,
        18114,
        18117,
        18117,
        18125,
        18123,
        18127,
        18126,
        18126,
        18126,
        18121,
        18127,
        18126,
        18126,
        18135,
        18129,
        18140,
        18134,
        18134,
        18143,
        18137,
        18136,
        18135,
        18136,
        18143,
        18138,
        18141,
        18140,
        18148,
        18145,
        18147,
        18139,
        18142,
        18147,
        18143,
        18140,
        18138,
        18142,
        18148,
        18147,
        18149,
        18147,
        18145,
        18147,
        18145,
        18150,
        18135,
        18142,
        18144,
        18149,
        18144,
        18147,
        18139,
        18140,
        18147,
        18147,
        18157,
        18144,
        20225,
        18570,
        18528,
        18516,
        18516,
        18514,
        18514,
        18511,
        18524,
        18517,
        18512,
        18516,
        18518,
        18526,
        18529,
        18532,
        18531,
        18532,
        18543,
        18537,
        18534,
        18541,
        18546,
        18545,
        18538,
        18548,
        18547,
        18539,
        18540,
        18546,
        18548,
        18543,
        18548,
        18557,
        18548,
        18555,
        18548,
        18548,
        18555,
        18562,
        18560,
        18550,
        18563,
        18568,
        18574,
        18571,
        18568,
        18569,
        18572,
        18583,
        18568,
        18578,
        18583,
        18572,
        18570,
        18577,
        18574,
        18582,
        18585,
        18581,
        26466,
        26506,
        26507,
        26511,
        26518,
        26508,
        26513,
        26519,
        26514,
        26510,
        26515,
        26506,
        26524,
        26519,
        26518,
        26522,
        26534,
        26534,
        26522,
        26534,
        26532,
        26522,
        26510,
        26519,
        26518,
        26516,
        26522,
        26516,
        26518,
        26520,
        26524,
        26523,
        26525,
        26521,
        26527,
        26521,
        26523,
        26520,
        26520,
        26533,
        26529,
        26532,
        26535,
        26528,
        26535,
        26521,
        26537,
        26529,
        26534,
        26532,
        26537,
        26529,
        26533,
        26533,
        26529,
        26533,
        26535,
        26534,
        26533,
        26532,
        25894,
        25907,
        25908,
        25908,
        25896,
        25909,
        25913,
        25910,
        25913,
        25920,
        25914,
        25911,
        25913,
        25911,
        25902,
        25905,
        25912,
        25902,
        25912,
        25911,
        25915,
        25914,
        25923,
        25918,
        25916,
        25914,
        25922,
        25919,
        25923,
        25921,
        25924,
        25926,
        25920,
        25918,
        25916,
        25918,
        25920,
        25913,
        25913,
        25922,
        25919,
        25913,
        25912,
        25908,
        25908,
        25914,
        25914,
        25907,
        25912,
        25910,
        25910,
        25918,
        25914,
        25915,
        25907,
        25915,
        25915,
        25914,
        25913,
        25914
      ]
    }
  ],
  "app_os": "linux",
  "app_name": "PhotosynQ",
  "app_version": "0.3.9",
  "app_device": "x86-64",
  "location": [
    "42.2310800",
    "-83.7478556"
  ],
  "ConsoleMacro": "382"
}
Default avatar
Created by

Jon S


Protocol connections:
8
Latest Update:
Oct 2017