Source code for jii_multispeq_protocols.protocols.calibrations.relative_chlorophyll_spad_calibration

"""
Relative Chlorophyll (SPAD) Calibration
=======================================

Follow the instructions prompted by the protocol. Make sure the panels of the calibration cards are properly clamped.

.. warning:: This calibration method requires a set of calibration cards

ID: 1890
"""

import numpy as np
from scipy import stats
from jii_multispeq.analysis import GetProtocolByLabel
import warnings

_protocol = [
  {
    "_protocol_set_": [
      {
        "label": "gain",
        "alert": "Insert SPAD calibration panel 9, and press 'ok' to continue.",
        "auto_blank": [
          [
            2,
            2,
            3,
            100,
            10000
          ],
          [
            6,
            6,
            1,
            100,
            10000
          ],
          [
            3,
            3,
            3,
            100,
            10000
          ]
        ]
      },
      {
        "label": "spad",
        "prompt": "Insert SPAD calibration panel 2 ***AND*** enter the corresponding SPAD value for the panel.",
        "spad": [
          [
            2,
            3,
            6
          ],
          [
            -1
          ]
        ],
        "protocol_repeats": 1
      },
      {
        "label": "spad",
        "prompt": "Insert SPAD calibration panel 3 ***AND*** enter the corresponding SPAD value for the panel.",
        "spad": [
          [
            2,
            3,
            6
          ],
          [
            -1
          ]
        ],
        "protocol_repeats": 1
      },
      {
        "label": "spad",
        "prompt": "Insert SPAD calibration panel 4 ***AND*** enter the corresponding SPAD value for the panel.",
        "spad": [
          [
            2,
            3,
            6
          ],
          [
            -1
          ]
        ],
        "protocol_repeats": 1
      },
      {
        "label": "spad",
        "prompt": "Insert SPAD calibration panel 6 ***AND*** enter the corresponding SPAD value for the panel.",
        "spad": [
          [
            2,
            3,
            6
          ],
          [
            -1
          ]
        ],
        "protocol_repeats": 1
      },
      {
        "label": "spad",
        "prompt": "Insert SPAD calibration panel 7 ***AND*** enter the corresponding SPAD value for the panel.",
        "spad": [
          [
            2,
            3,
            6
          ],
          [
            -1
          ]
        ],
        "protocol_repeats": 1
      },
      {
        "label": "spad",
        "prompt": "Insert SPAD calibration panel 8 ***AND*** enter the corresponding SPAD value for the panel.",
        "spad": [
          [
            2,
            3,
            6
          ],
          [
            -1
          ]
        ],
        "protocol_repeats": 1
      },
      {
        "label": "spad",
        "prompt": "Insert SPAD calibration panel 10 ***AND*** enter the corresponding SPAD value for the panel.",
        "spad": [
          [
            2,
            3,
            6
          ],
          [
            -1
          ]
        ],
        "protocol_repeats": 1
      },
      {
        "label": "spad",
        "prompt": "Insert SPAD calibration panel 11 ***AND*** enter the corresponding SPAD value for the panel.",
        "spad": [
          [
            2,
            3,
            6
          ],
          [
            -1
          ]
        ],
        "protocol_repeats": 1
      },
      {
        "label": "spad",
        "prompt": "Insert SPAD calibration panel 12 ***AND*** enter the corresponding SPAD value for the panel.",
        "spad": [
          [
            2,
            3,
            6
          ],
          [
            -1
          ]
        ],
        "protocol_repeats": 1
      }
    ]
  }
]

