From 5ec46802a3dae0ff4871fa293be0745c76187d8f Mon Sep 17 00:00:00 2001 From: Graham Jones Date: Tue, 20 Sep 2022 16:58:40 +0100 Subject: [PATCH] Added settings to enable the original OSD or the new neural network algorithms (or both). Display the seizure probability from the neural network on the main screen. Add seizure probability to the data stored with the datapoints in the database. --- .../org/openseizuredetector/MainActivity.java | 16 +++++++ .../uk/org/openseizuredetector/SdAlgNn.java | 7 +-- .../uk/org/openseizuredetector/SdData.java | 9 ++++ .../org/openseizuredetector/SdDataSource.java | 44 ++++++++++++++----- app/src/main/res/layout/main.xml | 15 +++++++ app/src/main/res/values/strings.xml | 4 ++ .../main/res/xml/seizure_detector_prefs.xml | 10 +++++ 7 files changed, 89 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/uk/org/openseizuredetector/MainActivity.java b/app/src/main/java/uk/org/openseizuredetector/MainActivity.java index d6cd7dd..2a6b7ac 100644 --- a/app/src/main/java/uk/org/openseizuredetector/MainActivity.java +++ b/app/src/main/java/uk/org/openseizuredetector/MainActivity.java @@ -709,10 +709,14 @@ public class MainActivity extends AppCompatActivity { } else specRatio = 0; + long pSeizurePc; + pSeizurePc = (long)(mConnection.mSdServer.mSdData.mPseizure * 100); + Log.d(TAG,"pSeizurePc="+pSeizurePc+", mPseizure="+mConnection.mSdServer.mSdData.mPseizure); ((TextView) findViewById(R.id.powerTv)).setText(getString(R.string.PowerEquals) + mConnection.mSdServer.mSdData.roiPower + " (" + getString(R.string.Threshold) + "=" + mConnection.mSdServer.mSdData.alarmThresh + ")"); ((TextView) findViewById(R.id.spectrumTv)).setText(getString(R.string.SpectrumRatioEquals) + specRatio + " (" + getString(R.string.Threshold) + "=" + mConnection.mSdServer.mSdData.alarmRatioThresh + ")"); + ((TextView) findViewById(R.id.pSeizureTv)).setText("Seizure Probability = "+pSeizurePc+"%"); ProgressBar pb; Drawable pbDrawable; @@ -740,6 +744,18 @@ public class MainActivity extends AppCompatActivity { //pb.getProgressDrawable().setColorFilter(colour, PorterDuff.Mode.SRC_IN); pb.setProgressDrawable(pbDrawable); + pb = ((ProgressBar) findViewById(R.id.pSeizureProgressBar)); + pb.setMax(100); + pb.setProgress((int) pSeizurePc); + pbDrawable = getResources().getDrawable(R.drawable.progress_bar_blue); + if (pSeizurePc > 30) + pbDrawable = getResources().getDrawable(R.drawable.progress_bar_yellow); + if (pSeizurePc > 50) + pbDrawable = getResources().getDrawable(R.drawable.progress_bar_red); + //pb.getProgressDrawable().setColorFilter(colour, PorterDuff.Mode.SRC_IN); + pb.setProgressDrawable(pbDrawable); + + // Fault Conditions - We override the values in the UI because we do not know // if the stored ones are correct or not with a fault present. diff --git a/app/src/main/java/uk/org/openseizuredetector/SdAlgNn.java b/app/src/main/java/uk/org/openseizuredetector/SdAlgNn.java index 7305b8a..01d66bf 100644 --- a/app/src/main/java/uk/org/openseizuredetector/SdAlgNn.java +++ b/app/src/main/java/uk/org/openseizuredetector/SdAlgNn.java @@ -66,7 +66,7 @@ public class SdAlgNn { interpreter.close(); } - public int run(SdData sdData) { + public float getPseizure(SdData sdData) { int i; float[][][] modelInput = new float[1][125][1]; float[][] modelOutput = new float[1][2]; @@ -75,9 +75,6 @@ public class SdAlgNn { } interpreter.run(modelInput, modelOutput); Log.d(TAG,"run - pSeizure="+modelOutput[0][1]); - if (modelOutput[0][1]>0.5) - return 1; - else - return 0; + return(modelOutput[0][1]); } } diff --git a/app/src/main/java/uk/org/openseizuredetector/SdData.java b/app/src/main/java/uk/org/openseizuredetector/SdData.java index fd73a29..1171ca1 100644 --- a/app/src/main/java/uk/org/openseizuredetector/SdData.java +++ b/app/src/main/java/uk/org/openseizuredetector/SdData.java @@ -37,6 +37,11 @@ import org.json.JSONArray; public class SdData implements Parcelable { private final static String TAG = "SdData"; private final static int N_RAW_DATA = 500; // 5 seconds at 100 Hz. + + // Seizure Detection Algorithm Selection + public boolean mOsdAlarmActive; + public boolean mCnnAlarmActive; + /* Analysis settings */ public String phoneAppVersion = ""; public boolean haveSettings = false; // flag to say if we have received settings or not. @@ -107,6 +112,7 @@ public class SdData implements Parcelable { public boolean mO2SatFaultStanding = false; public double mO2Sat = 0; + public double mPseizure = 0.; public SdData() { simpleSpec = new int[10]; @@ -196,6 +202,7 @@ public class SdData implements Parcelable { jsonObj.put("alarmPhrase", alarmPhrase); jsonObj.put("hr", mHR); jsonObj.put("o2Sat", mO2Sat); + jsonObj.put("pSeizure", mPseizure); JSONArray arr = new JSONArray(); for (int i = 0; i < simpleSpec.length; i++) { arr.put(simpleSpec[i]); @@ -247,6 +254,8 @@ public class SdData implements Parcelable { jsonObj.put("alarmFreqMax", alarmFreqMax); jsonObj.put("alarmThresh", alarmThresh); jsonObj.put("alarmRatioThresh", alarmRatioThresh); + jsonObj.put("osdAlarmActive", mOsdAlarmActive); + jsonObj.put("cnnAlarmActive", mCnnAlarmActive); jsonObj.put("hrAlarmActive", mHRAlarmActive); jsonObj.put("hrAlarmStanding", mHRAlarmStanding); jsonObj.put("hrThreshMin", mHRThreshMin); diff --git a/app/src/main/java/uk/org/openseizuredetector/SdDataSource.java b/app/src/main/java/uk/org/openseizuredetector/SdDataSource.java index 12c5be1..ab81759 100644 --- a/app/src/main/java/uk/org/openseizuredetector/SdDataSource.java +++ b/app/src/main/java/uk/org/openseizuredetector/SdDataSource.java @@ -220,6 +220,8 @@ public abstract class SdDataSource { mUtil.writeToSysLogFile("SDDataSource.stop() - error - " + e.toString()); } + mSdAlgNn.close(); + } /** @@ -485,9 +487,12 @@ public abstract class SdDataSource { mWatchAppRunningCheck = false; } + // Use the neural network algorithm to calculate the probability of the data + // being representative of a seizure (sets mSdData.mPseizure) + nnAnalysis(); + // Check this data to see if it represents an alarm state. alarmCheck(); - nnCheck(); hrCheck(); o2SatCheck(); fallCheck(); @@ -505,16 +510,23 @@ public abstract class SdDataSource { * Sets mSdData.alarmState and mSdData.hrAlarmStanding */ private void alarmCheck() { - boolean inAlarm; + boolean inAlarm = false; // Avoid potential divide by zero issue if (mSdData.specPower == 0) mSdData.specPower = 1; Log.v(TAG, "alarmCheck() - roiPower="+mSdData.roiPower+" specPower="+ mSdData.specPower+" ratio="+10*mSdData.roiPower/ mSdData.specPower); - // Is the current set of data representing an alarm state? - if ((mSdData.roiPower > mAlarmThresh) && ((10 * mSdData.roiPower / mSdData.specPower) > mAlarmRatioThresh)) { - inAlarm = true; - } else { - inAlarm = false; + + if (mSdData.mOsdAlarmActive) { + // Is the current set of data representing an alarm state? + if ((mSdData.roiPower > mAlarmThresh) && ((10 * mSdData.roiPower / mSdData.specPower) > mAlarmRatioThresh)) { + inAlarm = true; + } + } + + if (mSdData.mCnnAlarmActive) { + if (mSdData.mPseizure > 0.5) { + inAlarm = true; + } } // set the alarmState to Alarm, Warning or OK, depending on the current state and previous ones. @@ -728,11 +740,12 @@ public abstract class SdDataSource { } } - void nnCheck() { + void nnAnalysis() { //Check the current set of data using the neural network model to look for alarms. - Log.d(TAG,"nnCheck"); - int nnResult = mSdAlgNn.run(mSdData); - Log.d(TAG,"nnCheck - nnResult="+nnResult); + Log.d(TAG,"nnAnalysis"); + float pSeizure = mSdAlgNn.getPseizure(mSdData); + Log.d(TAG,"nnAnalysis - nnResult="+pSeizure); + mSdData.mPseizure = pSeizure; } /** @@ -873,6 +886,15 @@ public abstract class SdDataSource { Log.v(TAG, "updatePrefs() FallWindow = " + mFallWindow); mUtil.writeToSysLogFile( "updatePrefs() FallWindow = " + mFallWindow); + mSdData.mOsdAlarmActive = SP.getBoolean("OsdAlarmActive", false); + Log.v(TAG, "updatePrefs() OsdAlarmActive = " + mSdData.mOsdAlarmActive); + mUtil.writeToSysLogFile( "updatePrefs() OsdAlarmActive = " + mSdData.mOsdAlarmActive); + + mSdData.mCnnAlarmActive = SP.getBoolean("CnnAlarmActive", false); + Log.v(TAG, "updatePrefs() CnnAlarmActive = " + mSdData.mCnnAlarmActive); + mUtil.writeToSysLogFile( "updatePrefs() CnnAlarmActive = " + mSdData.mCnnAlarmActive); + + mSdData.mHRAlarmActive = SP.getBoolean("HRAlarmActive", false); Log.v(TAG, "updatePrefs() HRAlarmActive = " + mSdData.mHRAlarmActive); mUtil.writeToSysLogFile( "updatePrefs() HRAlarmActive = " + mSdData.mHRAlarmActive); diff --git a/app/src/main/res/layout/main.xml b/app/src/main/res/layout/main.xml index ccb06c7..433738a 100644 --- a/app/src/main/res/layout/main.xml +++ b/app/src/main/res/layout/main.xml @@ -119,6 +119,21 @@ android:indeterminate="false" android:minHeight="20dp" /> + + + + + Not Logged in to Data Sharing You must be logged in to the Data Sharing system to be able to report seizures. Include Warnings + Enable the original deterministic OpenSeizureDetector Algorithm to generate alarms. + Enable Original OSD Algorithm + Enable AI (Neural Network) Algorithm + Enable the Artificial Intelligence (Neural Network) algorithm to generate alarms. diff --git a/app/src/main/res/xml/seizure_detector_prefs.xml b/app/src/main/res/xml/seizure_detector_prefs.xml index 3f1460f..d7d1f84 100644 --- a/app/src/main/res/xml/seizure_detector_prefs.xml +++ b/app/src/main/res/xml/seizure_detector_prefs.xml @@ -3,6 +3,16 @@ + +