check deoxygenation and classify with abs

This commit is contained in:
Pritimay Sarkar
2023-11-15 14:18:01 +05:30
parent 467dde9a24
commit 3c70142c15
5 changed files with 107 additions and 13 deletions

View File

@@ -77,4 +77,19 @@ object Constants {
const val BUFFER_LED_LOWER_BOUND = 21000 const val BUFFER_LED_LOWER_BOUND = 21000
const val BUFFER_LED_UPPER_BOUND = 24500 const val BUFFER_LED_UPPER_BOUND = 24500
val DEVICE_CONFIGURATION: Map<String, List<List<Double>>> = mapOf<String, List<List<Double>>>(
"HCV-000-3001" to listOf(
listOf(1.264817, -0.85965), // LED1
listOf(0.581462456, -0.58502), // LED2
listOf(0.184991, 0.184991), // LED3
listOf(1.0, 0.0) // LED4
),
"HCV-000-3002" to listOf(
listOf(1.264817, -0.85965), // LED1
listOf(0.581462456, -0.58502), // LED2
listOf(0.184991, 0.184991), // LED3
listOf(1.0, 0.0) // LED4
),
)
} }

View File

@@ -11,7 +11,7 @@ import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.google.android.datatransport.runtime.dagger.Provides import com.google.android.datatransport.runtime.dagger.Provides
import javax.inject.Singleton import javax.inject.Singleton
@Database(entities = [UserData::class, HemoCubeTestData::class, DeviceData::class], version = 5, exportSchema = false) @Database(entities = [UserData::class, HemoCubeTestData::class, DeviceData::class], version = 8, exportSchema = false)
@TypeConverters(Converters::class) @TypeConverters(Converters::class)
abstract class MyDatabase : RoomDatabase() { abstract class MyDatabase : RoomDatabase() {
abstract fun userDao(): UserDao abstract fun userDao(): UserDao

View File

@@ -36,8 +36,14 @@ data class HemoCubeTestData(
var led2Average: Double? = null, var led2Average: Double? = null,
var led3Average: Double? = null, var led3Average: Double? = null,
var led4Average: Double? = null, var led4Average: Double? = null,
var abs1: Double? = null,
var abs2: Double? = null,
var abs3: Double? = null,
var abs4: Double? = null,
var deviceRatio: Double? = null, var deviceRatio: Double? = null,
var calculatedRatio: Double? = null, var calculatedRatio: Double? = null,
var predictedDenovixRatio: Double? = null,
var coefficients: String? = "", var coefficients: String? = "",
var classificationResult: String = "" var classificationResult: String = "",
var prdClassification: String = "",
) )

View File

@@ -49,7 +49,13 @@ class HemoCubeFragment : Fragment() {
private var led2SampleForDevice = 0.0 private var led2SampleForDevice = 0.0
private var led3SampleForDevice = 0.0 private var led3SampleForDevice = 0.0
private var led4SampleForDevice = 0.0 private var led4SampleForDevice = 0.0
private var fittedAbs1 = 0.0
private var fittedAbs2 = 0.0
private var fittedAbs3 = 0.0
private var fittedAbs4 = 0.0
private var _predictedDenovixRatio = 0.0
private var validationError = false private var validationError = false
private var deviceHardwareId = ""
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?, inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
@@ -285,6 +291,7 @@ class HemoCubeFragment : Fragment() {
val slData = stringData.split(" ") val slData = stringData.split(" ")
if (slData.size > 1) { if (slData.size > 1) {
val hardwareId = slData[1].trim() val hardwareId = slData[1].trim()
deviceHardwareId = hardwareId
with(sharedPreferences.edit()) { with(sharedPreferences.edit()) {
putString(Constants.DEVICE_ID, hardwareId) putString(Constants.DEVICE_ID, hardwareId)
apply() apply()
@@ -321,8 +328,10 @@ class HemoCubeFragment : Fragment() {
} }
resultData.contains("REND") -> { resultData.contains("REND") -> {
hemoCubeViewModel.messages.postValue("Data collected \n" + hemoCubeViewModel.messages.postValue(
" Processing data") "Data collected \n" +
" Processing data"
)
val resultLines = resultData.split("\\s+(?=LB|LS)".toRegex()) val resultLines = resultData.split("\\s+(?=LB|LS)".toRegex())
var bufferIntensity = resultLines[1].split(' ')[1].trim() var bufferIntensity = resultLines[1].split(' ')[1].trim()
led1BufferForDevice = if (isUsingExistingBuffer) { led1BufferForDevice = if (isUsingExistingBuffer) {
@@ -408,14 +417,6 @@ class HemoCubeFragment : Fragment() {
val led4Average = log10(led4BufferForDevice?.div(led4SampleForDevice!!) ?: 0.0) val led4Average = log10(led4BufferForDevice?.div(led4SampleForDevice!!) ?: 0.0)
val deviceRatio = led3Average / led1Average val deviceRatio = led3Average / led1Average
if (led1Average < 0 || led2Average < 0 || led3Average < 0 || led4Average < 0) {
validationError = true
activity?.runOnUiThread {
binding.errorMessage.text = "Error: Negative Abs. Retake Blank Reading"
binding.errorMessage.visibility = View.VISIBLE
}
}
if (led1BufferForDevice < Constants.BUFFER_LED_LOWER_BOUND if (led1BufferForDevice < Constants.BUFFER_LED_LOWER_BOUND
|| led2BufferForDevice < Constants.BUFFER_LED_LOWER_BOUND || led2BufferForDevice < Constants.BUFFER_LED_LOWER_BOUND
|| led3BufferForDevice < Constants.BUFFER_LED_LOWER_BOUND || led3BufferForDevice < Constants.BUFFER_LED_LOWER_BOUND
@@ -435,7 +436,42 @@ class HemoCubeFragment : Fragment() {
) { ) {
validationError = true validationError = true
activity?.runOnUiThread { activity?.runOnUiThread {
binding.errorMessage.text = "Error: Invalid Test. Improper buffer reading (high)" binding.errorMessage.text =
"Error: Invalid Test. Improper buffer reading (high)"
binding.errorMessage.visibility = View.VISIBLE
}
}
var gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(0)?.get(0)
var constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(0)?.get(1)
fittedAbs1 = gradient?.times(led1Average)?.plus(constant!!)!!
gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(1)?.get(0)
constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(1)?.get(1)
fittedAbs2 = gradient?.times(led2Average)?.plus(constant!!)!!
gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(2)?.get(0)
constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(2)?.get(1)
fittedAbs3 = gradient?.times(led3Average)?.plus(constant!!)!!
gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(3)?.get(0)
constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(3)?.get(1)
fittedAbs4 = gradient?.times(led4Average)?.plus(constant!!)!!
_predictedDenovixRatio = fittedAbs3?.div(fittedAbs1!!)!!
if (fittedAbs1!! <= fittedAbs2!!) {
validationError = true
activity?.runOnUiThread {
binding.errorMessage.text = "Error: Invalid Test. Problem with de-oxygenation"
binding.errorMessage.visibility = View.VISIBLE
}
}
if (led1Average < 0 || led2Average < 0 || led3Average < 0 || led4Average < 0) {
validationError = true
activity?.runOnUiThread {
binding.errorMessage.text = "Error: Negative Abs. Retake Blank Reading"
binding.errorMessage.visibility = View.VISIBLE binding.errorMessage.visibility = View.VISIBLE
} }
} }
@@ -455,11 +491,17 @@ class HemoCubeFragment : Fragment() {
this.led2Average = led2Average this.led2Average = led2Average
this.led3Average = led3Average this.led3Average = led3Average
this.led4Average = led4Average this.led4Average = led4Average
this.abs1 = fittedAbs1
this.abs2 = fittedAbs2
this.abs3 = fittedAbs3
this.abs4 = fittedAbs4
this.deviceRatio = deviceRatio this.deviceRatio = deviceRatio
this.calculatedRatio = calculateRatio(deviceRatio) this.calculatedRatio = calculateRatio(deviceRatio)
this.predictedDenovixRatio = _predictedDenovixRatio
this.coefficients = currentDeviceData?.coefficients?.get(0) this.coefficients = currentDeviceData?.coefficients?.get(0)
.toString() + ", " + currentDeviceData?.coefficients?.get(1).toString() .toString() + ", " + currentDeviceData?.coefficients?.get(1).toString()
this.classificationResult = findResult(calculatedRatio) this.classificationResult = findResult(calculatedRatio)
this.prdClassification = absorbanceBasedClassification(predictedDenovixRatio)
hemoCubeViewModel.messages.postValue(this.classificationResult) hemoCubeViewModel.messages.postValue(this.classificationResult)
this.resultData = deviceLog this.resultData = deviceLog
if (!isUsingExistingBuffer) { if (!isUsingExistingBuffer) {
@@ -519,6 +561,31 @@ class HemoCubeFragment : Fragment() {
return "INVALID" return "INVALID"
} }
private fun absorbanceBasedClassification(predictedDenovixRatio: Double?): String {
try {
hemoCubeViewModel.messages.postValue("result classification")
if (predictedDenovixRatio != null) {
if (predictedDenovixRatio in 0.0..0.16)
return "Normal"
if (predictedDenovixRatio in 0.16..0.165)
return "Negative Borderline"
if (predictedDenovixRatio in 0.165..0.235)
return "Sickle Cell Trait"
if (predictedDenovixRatio in 0.235..0.24)
return "Positive Borderline"
if (predictedDenovixRatio in 0.24..1.0)
return "Sickle Cell Disease"
} else {
return "INVALID"
}
} catch (e: Exception) {
showToast("error while performing classification")
Firebase.crashlytics.recordException(e)
return "ERROR"
}
return "INVALID"
}
private fun showToast(message: String) { private fun showToast(message: String) {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
} }

View File

@@ -106,10 +106,16 @@ class HemoCubeViewModel @Inject constructor(
testDetails?.led2Average = DataHolder.hemoCubeTestData?.led2Average testDetails?.led2Average = DataHolder.hemoCubeTestData?.led2Average
testDetails?.led3Average = DataHolder.hemoCubeTestData?.led3Average testDetails?.led3Average = DataHolder.hemoCubeTestData?.led3Average
testDetails?.led4Average = DataHolder.hemoCubeTestData?.led4Average testDetails?.led4Average = DataHolder.hemoCubeTestData?.led4Average
testDetails?.abs1 = DataHolder.hemoCubeTestData?.abs1
testDetails?.abs2 = DataHolder.hemoCubeTestData?.abs2
testDetails?.abs3 = DataHolder.hemoCubeTestData?.abs3
testDetails?.abs4 = DataHolder.hemoCubeTestData?.abs4
testDetails?.deviceRatio = DataHolder.hemoCubeTestData?.deviceRatio testDetails?.deviceRatio = DataHolder.hemoCubeTestData?.deviceRatio
testDetails?.predictedDenovixRatio = DataHolder.hemoCubeTestData?.predictedDenovixRatio
testDetails?.calculatedRatio = DataHolder.hemoCubeTestData?.calculatedRatio testDetails?.calculatedRatio = DataHolder.hemoCubeTestData?.calculatedRatio
testDetails?.coefficients = DataHolder.hemoCubeTestData?.coefficients testDetails?.coefficients = DataHolder.hemoCubeTestData?.coefficients
testDetails?.classificationResult = DataHolder.hemoCubeTestData?.classificationResult!! testDetails?.classificationResult = DataHolder.hemoCubeTestData?.classificationResult!!
testDetails?.prdClassification = DataHolder.hemoCubeTestData?.prdClassification.toString()
} }
private fun addResultTestToDb() { private fun addResultTestToDb() {