[docs] def _analyze( _data ): """ * Macro for data evaluation on PhotosynQ.org * by: David M. Kramer * created: 2017-06-21 @ 10:36:29 """ # light_1 = 530 nm top # light_2 = 650 nm top # light_3 = 605 nm top # light 4 = blue top # light_5 = 940 nm top # light_9 = 940 nm bottom # light_7 = 650 bottom # light_8 = 850 nm bottom # light 9 = 730 nm bottom # light 10 = 880 nm bottom ## Define the output object here output = {} s=[7.8, 16.7, 34.3, 26.5, 39.9, 44, 24, 40, 51] output["calibrationValuesStock"] = repr(s) ## Check if the key time exists in json if "time" in _data: ## Add key time and value to output output["time"] = _data["time"] t = GetProtocolByLabel( "spad", _data, True ) ab = GetProtocolByLabel( "gain", _data, True ) for i in range(len(t)): if (t[i]["message"][2] != ""): s[i] = int(t[i].message[2]) # TODO: check if it is int or float output["calibrationValues"] = repr(s) v655 = [] v950 = [] r655 = [] r950 = [] for i in range(len(t)): ## cycle through the set of measurements v655.append(t[i]["absorbance"][0][0]) ## v is the value of the measurements r655.append(t[i]["absorbance"][0][1]) ## r is the reference v950.append(t[i]["absorbance"][1][0]) ## v is the value of the measurements r950.append(t[i]["absorbance"][1][1]) ## r is the reference r2 = [] maxR2 = 0 bestOffset = -2000 spadSlope = 0 spadYInt = 0 for offset in np.arange(-200, 200, 10): da = [] for i in range(len(t)): ## cycle through the set of measurements DA655 = np.round(r655[i] - offset) - np.round(v655[i] - offset) DA950 = np.round(r950[i]) - np.round(v950[i]) da.append(DA655 - DA950) slope, intercept, r_value, p_value, std_err = stats.linregress(da, s) r2_value = r_value**2 r2.append(r2_value) if r2_value > maxR2: maxR2 = r2_value bestOffset = offset spadSlope = slope spadYInt = intercept output["bestOffset"] = bestOffset output["maxR2"] = np.round(maxR2, 5) output["spadSlope"] = np.round(spadSlope, 4) output["spadYInt"] = np.round(spadYInt, 4) spad=[] for i in range(len(t)): ## cycle through the set of measurements DA655 = np.log10(r655[i]-bestOffset) - np.log10(v655[i]-bestOffset) DA950 = np.log10(r950[i]) - np.log10(v950[i]) dax = DA655-DA950 spad.append(np.round(spadYInt + spadSlope*dax, 2)) output["spad"] = repr(spad) output["toDevice"] = "" output["toDevice"] += "set_spad_offset+%s+" % np.round(bestOffset, 4) output["toDevice"] += "set_spad_scale+%s+" % np.round(spadSlope, 4) output["toDevice"] += "set_spad_yint+%s+" % np.round(spadYInt, 4) if maxR2 < .97: output["test"] = "R2 value low. Calibration card may be out of date" warnings.warn( output["test"] ) else: output["test"] = "OK" return output
_example = { "time": 1553786924729, "device_name": "MultispeQ", "device_version": "2", "device_id": "41:00:08:6b", "device_battery": 100, "device_firmware": 2.011, "sample": [ [ { "time": 1553786924729, "protocol_id": 1, "set": [ { "time": 1553786924739, "message": [ "prompt", "Insert panel 9", "" ], "label": "gain", "auto_blank": [ [ 2, 2, 3, 100, -461, 9286 ], [ 6, 6, 1, 100, -303, 9338 ], [ 3, 3, 3, 100, -324, 9447 ] ], "data_raw": [ ] }, { "time": 1553786933707, "message": [ "prompt", "Insert spad sample", "" ], "label": "spad", "absorbance": [ [ 27992, 9286, -90, -0.47641, 2, 3, 655 ], [ 27837, 9338, 20, -0.474988, 6, 1, 950 ] ], "spad": [ 7.863, 36.467, -90, 7.915 ], "data_raw": [ ] }, { "time": 1553786941484, "message": [ "prompt", "Insert spad sample", "" ], "label": "spad", "absorbance": [ [ 14921, 9286, -90, -0.204392, 2, 3, 655 ], [ 25923, 9338, 20, -0.444027, 6, 1, 950 ] ], "spad": [ 16.653, 36.467, -90, 7.915 ], "data_raw": [ ] }, { "time": 1553786946755, "message": [ "prompt", "Insert spad sample", "" ], "label": "spad", "absorbance": [ [ 2081, 9286, -90, 0.635358, 2, 3, 655 ], [ 11169, 9338, 20, -0.077913, 6, 1, 950 ] ], "spad": [ 33.925, 36.467, -90, 7.915 ], "data_raw": [ ] }, { "time": 1553786949693, "message": [ "prompt", "Insert spad sample", "" ], "label": "spad", "absorbance": [ [ 3541, 9286, -90, 0.411991, 2, 3, 655 ], [ 11675, 9338, 20, -0.09719, 6, 1, 950 ] ], "spad": [ 26.483, 36.467, -90, 7.915 ], "data_raw": [ ] }, { "time": 1553786954833, "message": [ "prompt", "Insert spad sample", "" ], "label": "spad", "absorbance": [ [ 722, 9286, -90, 1.062462, 2, 3, 655 ], [ 6145, 9338, 20, 0.182217, 6, 1, 950 ] ], "spad": [ 40.014, 36.467, -90, 7.915 ], "data_raw": [ ] }, { "time": 1553786958252, "message": [ "prompt", "Insert spad sample", "" ], "label": "spad", "absorbance": [ [ 467, 9286, -90, 1.226162, 2, 3, 655 ], [ 5311, 9338, 20, 0.245785, 6, 1, 950 ] ], "spad": [ 43.666, 36.467, -90, 7.915 ], "data_raw": [ ] }, { "time": 1553786961600, "message": [ "prompt", "Insert spad sample", "" ], "label": "spad", "absorbance": [ [ 3130, 9286, -90, 0.464162, 2, 3, 655 ], [ 8767, 9338, 20, 0.027464, 6, 1, 950 ] ], "spad": [ 23.84, 36.467, -90, 7.915 ], "data_raw": [ ] }, { "time": 1553786969037, "message": [ "prompt", "Insert spad sample", "" ], "label": "spad", "absorbance": [ [ 416, 9286, -90, 1.267867, 2, 3, 655 ], [ 3779, 9338, 20, 0.39425, 6, 1, 950 ] ], "spad": [ 39.773, 36.467, -90, 7.915 ], "data_raw": [ ] }, { "time": 1553786972223, "message": [ "prompt", "Insert spad sample", "" ], "label": "spad", "absorbance": [ [ 283, 9286, -90, 1.400309, 2, 3, 655 ], [ 5821, 9338, 20, 0.20582, 6, 1, 950 ] ], "spad": [ 51.474, 36.467, -90, 7.915 ], "data_raw": [ ] } ], "data_raw": [ ] } ] ], "app_os": "macOS 16.7.0", "app_name": "PhotosynQ", "app_version": "1.2.1", "app_device": "x64", "location": False, "time_offset": "America/Detroit" }