AutotunePlugin -> plugins module
This commit is contained in:
parent
efcae9f073
commit
f0f5a89fe6
|
@ -37,13 +37,11 @@ import info.nightscout.androidaps.plugins.aps.openAPSSMBDynamicISF.OpenAPSSMBDyn
|
|||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.configBuilder.PluginStore
|
||||
import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin
|
||||
import info.nightscout.androidaps.plugins.general.autotune.AutotunePlugin
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.MaintenancePlugin
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus
|
||||
import info.nightscout.androidaps.plugins.general.tidepool.TidepoolPlugin
|
||||
import info.nightscout.androidaps.plugins.general.wear.WearPlugin
|
||||
import info.nightscout.plugins.general.xdripStatusline.StatusLinePlugin
|
||||
import info.nightscout.androidaps.plugins.pump.combo.ComboPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.eopatch.EopatchPumpPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin
|
||||
|
@ -67,7 +65,9 @@ import info.nightscout.androidaps.utils.protection.ProtectionCheck.ProtectionTyp
|
|||
import info.nightscout.androidaps.utils.protection.ProtectionCheck.ProtectionType.CUSTOM_PIN
|
||||
import info.nightscout.androidaps.utils.protection.ProtectionCheck.ProtectionType.NONE
|
||||
import info.nightscout.automation.AutomationPlugin
|
||||
import info.nightscout.plugins.general.autotune.AutotunePlugin
|
||||
import info.nightscout.plugins.general.smsCommunicator.SmsCommunicatorPlugin
|
||||
import info.nightscout.plugins.general.xdripStatusline.StatusLinePlugin
|
||||
import info.nightscout.plugins.insulin.InsulinOrefFreePeakPlugin
|
||||
import info.nightscout.shared.SafeParse
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
|
@ -335,9 +335,9 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
|
|||
p.initialExpandedChildrenCount = Int.MAX_VALUE
|
||||
}
|
||||
} else {
|
||||
visible = visible || p.key?.contains(filter, true) == true
|
||||
visible = visible || p.title?.contains(filter, true) == true
|
||||
visible = visible || p.summary?.contains(filter, true) == true
|
||||
visible = visible || p.key?.contains(filter, true) == true
|
||||
visible = visible || p.title?.contains(filter, true) == true
|
||||
visible = visible || p.summary?.contains(filter, true) == true
|
||||
}
|
||||
|
||||
p.isVisible = visible
|
||||
|
@ -405,7 +405,7 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
|
|||
} else {
|
||||
if (pref.key.contains("pin")) {
|
||||
pref.summary = rh.gs(R.string.pin_not_set)
|
||||
}else {
|
||||
} else {
|
||||
pref.summary = rh.gs(R.string.password_not_set)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import info.nightscout.androidaps.dana.di.DanaModule
|
|||
import info.nightscout.androidaps.danar.di.DanaRModule
|
||||
import info.nightscout.androidaps.danars.di.DanaRSModule
|
||||
import info.nightscout.androidaps.database.DatabaseModule
|
||||
import info.nightscout.androidaps.dependencyInjection.AutotuneModule
|
||||
import info.nightscout.androidaps.diaconn.di.DiaconnG8Module
|
||||
import info.nightscout.androidaps.insight.di.InsightDatabaseModule
|
||||
import info.nightscout.androidaps.insight.di.InsightModule
|
||||
|
@ -40,7 +39,6 @@ import javax.inject.Singleton
|
|||
FragmentsModule::class,
|
||||
ReceiversModule::class,
|
||||
ServicesModule::class,
|
||||
AutotuneModule::class,
|
||||
ObjectivesModule::class,
|
||||
WizardModule::class,
|
||||
APSModule::class,
|
||||
|
|
|
@ -42,7 +42,6 @@ import info.nightscout.androidaps.plugins.bus.RxBus
|
|||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.plugins.configBuilder.PluginStore
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctionImpl
|
||||
import info.nightscout.androidaps.plugins.general.autotune.AutotunePlugin
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefsImpl
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.PrefFileListProvider
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.DataSyncSelectorImplementation
|
||||
|
@ -71,6 +70,7 @@ import info.nightscout.implementation.queue.CommandQueueImplementation
|
|||
import info.nightscout.implementation.stats.DexcomTirCalculatorImpl
|
||||
import info.nightscout.implementation.stats.TddCalculatorImpl
|
||||
import info.nightscout.implementation.stats.TirCalculatorImpl
|
||||
import info.nightscout.plugins.general.autotune.AutotunePlugin
|
||||
import info.nightscout.plugins.general.smsCommunicator.SmsCommunicatorPlugin
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
|
|
|
@ -27,17 +27,16 @@ import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderFragment
|
|||
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesFragment
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.activities.ObjectivesExamDialog
|
||||
import info.nightscout.androidaps.plugins.general.actions.ActionsFragment
|
||||
import info.nightscout.androidaps.plugins.general.autotune.AutotuneFragment
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.MaintenanceFragment
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSClientFragment
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewFragment
|
||||
import info.nightscout.androidaps.plugins.general.overview.dialogs.EditQuickWizardDialog
|
||||
import info.nightscout.androidaps.plugins.general.tidepool.TidepoolFragment
|
||||
import info.nightscout.androidaps.plugins.general.wear.WearFragment
|
||||
import info.nightscout.plugins.profile.ProfileFragment
|
||||
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpFragment
|
||||
import info.nightscout.androidaps.plugins.source.BGSourceFragment
|
||||
import info.nightscout.androidaps.utils.protection.PasswordCheck
|
||||
import info.nightscout.plugins.general.autotune.AutotuneFragment
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
||||
|
@ -48,10 +47,7 @@ abstract class FragmentsModule {
|
|||
@ContributesAndroidInjector abstract fun contributesActionsFragment(): ActionsFragment
|
||||
@ContributesAndroidInjector abstract fun contributesAutotuneFragment(): AutotuneFragment
|
||||
@ContributesAndroidInjector abstract fun contributesBGSourceFragment(): BGSourceFragment
|
||||
|
||||
@ContributesAndroidInjector abstract fun contributesConfigBuilderFragment(): ConfigBuilderFragment
|
||||
|
||||
@ContributesAndroidInjector abstract fun contributesLocalProfileFragment(): ProfileFragment
|
||||
@ContributesAndroidInjector abstract fun contributesObjectivesFragment(): ObjectivesFragment
|
||||
@ContributesAndroidInjector abstract fun contributesOpenAPSFragment(): OpenAPSFragment
|
||||
@ContributesAndroidInjector abstract fun contributesOverviewFragment(): OverviewFragment
|
||||
|
|
|
@ -24,18 +24,14 @@ import info.nightscout.androidaps.plugins.constraints.signatureVerifier.Signatur
|
|||
import info.nightscout.androidaps.plugins.constraints.storage.StorageConstraintPlugin
|
||||
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerPlugin
|
||||
import info.nightscout.androidaps.plugins.general.actions.ActionsPlugin
|
||||
import info.nightscout.androidaps.plugins.general.autotune.AutotunePlugin
|
||||
import info.nightscout.androidaps.plugins.general.dataBroadcaster.DataBroadcastPlugin
|
||||
import info.nightscout.plugins.general.food.FoodPlugin
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.MaintenancePlugin
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin
|
||||
import info.nightscout.androidaps.plugins.general.persistentNotification.PersistentNotificationPlugin
|
||||
import info.nightscout.plugins.general.themes.ThemeSwitcherPlugin
|
||||
import info.nightscout.androidaps.plugins.general.tidepool.TidepoolPlugin
|
||||
import info.nightscout.androidaps.plugins.general.wear.WearPlugin
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||
import info.nightscout.plugins.profile.ProfilePlugin
|
||||
import info.nightscout.androidaps.plugins.pump.combo.ComboPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.eopatch.EopatchPumpPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin
|
||||
|
@ -58,12 +54,16 @@ import info.nightscout.androidaps.plugins.source.RandomBgPlugin
|
|||
import info.nightscout.androidaps.plugins.source.TomatoPlugin
|
||||
import info.nightscout.androidaps.plugins.source.XdripPlugin
|
||||
import info.nightscout.automation.AutomationPlugin
|
||||
import info.nightscout.plugins.general.autotune.AutotunePlugin
|
||||
import info.nightscout.plugins.general.food.FoodPlugin
|
||||
import info.nightscout.plugins.general.smsCommunicator.SmsCommunicatorPlugin
|
||||
import info.nightscout.plugins.general.themes.ThemeSwitcherPlugin
|
||||
import info.nightscout.plugins.general.xdripStatusline.StatusLinePlugin
|
||||
import info.nightscout.plugins.insulin.InsulinLyumjevPlugin
|
||||
import info.nightscout.plugins.insulin.InsulinOrefFreePeakPlugin
|
||||
import info.nightscout.plugins.insulin.InsulinOrefRapidActingPlugin
|
||||
import info.nightscout.plugins.insulin.InsulinOrefUltraRapidActingPlugin
|
||||
import info.nightscout.plugins.profile.ProfilePlugin
|
||||
import javax.inject.Qualifier
|
||||
|
||||
@Suppress("unused")
|
||||
|
|
|
@ -7,17 +7,23 @@ import androidx.core.content.FileProvider
|
|||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.BuildConfig
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.interfaces.BuildHelper
|
||||
import info.nightscout.androidaps.interfaces.Config
|
||||
import info.nightscout.androidaps.interfaces.PluginBase
|
||||
import info.nightscout.androidaps.interfaces.PluginDescription
|
||||
import info.nightscout.androidaps.interfaces.PluginType
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus
|
||||
import info.nightscout.androidaps.interfaces.BuildHelper
|
||||
import info.nightscout.androidaps.interfaces.ResourceHelper
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus
|
||||
import info.nightscout.plugins.general.maintenance.LoggerUtils
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
import java.io.*
|
||||
import java.util.*
|
||||
import java.io.BufferedInputStream
|
||||
import java.io.BufferedOutputStream
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.util.Arrays
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipOutputStream
|
||||
import javax.inject.Inject
|
||||
|
|
|
@ -51,7 +51,6 @@ import java.util.concurrent.ScheduledFuture
|
|||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlin.math.floor
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
|
@ -450,23 +449,6 @@ class IobCobCalculatorPlugin @Inject constructor(
|
|||
return array
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
// From https://gist.github.com/IceCreamYou/6ffa1b18c4c8f6aeaad2
|
||||
// Returns the value at a given percentile in a sorted numeric array.
|
||||
// "Linear interpolation between closest ranks" method
|
||||
fun percentile(arr: Array<Double>, p: Double): Double {
|
||||
if (arr.isEmpty()) return 0.0
|
||||
if (p <= 0) return arr[0]
|
||||
if (p >= 1) return arr[arr.size - 1]
|
||||
val index = arr.size * p
|
||||
val lower = floor(index)
|
||||
val upper = lower + 1
|
||||
val weight = index % 1
|
||||
return if (upper >= arr.size) arr[lower.toInt()] else arr[lower.toInt()] * (1 - weight) + arr[upper.toInt()] * weight
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Time range to the past for IOB calculation
|
||||
* @return milliseconds
|
||||
|
|
|
@ -12,18 +12,18 @@ import info.nightscout.androidaps.interfaces.PluginDescription
|
|||
import info.nightscout.androidaps.interfaces.PluginType
|
||||
import info.nightscout.androidaps.interfaces.Profile
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.interfaces.ResourceHelper
|
||||
import info.nightscout.androidaps.interfaces.Sensitivity.SensitivityType
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensDataStore
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.interfaces.ResourceHelper
|
||||
import info.nightscout.plugins.utils.Percentile
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.logging.LTag
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
import java.util.Arrays
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlin.math.roundToInt
|
||||
|
@ -116,7 +116,7 @@ class SensitivityAAPSPlugin @Inject constructor(
|
|||
val sensResult: String
|
||||
aapsLogger.debug(LTag.AUTOSENS, "Records: $index $pastSensitivity")
|
||||
Arrays.sort(deviations)
|
||||
val percentile = IobCobCalculatorPlugin.percentile(deviations, 0.50)
|
||||
val percentile = Percentile.percentile(deviations, 0.50)
|
||||
val basalOff = percentile * (60.0 / 5.0) / sens
|
||||
val ratio = 1 + basalOff / profile.getMaxDailyBasal()
|
||||
sensResult = when {
|
||||
|
@ -126,13 +126,16 @@ class SensitivityAAPSPlugin @Inject constructor(
|
|||
|
||||
}
|
||||
aapsLogger.debug(LTag.AUTOSENS, sensResult)
|
||||
val output = fillResult(ratio, current.cob, pastSensitivity, ratioLimit,
|
||||
sensResult, deviationsArray.size)
|
||||
val output = fillResult(
|
||||
ratio, current.cob, pastSensitivity, ratioLimit,
|
||||
sensResult, deviationsArray.size
|
||||
)
|
||||
aapsLogger.debug(
|
||||
LTag.AUTOSENS, "Sensitivity to: "
|
||||
+ dateUtil.dateAndTimeString(toTime) +
|
||||
" ratio: " + output.ratio
|
||||
+ " mealCOB: " + current.cob)
|
||||
+ dateUtil.dateAndTimeString(toTime) +
|
||||
" ratio: " + output.ratio
|
||||
+ " mealCOB: " + current.cob
|
||||
)
|
||||
aapsLogger.debug(LTag.AUTOSENS, "Sensitivity to: deviations " + deviations.contentToString())
|
||||
return output
|
||||
}
|
||||
|
@ -158,7 +161,10 @@ class SensitivityAAPSPlugin @Inject constructor(
|
|||
override fun applyConfiguration(configuration: JSONObject) {
|
||||
try {
|
||||
if (configuration.has(rh.gs(R.string.key_absorption_maxtime))) sp.putDouble(R.string.key_absorption_maxtime, configuration.getDouble(rh.gs(R.string.key_absorption_maxtime)))
|
||||
if (configuration.has(rh.gs(R.string.key_openapsama_autosens_period))) sp.putDouble(R.string.key_openapsama_autosens_period, configuration.getDouble(rh.gs(R.string.key_openapsama_autosens_period)))
|
||||
if (configuration.has(rh.gs(R.string.key_openapsama_autosens_period))) sp.putDouble(
|
||||
R.string.key_openapsama_autosens_period,
|
||||
configuration.getDouble(rh.gs(R.string.key_openapsama_autosens_period))
|
||||
)
|
||||
if (configuration.has(rh.gs(R.string.key_openapsama_autosens_max))) sp.getDouble(R.string.key_openapsama_autosens_max, configuration.getDouble(rh.gs(R.string.key_openapsama_autosens_max)))
|
||||
if (configuration.has(rh.gs(R.string.key_openapsama_autosens_min))) sp.getDouble(R.string.key_openapsama_autosens_min, configuration.getDouble(rh.gs(R.string.key_openapsama_autosens_min)))
|
||||
} catch (e: JSONException) {
|
||||
|
|
|
@ -12,19 +12,19 @@ import info.nightscout.androidaps.interfaces.PluginDescription
|
|||
import info.nightscout.androidaps.interfaces.PluginType
|
||||
import info.nightscout.androidaps.interfaces.Profile
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.interfaces.ResourceHelper
|
||||
import info.nightscout.androidaps.interfaces.Sensitivity.SensitivityType
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensDataStore
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.interfaces.ResourceHelper
|
||||
import info.nightscout.plugins.utils.Percentile
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.logging.LTag
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
import java.util.Arrays
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlin.math.roundToInt
|
||||
|
@ -75,7 +75,7 @@ class SensitivityOref1Plugin @Inject constructor(
|
|||
//[0] = 8 hour
|
||||
//[1] = 24 hour
|
||||
//deviationsHour has DeviationsArray
|
||||
val deviationsHour = mutableListOf(ArrayList<Double>(), ArrayList<Double>())
|
||||
val deviationsHour = mutableListOf(ArrayList(), ArrayList<Double>())
|
||||
val pastSensitivityArray = mutableListOf("", "")
|
||||
val sensResultArray = mutableListOf("", "")
|
||||
val ratioArray = mutableListOf(0.0, 0.0)
|
||||
|
@ -160,8 +160,8 @@ class SensitivityOref1Plugin @Inject constructor(
|
|||
val sens = profile.getIsfMgdl()
|
||||
aapsLogger.debug(LTag.AUTOSENS, "Records: $index $pastSensitivity")
|
||||
Arrays.sort(deviations)
|
||||
val pSensitive = IobCobCalculatorPlugin.percentile(deviations, 0.50)
|
||||
val pResistant = IobCobCalculatorPlugin.percentile(deviations, 0.50)
|
||||
val pSensitive = Percentile.percentile(deviations, 0.50)
|
||||
val pResistant = Percentile.percentile(deviations, 0.50)
|
||||
var basalOff = 0.0
|
||||
when {
|
||||
pSensitive < 0 -> { // sensitive
|
||||
|
@ -196,9 +196,10 @@ class SensitivityOref1Plugin @Inject constructor(
|
|||
val output = fillResult(ratioArray[key], current.cob, pastSensitivityArray[key], ratioLimitArray[key], sensResultArray[key] + comparison, deviationsHour[key].size)
|
||||
aapsLogger.debug(
|
||||
LTag.AUTOSENS, "Sensitivity to: "
|
||||
+ dateUtil.dateAndTimeString(toTime) +
|
||||
" ratio: " + output.ratio
|
||||
+ " mealCOB: " + current.cob)
|
||||
+ dateUtil.dateAndTimeString(toTime) +
|
||||
" ratio: " + output.ratio
|
||||
+ " mealCOB: " + current.cob
|
||||
)
|
||||
return output
|
||||
}
|
||||
|
||||
|
@ -219,7 +220,10 @@ class SensitivityOref1Plugin @Inject constructor(
|
|||
|
||||
override fun applyConfiguration(configuration: JSONObject) {
|
||||
try {
|
||||
if (configuration.has(rh.gs(R.string.key_openapsama_min_5m_carbimpact))) sp.putDouble(R.string.key_openapsama_min_5m_carbimpact, configuration.getDouble(rh.gs(R.string.key_openapsama_min_5m_carbimpact)))
|
||||
if (configuration.has(rh.gs(R.string.key_openapsama_min_5m_carbimpact))) sp.putDouble(
|
||||
R.string.key_openapsama_min_5m_carbimpact,
|
||||
configuration.getDouble(rh.gs(R.string.key_openapsama_min_5m_carbimpact))
|
||||
)
|
||||
if (configuration.has(rh.gs(R.string.key_absorption_cutoff))) sp.putDouble(R.string.key_absorption_cutoff, configuration.getDouble(rh.gs(R.string.key_absorption_cutoff)))
|
||||
if (configuration.has(rh.gs(R.string.key_openapsama_autosens_max))) sp.getDouble(R.string.key_openapsama_autosens_max, configuration.getDouble(rh.gs(R.string.key_openapsama_autosens_max)))
|
||||
if (configuration.has(rh.gs(R.string.key_openapsama_autosens_min))) sp.getDouble(R.string.key_openapsama_autosens_min, configuration.getDouble(rh.gs(R.string.key_openapsama_autosens_min)))
|
||||
|
|
|
@ -270,8 +270,6 @@
|
|||
<string name="show_queue">Show queue</string>
|
||||
<string name="queue">Queue:</string>
|
||||
<string name="status">Status:</string>
|
||||
<string name="key_nsclientinternal_url" translatable="false">nsclientinternal_url</string>
|
||||
<string name="key_nsclientinternal_api_secret" translatable="false">nsclientinternal_api_secret</string>
|
||||
<string name="clearlog">Clear log</string>
|
||||
<string name="key_nsclientinternal_autoscroll" translatable="false">nsclientinternal_autoscroll</string>
|
||||
<string name="key_nsclientinternal_paused" translatable="false">nsclientinternal_paused</string>
|
||||
|
@ -529,7 +527,6 @@
|
|||
<string name="overview_show_basals">Basals</string>
|
||||
<string name="closed_loop_disabled_on_dev_branch">Running dev version. Closed loop is disabled.</string>
|
||||
<string name="engineering_mode_enabled">Engineering mode enabled</string>
|
||||
<string name="profileswitch_ismissing">ProfileSwitch missing. Please do a profile switch or press \"Activate Profile\" in the LocalProfile.</string>
|
||||
<string name="pumpisnottempbasalcapable">Pump is not temp basal capable</string>
|
||||
<string name="closedmodedisabledinpreferences">Closed loop mode disabled in preferences</string>
|
||||
<string name="autosensdisabledinpreferences">Autosens disabled in preferences</string>
|
||||
|
|
|
@ -3,10 +3,11 @@ package info.nightscout.androidaps.plugins.general.maintenance
|
|||
import android.content.Context
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.TestBase
|
||||
import info.nightscout.androidaps.interfaces.Config
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus
|
||||
import info.nightscout.androidaps.interfaces.BuildHelper
|
||||
import info.nightscout.androidaps.interfaces.Config
|
||||
import info.nightscout.androidaps.interfaces.ResourceHelper
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus
|
||||
import info.nightscout.plugins.general.maintenance.LoggerUtils
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
import org.junit.Assert
|
||||
import org.junit.Before
|
||||
|
@ -27,7 +28,7 @@ class MaintenancePluginTest : TestBase() {
|
|||
@Mock lateinit var fileListProvider: PrefFileListProvider
|
||||
@Mock lateinit var config: Config
|
||||
|
||||
lateinit var sut: MaintenancePlugin
|
||||
private lateinit var sut: MaintenancePlugin
|
||||
|
||||
@Before
|
||||
fun mock() {
|
||||
|
|
|
@ -86,6 +86,8 @@
|
|||
<string name="key_rangetodisplay" translatable="false">rangetodisplay</string>
|
||||
<string name="key_local_profile_last_change" translatable="false">local_profile_last_change</string>
|
||||
<string name="key_ns_receive_profile_store" translatable="false">ns_receive_profile_store</string>
|
||||
<string name="key_nsclientinternal_url" translatable="false">nsclientinternal_url</string>
|
||||
<string name="key_nsclientinternal_api_secret" translatable="false">nsclientinternal_api_secret</string>
|
||||
|
||||
<!-- General-->
|
||||
<string name="refresh">Refresh</string>
|
||||
|
@ -233,6 +235,8 @@
|
|||
<string name="remove_label">REMOVE</string>
|
||||
<string name="activate_profile">Activate profile</string>
|
||||
<string name="reset">reset</string>
|
||||
<string name="profileswitch_ismissing">ProfileSwitch missing. Please do a profile switch or press \"Activate Profile\" in the LocalProfile.</string>
|
||||
<string name="profile">Profile</string>
|
||||
|
||||
<!-- Constraints-->
|
||||
<string name="limitingbasalratio">Limiting max basal rate to %1$.2f U/h because of %2$s</string>
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
package info.nightscout.androidaps.dependencyInjection
|
||||
package info.nightscout.plugins.di
|
||||
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.androidaps.plugins.general.autotune.AutotuneCore
|
||||
import info.nightscout.androidaps.plugins.general.autotune.AutotuneIob
|
||||
import info.nightscout.androidaps.plugins.general.autotune.AutotunePrep
|
||||
import info.nightscout.androidaps.plugins.general.autotune.AutotuneFS
|
||||
import info.nightscout.androidaps.plugins.general.autotune.data.*
|
||||
import info.nightscout.plugins.general.autotune.AutotuneCore
|
||||
import info.nightscout.plugins.general.autotune.AutotuneFS
|
||||
import info.nightscout.plugins.general.autotune.AutotuneIob
|
||||
import info.nightscout.plugins.general.autotune.AutotunePrep
|
||||
import info.nightscout.plugins.general.autotune.data.ATProfile
|
||||
import info.nightscout.plugins.general.autotune.data.BGDatum
|
||||
import info.nightscout.plugins.general.autotune.data.CRDatum
|
||||
import info.nightscout.plugins.general.autotune.data.PreppedGlucose
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
|
@ -6,7 +6,9 @@ import dagger.Module
|
|||
includes = [
|
||||
InsulinModule::class,
|
||||
FoodModule::class,
|
||||
SMSCommunicatorModule::class
|
||||
SMSCommunicatorModule::class,
|
||||
AutotuneModule::class,
|
||||
ProfileModule::class
|
||||
]
|
||||
)
|
||||
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package info.nightscout.plugins.di
|
||||
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.plugins.profile.ProfileFragment
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
||||
abstract class ProfileModule {
|
||||
|
||||
@ContributesAndroidInjector abstract fun contributesLocalProfileFragment(): ProfileFragment
|
||||
}
|
|
@ -1,15 +1,16 @@
|
|||
package info.nightscout.androidaps.plugins.general.autotune
|
||||
package info.nightscout.plugins.general.autotune
|
||||
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.LocalInsulin
|
||||
import info.nightscout.androidaps.plugins.general.autotune.data.ATProfile
|
||||
import info.nightscout.androidaps.plugins.general.autotune.data.PreppedGlucose
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||
import info.nightscout.androidaps.utils.Round
|
||||
import info.nightscout.plugins.R
|
||||
import info.nightscout.plugins.general.autotune.data.ATProfile
|
||||
import info.nightscout.plugins.general.autotune.data.PreppedGlucose
|
||||
import info.nightscout.plugins.utils.Percentile
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlin.math.max
|
||||
|
||||
@Singleton
|
||||
class AutotuneCore @Inject constructor(
|
||||
|
@ -47,8 +48,7 @@ class AutotuneCore @Inject constructor(
|
|||
|
||||
// tune DIA
|
||||
var newDia = dia
|
||||
if (diaDeviations.size > 0)
|
||||
{
|
||||
if (diaDeviations.isNotEmpty()) {
|
||||
val currentDiaMeanDev = diaDeviations[2].meanDeviation
|
||||
val currentDiaRMSDev = diaDeviations[2].rmsDeviation
|
||||
//Console.WriteLine(DIA,currentDIAMeanDev,currentDIARMSDev);
|
||||
|
@ -56,35 +56,28 @@ class AutotuneCore @Inject constructor(
|
|||
var minRmsDeviations = 1000000.0
|
||||
var meanBest = 2
|
||||
var rmsBest = 2
|
||||
for (i in 0..diaDeviations.size-1)
|
||||
{
|
||||
for (i in diaDeviations.indices) {
|
||||
val meanDeviations = diaDeviations[i].meanDeviation
|
||||
val rmsDeviations = diaDeviations[i].rmsDeviation
|
||||
if (meanDeviations < minMeanDeviations)
|
||||
{
|
||||
if (meanDeviations < minMeanDeviations) {
|
||||
minMeanDeviations = Round.roundTo(meanDeviations, 0.001)
|
||||
meanBest = i
|
||||
}
|
||||
if (rmsDeviations < minRmsDeviations)
|
||||
{
|
||||
if (rmsDeviations < minRmsDeviations) {
|
||||
minRmsDeviations = Round.roundTo(rmsDeviations, 0.001)
|
||||
rmsBest = i
|
||||
}
|
||||
}
|
||||
log("Best insulinEndTime for meanDeviations: ${diaDeviations[meanBest].dia} hours")
|
||||
log("Best insulinEndTime for RMSDeviations: ${diaDeviations[rmsBest].dia} hours")
|
||||
if (meanBest < 2 && rmsBest < 2)
|
||||
{
|
||||
if (meanBest < 2 && rmsBest < 2) {
|
||||
if (diaDeviations[1].meanDeviation < currentDiaMeanDev * 0.99 && diaDeviations[1].rmsDeviation < currentDiaRMSDev * 0.99)
|
||||
newDia = diaDeviations[1].dia
|
||||
}
|
||||
else if (meanBest > 2 && rmsBest > 2)
|
||||
{
|
||||
} else if (meanBest > 2 && rmsBest > 2) {
|
||||
if (diaDeviations[3].meanDeviation < currentDiaMeanDev * 0.99 && diaDeviations[3].rmsDeviation < currentDiaRMSDev * 0.99)
|
||||
newDia = diaDeviations[3].dia
|
||||
}
|
||||
if (newDia > 12.0)
|
||||
{
|
||||
if (newDia > 12.0) {
|
||||
log("insulinEndTime maximum is 12h: not raising further")
|
||||
newDia = 12.0
|
||||
}
|
||||
|
@ -96,8 +89,7 @@ class AutotuneCore @Inject constructor(
|
|||
|
||||
// tune insulinPeakTime
|
||||
var newPeak = peak
|
||||
if (peakDeviations.size > 2)
|
||||
{
|
||||
if (peakDeviations.size > 2) {
|
||||
val currentPeakMeanDev = peakDeviations[2].meanDeviation
|
||||
val currentPeakRMSDev = peakDeviations[2].rmsDeviation
|
||||
//Console.WriteLine(currentPeakMeanDev);
|
||||
|
@ -105,37 +97,31 @@ class AutotuneCore @Inject constructor(
|
|||
var minRmsDeviations = 1000000.0
|
||||
var meanBest = 2
|
||||
var rmsBest = 2
|
||||
for (i in 0..peakDeviations.size-1)
|
||||
{
|
||||
val meanDeviations = peakDeviations[i].meanDeviation;
|
||||
val rmsDeviations = peakDeviations[i].rmsDeviation;
|
||||
if (meanDeviations < minMeanDeviations)
|
||||
{
|
||||
for (i in peakDeviations.indices) {
|
||||
val meanDeviations = peakDeviations[i].meanDeviation
|
||||
val rmsDeviations = peakDeviations[i].rmsDeviation
|
||||
if (meanDeviations < minMeanDeviations) {
|
||||
minMeanDeviations = Round.roundTo(meanDeviations, 0.001)
|
||||
meanBest = i
|
||||
}
|
||||
if (rmsDeviations < minRmsDeviations)
|
||||
{
|
||||
if (rmsDeviations < minRmsDeviations) {
|
||||
minRmsDeviations = Round.roundTo(rmsDeviations, 0.001)
|
||||
rmsBest = i
|
||||
}
|
||||
}
|
||||
log("Best insulinPeakTime for meanDeviations: ${peakDeviations[meanBest].peak} minutes")
|
||||
log("Best insulinPeakTime for RMSDeviations: ${peakDeviations[rmsBest].peak} minutes")
|
||||
if (meanBest < 2 && rmsBest < 2)
|
||||
{
|
||||
if (meanBest < 2 && rmsBest < 2) {
|
||||
if (peakDeviations[1].meanDeviation < currentPeakMeanDev * 0.99 && peakDeviations[1].rmsDeviation < currentPeakRMSDev * 0.99)
|
||||
newPeak = peakDeviations[1].peak
|
||||
}
|
||||
else if (meanBest > 2 && rmsBest > 2)
|
||||
{
|
||||
} else if (meanBest > 2 && rmsBest > 2) {
|
||||
if (peakDeviations[3].meanDeviation < currentPeakMeanDev * 0.99 && peakDeviations[3].rmsDeviation < currentPeakRMSDev * 0.99)
|
||||
newPeak = peakDeviations[3].peak
|
||||
}
|
||||
if (newPeak != peak)
|
||||
log("Adjusting insulinPeakTime from " + peak + " to " + newPeak + " minutes")
|
||||
log("Adjusting insulinPeakTime from $peak to $newPeak minutes")
|
||||
else
|
||||
log("Leaving insulinPeakTime unchanged at " + peak)
|
||||
log("Leaving insulinPeakTime unchanged at $peak")
|
||||
}
|
||||
|
||||
// Calculate carb ratio (CR) independently of csf and isf
|
||||
|
@ -180,22 +166,22 @@ class AutotuneCore @Inject constructor(
|
|||
for (i in 0..23) {
|
||||
newHourlyBasalProfile[i] = hourlyBasalProfile[i]
|
||||
}
|
||||
val basalUntuned = previousAutotune.basalUntuned
|
||||
val basalUnTuned = previousAutotune.basalUntuned
|
||||
|
||||
//autotune-core (lib/autotune/index.js) #210-#266
|
||||
// look at net deviations for each hour
|
||||
for (hour in 0..23) {
|
||||
var deviations = 0.0
|
||||
for (i in basalGlucose.indices) {
|
||||
val BGTime = Calendar.getInstance()
|
||||
val bgTime = Calendar.getInstance()
|
||||
//var BGTime: Date? = null
|
||||
if (basalGlucose[i].date != 0L) {
|
||||
BGTime.setTimeInMillis(basalGlucose[i].date)
|
||||
bgTime.timeInMillis = basalGlucose[i].date
|
||||
//BGTime = Date(basalGlucose[i].date)
|
||||
} else {
|
||||
log("Could not determine last BG time")
|
||||
}
|
||||
val myHour = BGTime.get(Calendar.HOUR_OF_DAY)
|
||||
val myHour = bgTime.get(Calendar.HOUR_OF_DAY)
|
||||
//val myHour = BGTime!!.hours
|
||||
if (hour == myHour) {
|
||||
//log.debug(basalGlucose[i].deviation);
|
||||
|
@ -280,7 +266,7 @@ class AutotuneCore @Inject constructor(
|
|||
}
|
||||
//log.debug(hour, newHourlyBasalProfile);
|
||||
newHourlyBasalProfile[hour] = Round.roundTo(0.8 * hourlyBasalProfile[hour] + 0.1 * newHourlyBasalProfile[lastAdjustedHour] + 0.1 * newHourlyBasalProfile[nextAdjustedHour], 0.001)
|
||||
basalUntuned[hour]++
|
||||
basalUnTuned[hour]++
|
||||
log("Adjusting hour " + hour + " basal from " + hourlyBasalProfile[hour] + " to " + newHourlyBasalProfile[hour] + " based on hour " + lastAdjustedHour + " = " + newHourlyBasalProfile[lastAdjustedHour] + " and hour " + nextAdjustedHour + " = " + newHourlyBasalProfile[nextAdjustedHour])
|
||||
} else {
|
||||
lastAdjustedHour = hour
|
||||
|
@ -301,7 +287,6 @@ class AutotuneCore @Inject constructor(
|
|||
var mealCarbs = 0
|
||||
var totalMealCarbs = 0
|
||||
var totalDeviations = 0.0
|
||||
val fullNewCSF: Double
|
||||
//log.debug(CSFGlucose[0].mealAbsorption);
|
||||
//log.debug(CSFGlucose[0]);
|
||||
//autotune-core (lib/autotune/index.js) #346-#365
|
||||
|
@ -321,8 +306,8 @@ class AutotuneCore @Inject constructor(
|
|||
totalDeviations += deviations
|
||||
} else {
|
||||
//todo Philoul check 0 * min5minCarbImpact ???
|
||||
deviations += Math.max(0 * min5minCarbImpact, csfGlucose[i].deviation)
|
||||
mealCarbs = Math.max(mealCarbs, csfGlucose[i].mealCarbs)
|
||||
deviations += max(0 * min5minCarbImpact, csfGlucose[i].deviation)
|
||||
mealCarbs = max(mealCarbs, csfGlucose[i].mealCarbs)
|
||||
}
|
||||
}
|
||||
// at midnight, write down the mealcarbs as total meal carbs (to prevent special case of when only one meal and it not finishing absorbing by midnight)
|
||||
|
@ -334,7 +319,7 @@ class AutotuneCore @Inject constructor(
|
|||
totalDeviations += deviations
|
||||
}
|
||||
//log.debug(totalDeviations, totalMealCarbs);
|
||||
fullNewCSF = if (totalMealCarbs == 0) {
|
||||
val fullNewCSF: Double = if (totalMealCarbs == 0) {
|
||||
// if no meals today, csf is unchanged
|
||||
csf
|
||||
} else {
|
||||
|
@ -420,22 +405,22 @@ class AutotuneCore @Inject constructor(
|
|||
for (i in isfGlucose.indices) {
|
||||
val deviation = isfGlucose[i].deviation
|
||||
isfDeviations.add(deviation)
|
||||
val BGI = isfGlucose[i].bgi
|
||||
bGIs.add(BGI)
|
||||
val bgi = isfGlucose[i].bgi
|
||||
bGIs.add(bgi)
|
||||
val avgDelta = isfGlucose[i].avgDelta
|
||||
avgDeltas.add(avgDelta)
|
||||
val ratio = 1 + deviation / BGI
|
||||
val ratio = 1 + deviation / bgi
|
||||
//log.debug("Deviation:",deviation,"BGI:",BGI,"avgDelta:",avgDelta,"ratio:",ratio);
|
||||
ratios.add(ratio)
|
||||
count++
|
||||
}
|
||||
Collections.sort(avgDeltas)
|
||||
Collections.sort(bGIs)
|
||||
Collections.sort(isfDeviations)
|
||||
Collections.sort(ratios)
|
||||
var p50deviation = IobCobCalculatorPlugin.percentile(isfDeviations.toTypedArray(), 0.50)
|
||||
var p50BGI = IobCobCalculatorPlugin.percentile(bGIs.toTypedArray(), 0.50)
|
||||
val p50ratios = Round.roundTo(IobCobCalculatorPlugin.percentile(ratios.toTypedArray(), 0.50), 0.001)
|
||||
avgDeltas.sort()
|
||||
bGIs.sort()
|
||||
isfDeviations.sort()
|
||||
ratios.sort()
|
||||
var p50deviation = Percentile.percentile(isfDeviations.toTypedArray(), 0.50)
|
||||
var p50BGI = Percentile.percentile(bGIs.toTypedArray(), 0.50)
|
||||
val p50ratios = Round.roundTo(Percentile.percentile(ratios.toTypedArray(), 0.50), 0.001)
|
||||
var fullNewISF = isf
|
||||
if (count < 10) {
|
||||
// leave isf unchanged if fewer than 5 isf data points
|
||||
|
@ -446,13 +431,12 @@ class AutotuneCore @Inject constructor(
|
|||
}
|
||||
fullNewISF = Round.roundTo(fullNewISF, 0.001)
|
||||
// adjust the target isf to be a weighted average of fullNewISF and pumpISF
|
||||
val adjustmentFraction: Double
|
||||
/*
|
||||
// TODO: philoul may be allow adjustmentFraction in settings with safety limits ?)
|
||||
if (typeof(pumpProfile.autotune_isf_adjustmentFraction) !== 'undefined') {
|
||||
adjustmentFraction = pumpProfile.autotune_isf_adjustmentFraction;
|
||||
} else {*/
|
||||
adjustmentFraction = 1.0
|
||||
val adjustmentFraction = 1.0
|
||||
// }
|
||||
|
||||
// low autosens ratio = high isf
|
||||
|
@ -501,7 +485,7 @@ class AutotuneCore @Inject constructor(
|
|||
previousAutotune.basal = basalProfile
|
||||
previousAutotune.isf = isf
|
||||
previousAutotune.ic = Round.roundTo(carbRatio, 0.001)
|
||||
previousAutotune.basalUntuned = basalUntuned
|
||||
previousAutotune.basalUntuned = basalUnTuned
|
||||
previousAutotune.dia = newDia
|
||||
previousAutotune.peak = newPeak
|
||||
val localInsulin = LocalInsulin("Ins_$newPeak-$newDia", newPeak, newDia)
|
|
@ -1,13 +1,21 @@
|
|||
package info.nightscout.androidaps.plugins.general.autotune
|
||||
package info.nightscout.plugins.general.autotune
|
||||
|
||||
import info.nightscout.androidaps.interfaces.ResourceHelper
|
||||
import info.nightscout.androidaps.plugins.general.autotune.data.ATProfile
|
||||
import info.nightscout.androidaps.plugins.general.autotune.data.PreppedGlucose
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.LoggerUtils
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.plugins.R
|
||||
import info.nightscout.plugins.general.autotune.data.ATProfile
|
||||
import info.nightscout.plugins.general.autotune.data.PreppedGlucose
|
||||
import info.nightscout.plugins.general.maintenance.LoggerUtils
|
||||
import org.json.JSONException
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.*
|
||||
import java.io.BufferedInputStream
|
||||
import java.io.BufferedOutputStream
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.FileOutputStream
|
||||
import java.io.FileWriter
|
||||
import java.io.IOException
|
||||
import java.io.PrintWriter
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipOutputStream
|
||||
|
@ -28,7 +36,6 @@ class AutotuneFS @Inject constructor(
|
|||
val AAPSBOLUSESPREF = "aaps-boluses."
|
||||
val PREPPEDPREF = "aaps-autotune."
|
||||
val SETTINGS = "settings.json"
|
||||
val PROFIL = "profil"
|
||||
val PUMPPROFILE = "pumpprofile.json"
|
||||
val TUNEDPROFILE = "newaapsprofile."
|
||||
val LOGPREF = "autotune."
|
|
@ -1,4 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.general.autotune
|
||||
package info.nightscout.plugins.general.autotune
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Paint
|
||||
|
@ -20,12 +20,10 @@ import android.widget.TextView
|
|||
import dagger.android.HasAndroidInjector
|
||||
import dagger.android.support.DaggerFragment
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.LocalInsulin
|
||||
import info.nightscout.androidaps.data.ProfileSealed
|
||||
import info.nightscout.androidaps.database.entities.UserEntry
|
||||
import info.nightscout.androidaps.database.entities.ValueWithUnit
|
||||
import info.nightscout.androidaps.databinding.AutotuneFragmentBinding
|
||||
import info.nightscout.androidaps.dialogs.ProfileViewerDialog
|
||||
import info.nightscout.androidaps.extensions.runOnUiThread
|
||||
import info.nightscout.androidaps.extensions.toVisibility
|
||||
|
@ -37,16 +35,18 @@ import info.nightscout.androidaps.interfaces.ProfileStore
|
|||
import info.nightscout.androidaps.interfaces.ResourceHelper
|
||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.general.autotune.data.ATProfile
|
||||
import info.nightscout.androidaps.plugins.general.autotune.events.EventAutotuneUpdateGui
|
||||
import info.nightscout.plugins.profile.ProfilePlugin
|
||||
import info.nightscout.plugins.profile.events.EventLocalProfileChanged
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.MidnightTime
|
||||
import info.nightscout.androidaps.utils.Round
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog.showConfirmation
|
||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||
import info.nightscout.plugins.R
|
||||
import info.nightscout.plugins.databinding.AutotuneFragmentBinding
|
||||
import info.nightscout.plugins.general.autotune.data.ATProfile
|
||||
import info.nightscout.plugins.general.autotune.events.EventAutotuneUpdateGui
|
||||
import info.nightscout.plugins.profile.ProfilePlugin
|
||||
import info.nightscout.plugins.profile.events.EventLocalProfileChanged
|
||||
import info.nightscout.shared.SafeParse
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
|
@ -126,7 +126,7 @@ class AutotuneFragment : DaggerFragment() {
|
|||
updateGui()
|
||||
}
|
||||
|
||||
binding.autotuneCopylocal.setOnClickListener {
|
||||
binding.autotuneCopyLocal.setOnClickListener {
|
||||
val localName = rh.gs(R.string.autotune_tunedprofile_name) + " " + dateUtil.dateAndTimeString(autotunePlugin.lastRun)
|
||||
val circadian = sp.getBoolean(R.string.key_autotune_circadian_ic_isf, false)
|
||||
autotunePlugin.tunedProfile?.let { tunedProfile ->
|
||||
|
@ -265,14 +265,14 @@ class AutotuneFragment : DaggerFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
binding.tuneLastrun.setOnClickListener {
|
||||
binding.tuneLastRun.setOnClickListener {
|
||||
if (!autotunePlugin.calculationRunning) {
|
||||
autotunePlugin.loadLastRun()
|
||||
binding.tuneDays.value = autotunePlugin.lastNbDays.toDouble()
|
||||
updateGui()
|
||||
}
|
||||
}
|
||||
binding.tuneLastrun.paintFlags = binding.tuneLastrun.paintFlags or Paint.UNDERLINE_TEXT_FLAG
|
||||
binding.tuneLastRun.paintFlags = binding.tuneLastRun.paintFlags or Paint.UNDERLINE_TEXT_FLAG
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
|
@ -315,7 +315,7 @@ class AutotuneFragment : DaggerFragment() {
|
|||
}
|
||||
binding.autotuneRun.visibility = View.GONE
|
||||
binding.autotuneCheckInputProfile.visibility = View.GONE
|
||||
binding.autotuneCopylocal.visibility = View.GONE
|
||||
binding.autotuneCopyLocal.visibility = View.GONE
|
||||
binding.autotuneUpdateProfile.visibility = View.GONE
|
||||
binding.autotuneRevertProfile.visibility = View.GONE
|
||||
binding.autotuneProfileswitch.visibility = View.GONE
|
||||
|
@ -326,7 +326,7 @@ class AutotuneFragment : DaggerFragment() {
|
|||
}
|
||||
|
||||
autotunePlugin.lastRunSuccess -> {
|
||||
binding.autotuneCopylocal.visibility = View.VISIBLE
|
||||
binding.autotuneCopyLocal.visibility = View.VISIBLE
|
||||
binding.autotuneUpdateProfile.visibility = autotunePlugin.updateButtonVisibility
|
||||
binding.autotuneRevertProfile.visibility = if (autotunePlugin.updateButtonVisibility == View.VISIBLE) View.GONE else View.VISIBLE
|
||||
binding.autotuneProfileswitch.visibility = View.VISIBLE
|
||||
|
@ -339,7 +339,7 @@ class AutotuneFragment : DaggerFragment() {
|
|||
binding.autotuneCheckInputProfile.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
binding.tuneLastrun.text = dateUtil.dateAndTimeString(autotunePlugin.lastRun)
|
||||
binding.tuneLastRun.text = dateUtil.dateAndTimeString(autotunePlugin.lastRun)
|
||||
showResults()
|
||||
}
|
||||
|
|
@ -1,29 +1,32 @@
|
|||
package info.nightscout.androidaps.plugins.general.autotune
|
||||
package info.nightscout.plugins.general.autotune
|
||||
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.IobTotal
|
||||
import info.nightscout.androidaps.data.LocalInsulin
|
||||
import info.nightscout.androidaps.database.AppRepository
|
||||
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||
import info.nightscout.androidaps.database.entities.*
|
||||
import info.nightscout.androidaps.database.entities.Bolus
|
||||
import info.nightscout.androidaps.database.entities.Carbs
|
||||
import info.nightscout.androidaps.database.entities.ExtendedBolus
|
||||
import info.nightscout.androidaps.database.entities.GlucoseValue
|
||||
import info.nightscout.androidaps.database.entities.TemporaryBasal
|
||||
import info.nightscout.androidaps.database.entities.TherapyEvent
|
||||
import info.nightscout.androidaps.extensions.durationInMinutes
|
||||
import info.nightscout.androidaps.extensions.iobCalc
|
||||
import info.nightscout.androidaps.extensions.toJson
|
||||
import info.nightscout.androidaps.extensions.toTemporaryBasal
|
||||
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||
import info.nightscout.androidaps.interfaces.Profile
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.plugins.general.autotune.data.ATProfile
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.Round
|
||||
import info.nightscout.androidaps.utils.T
|
||||
import info.nightscout.plugins.R
|
||||
import info.nightscout.plugins.general.autotune.data.ATProfile
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.logging.LTag
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlin.math.ceil
|
||||
|
@ -44,7 +47,7 @@ open class AutotuneIob @Inject constructor(
|
|||
lateinit var glucose: List<GlucoseValue> // newest at index 0
|
||||
private lateinit var tempBasals: ArrayList<TemporaryBasal>
|
||||
var startBG: Long = 0
|
||||
var endBG: Long = 0
|
||||
private var endBG: Long = 0
|
||||
private fun range(): Long = (60 * 60 * 1000L * dia + T.hours(2).msecs()).toLong()
|
||||
|
||||
fun initializeData(from: Long, to: Long, tunedProfile: ATProfile) {
|
||||
|
@ -236,11 +239,10 @@ open class AutotuneIob @Inject constructor(
|
|||
}
|
||||
|
||||
open fun getIOB(time: Long, localInsulin: LocalInsulin): IobTotal {
|
||||
val bolusIob = getCalculationToTimeTreatments(time, localInsulin).round()
|
||||
return bolusIob
|
||||
return getCalculationToTimeTreatments(time, localInsulin).round()
|
||||
}
|
||||
|
||||
fun getCalculationToTimeTreatments(time: Long, localInsulin: LocalInsulin): IobTotal {
|
||||
private fun getCalculationToTimeTreatments(time: Long, localInsulin: LocalInsulin): IobTotal {
|
||||
val total = IobTotal(time)
|
||||
val detailedLog = sp.getBoolean(R.string.key_autotune_additional_log, false)
|
||||
for (pos in boluses.indices) {
|
||||
|
@ -257,7 +259,7 @@ open class AutotuneIob @Inject constructor(
|
|||
}
|
||||
|
||||
|
||||
fun convertToBoluses(eb: ExtendedBolus): MutableList<Bolus> {
|
||||
private fun convertToBoluses(eb: ExtendedBolus): MutableList<Bolus> {
|
||||
val result: MutableList<Bolus> = ArrayList()
|
||||
val aboutFiveMinIntervals = ceil(eb.duration / 5.0).toInt()
|
||||
val spacing = eb.duration / aboutFiveMinIntervals.toDouble()
|
||||
|
@ -277,7 +279,7 @@ open class AutotuneIob @Inject constructor(
|
|||
return result
|
||||
}
|
||||
|
||||
fun convertToBoluses(tbr: TemporaryBasal, profile: Profile, tunedProfile: Profile): MutableList<Bolus> {
|
||||
private fun convertToBoluses(tbr: TemporaryBasal, profile: Profile, tunedProfile: Profile): MutableList<Bolus> {
|
||||
val result: MutableList<Bolus> = ArrayList()
|
||||
val realDuration = tbr.durationInMinutes
|
||||
val basalRate = profile.getBasal(tbr.timestamp)
|
|
@ -1,32 +1,41 @@
|
|||
package info.nightscout.androidaps.plugins.general.autotune
|
||||
package info.nightscout.plugins.general.autotune
|
||||
|
||||
import android.view.View
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.LocalInsulin
|
||||
import info.nightscout.androidaps.data.ProfileSealed
|
||||
import info.nightscout.androidaps.database.entities.UserEntry
|
||||
import info.nightscout.androidaps.database.entities.ValueWithUnit
|
||||
import info.nightscout.androidaps.extensions.pureProfileFromJson
|
||||
import info.nightscout.androidaps.interfaces.*
|
||||
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||
import info.nightscout.androidaps.interfaces.Autotune
|
||||
import info.nightscout.androidaps.interfaces.BuildHelper
|
||||
import info.nightscout.androidaps.interfaces.Insulin
|
||||
import info.nightscout.androidaps.interfaces.PluginBase
|
||||
import info.nightscout.androidaps.interfaces.PluginDescription
|
||||
import info.nightscout.androidaps.interfaces.PluginType
|
||||
import info.nightscout.androidaps.interfaces.Profile
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.interfaces.ProfileStore
|
||||
import info.nightscout.androidaps.interfaces.ResourceHelper
|
||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.general.autotune.data.ATProfile
|
||||
import info.nightscout.androidaps.plugins.general.autotune.data.PreppedGlucose
|
||||
import info.nightscout.androidaps.plugins.general.autotune.events.EventAutotuneUpdateGui
|
||||
import info.nightscout.plugins.profile.ProfilePlugin
|
||||
import info.nightscout.plugins.profile.events.EventLocalProfileChanged
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.JsonHelper
|
||||
import info.nightscout.androidaps.utils.MidnightTime
|
||||
import info.nightscout.androidaps.utils.T
|
||||
import info.nightscout.androidaps.interfaces.BuildHelper
|
||||
import info.nightscout.plugins.R
|
||||
import info.nightscout.plugins.general.autotune.data.ATProfile
|
||||
import info.nightscout.plugins.general.autotune.data.PreppedGlucose
|
||||
import info.nightscout.plugins.general.autotune.events.EventAutotuneUpdateGui
|
||||
import info.nightscout.plugins.profile.ProfilePlugin
|
||||
import info.nightscout.plugins.profile.events.EventLocalProfileChanged
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.logging.LTag
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
import java.util.TimeZone
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
|
@ -54,17 +63,19 @@ class AutotunePlugin @Inject constructor(
|
|||
private val buildHelper: BuildHelper,
|
||||
private val uel: UserEntryLogger,
|
||||
aapsLogger: AAPSLogger
|
||||
) : PluginBase(PluginDescription()
|
||||
.mainType(PluginType.GENERAL)
|
||||
.fragmentClass(AutotuneFragment::class.qualifiedName)
|
||||
.pluginIcon(R.drawable.ic_autotune)
|
||||
.pluginName(R.string.autotune)
|
||||
.shortName(R.string.autotune_shortname)
|
||||
.preferencesId(R.xml.pref_autotune)
|
||||
.showInList(buildHelper.isEngineeringMode() && buildHelper.isDev())
|
||||
.description(R.string.autotune_description),
|
||||
) : PluginBase(
|
||||
PluginDescription()
|
||||
.mainType(PluginType.GENERAL)
|
||||
.fragmentClass(AutotuneFragment::class.qualifiedName)
|
||||
.pluginIcon(R.drawable.ic_autotune)
|
||||
.pluginName(R.string.autotune)
|
||||
.shortName(R.string.autotune_shortname)
|
||||
.preferencesId(R.xml.pref_autotune)
|
||||
.showInList(buildHelper.isEngineeringMode() && buildHelper.isDev())
|
||||
.description(R.string.autotune_description),
|
||||
aapsLogger, resourceHelper, injector
|
||||
), Autotune {
|
||||
|
||||
@Volatile override var lastRunSuccess: Boolean = false
|
||||
@Volatile var result: String = ""
|
||||
@Volatile override var calculationRunning: Boolean = false
|
||||
|
@ -106,7 +117,7 @@ class AutotunePlugin @Inject constructor(
|
|||
calculationRunning = false
|
||||
return
|
||||
}
|
||||
selectedProfile = if (profileToTune.isEmpty()) profileFunction.getProfileName() else profileToTune
|
||||
selectedProfile = profileToTune.ifEmpty { profileFunction.getProfileName() }
|
||||
profileFunction.getProfile()?.let { currentProfile ->
|
||||
profile = profileStore.getSpecificProfile(profileToTune)?.let { ProfileSealed.Pure(it) } ?: currentProfile
|
||||
}
|
||||
|
@ -132,7 +143,7 @@ class AutotunePlugin @Inject constructor(
|
|||
val from = starttime + i * 24 * 60 * 60 * 1000L // get 24 hours BG values from 4 AM to 4 AM next day
|
||||
val to = from + 24 * 60 * 60 * 1000L
|
||||
log("Tune day " + (i + 1) + " of " + daysBack)
|
||||
tunedProfile?.let { it ->
|
||||
tunedProfile?.let {
|
||||
autotuneIob.initializeData(from, to, it) //autotuneIob contains BG and Treatments data from history (<=> query for ns-treatments and ns-entries)
|
||||
if (autotuneIob.boluses.size == 0) {
|
||||
result = rh.gs(R.string.autotune_error)
|
||||
|
@ -209,7 +220,8 @@ class AutotunePlugin @Inject constructor(
|
|||
UserEntry.Action.PROFILE_SWITCH,
|
||||
UserEntry.Sources.Automation,
|
||||
rh.gs(R.string.autotune),
|
||||
ValueWithUnit.SimpleString(tunedP.profilename))
|
||||
ValueWithUnit.SimpleString(tunedP.profilename)
|
||||
)
|
||||
}
|
||||
rxBus.send(EventLocalProfileChanged())
|
||||
}
|
||||
|
@ -265,8 +277,8 @@ class AutotunePlugin @Inject constructor(
|
|||
val jsonSettings = JSONObject()
|
||||
val insulinInterface = activePlugin.activeInsulin
|
||||
val utcOffset = T.msecs(TimeZone.getDefault().getOffset(dateUtil.now()).toLong()).hours()
|
||||
val startDateString = dateUtil.toISOString(firstloopstart).substring(0,10)
|
||||
val endDateString = dateUtil.toISOString(lastloopend - 24 * 60 * 60 * 1000L).substring(0,10)
|
||||
val startDateString = dateUtil.toISOString(firstloopstart).substring(0, 10)
|
||||
val endDateString = dateUtil.toISOString(lastloopend - 24 * 60 * 60 * 1000L).substring(0, 10)
|
||||
val nsUrl = sp.getString(R.string.key_nsclientinternal_url, "")
|
||||
val optCategorizeUam = if (sp.getBoolean(R.string.key_autotune_categorize_uam_as_basal, false)) "-c=true" else ""
|
||||
val optInsulinCurve = if (sp.getBoolean(R.string.key_autotune_tune_insulin_curve, false)) "-i=true" else ""
|
||||
|
@ -291,7 +303,7 @@ class AutotunePlugin @Inject constructor(
|
|||
|
||||
val peaktime: Int = insulinInterface.peak
|
||||
if (insulinInterface.id === Insulin.InsulinType.OREF_ULTRA_RAPID_ACTING)
|
||||
jsonSettings.put("curve","ultra-rapid")
|
||||
jsonSettings.put("curve", "ultra-rapid")
|
||||
else if (insulinInterface.id === Insulin.InsulinType.OREF_RAPID_ACTING)
|
||||
jsonSettings.put("curve", "rapid-acting")
|
||||
else if (insulinInterface.id === Insulin.InsulinType.OREF_LYUMJEV) {
|
||||
|
@ -304,7 +316,9 @@ class AutotunePlugin @Inject constructor(
|
|||
jsonSettings.put("insulinPeakTime", peaktime)
|
||||
}
|
||||
jsonString = jsonSettings.toString(4).replace("\\/", "/")
|
||||
} catch (e: JSONException) { }
|
||||
} catch (e: JSONException) {
|
||||
aapsLogger.error(LTag.AUTOTUNE, e.localizedMessage ?: e.toString())
|
||||
}
|
||||
return jsonString
|
||||
}
|
||||
|
||||
|
@ -332,7 +346,7 @@ class AutotunePlugin @Inject constructor(
|
|||
fun saveLastRun() {
|
||||
val json = JSONObject()
|
||||
json.put("lastNbDays", lastNbDays)
|
||||
json.put("lastRun",lastRun)
|
||||
json.put("lastRun", lastRun)
|
||||
json.put("pumpProfile", pumpProfile.profile.toPureNsJson(dateUtil))
|
||||
json.put("pumpProfileName", pumpProfile.profilename)
|
||||
json.put("pumpPeak", pumpProfile.peak)
|
||||
|
@ -378,13 +392,14 @@ class AutotunePlugin @Inject constructor(
|
|||
atProfile.profilename = tunedProfileName
|
||||
atProfile.circadianProfile = ProfileSealed.Pure(circadianTuned)
|
||||
for (i in 0..23) {
|
||||
atProfile.basalUntuned[i] = JsonHelper.safeGetInt(json,"missingDays_$i")
|
||||
atProfile.basalUntuned[i] = JsonHelper.safeGetInt(json, "missingDays_$i")
|
||||
}
|
||||
}
|
||||
result = JsonHelper.safeGetString(json, "result", "")
|
||||
updateButtonVisibility = JsonHelper.safeGetInt(json, "updateButtonVisibility")
|
||||
lastRunSuccess = true
|
||||
} catch (e: Exception) {
|
||||
aapsLogger.error(LTag.AUTOTUNE, e.localizedMessage ?: e.toString())
|
||||
}
|
||||
}
|
||||
|
|
@ -1,66 +1,71 @@
|
|||
package info.nightscout.androidaps.plugins.general.autotune
|
||||
package info.nightscout.plugins.general.autotune
|
||||
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.LocalInsulin
|
||||
import info.nightscout.androidaps.database.entities.GlucoseValue
|
||||
import info.nightscout.androidaps.plugins.general.autotune.data.*
|
||||
import info.nightscout.androidaps.database.entities.Bolus
|
||||
import info.nightscout.androidaps.database.entities.Carbs
|
||||
import info.nightscout.androidaps.database.entities.GlucoseValue
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.MidnightTime
|
||||
import info.nightscout.androidaps.utils.Round
|
||||
import info.nightscout.androidaps.utils.T
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.logging.LTag
|
||||
import info.nightscout.plugins.R
|
||||
import info.nightscout.plugins.general.autotune.data.ATProfile
|
||||
import info.nightscout.plugins.general.autotune.data.BGDatum
|
||||
import info.nightscout.plugins.general.autotune.data.CRDatum
|
||||
import info.nightscout.plugins.general.autotune.data.DiaDeviation
|
||||
import info.nightscout.plugins.general.autotune.data.PeakDeviation
|
||||
import info.nightscout.plugins.general.autotune.data.PreppedGlucose
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@Singleton
|
||||
class AutotunePrep @Inject constructor(
|
||||
private val aapsLogger: AAPSLogger,
|
||||
private val sp: SP,
|
||||
private val dateUtil: DateUtil,
|
||||
private val autotuneFS: AutotuneFS,
|
||||
private val autotuneIob: AutotuneIob
|
||||
) {
|
||||
fun categorize(tunedprofile: ATProfile): PreppedGlucose? {
|
||||
val preppedGlucose = categorizeBGDatums(tunedprofile, tunedprofile.localInsulin)
|
||||
|
||||
fun categorize(tunedProfile: ATProfile): PreppedGlucose? {
|
||||
val preppedGlucose = categorizeBGDatums(tunedProfile, tunedProfile.localInsulin)
|
||||
val tuneInsulin = sp.getBoolean(R.string.key_autotune_tune_insulin_curve, false)
|
||||
if (tuneInsulin) {
|
||||
var minDeviations = 1000000.0
|
||||
val diaDeviations: MutableList<DiaDeviation> = ArrayList()
|
||||
val peakDeviations: MutableList<PeakDeviation> = ArrayList()
|
||||
val currentDIA = tunedprofile.localInsulin.dia
|
||||
val currentPeak = tunedprofile.localInsulin.peak
|
||||
val currentDIA = tunedProfile.localInsulin.dia
|
||||
val currentPeak = tunedProfile.localInsulin.peak
|
||||
|
||||
var dia = currentDIA - 2
|
||||
val endDIA = currentDIA + 2
|
||||
while (dia <= endDIA)
|
||||
{
|
||||
while (dia <= endDIA) {
|
||||
var sqrtDeviations = 0.0
|
||||
var deviations = 0.0
|
||||
var deviationsSq = 0.0
|
||||
val localInsulin = LocalInsulin("Ins_$currentPeak-$dia", currentPeak, dia)
|
||||
val curve_output = categorizeBGDatums(tunedprofile, localInsulin, false)
|
||||
val basalGlucose = curve_output?.basalGlucoseData
|
||||
val curveOutput = categorizeBGDatums(tunedProfile, localInsulin, false)
|
||||
val basalGlucose = curveOutput?.basalGlucoseData
|
||||
|
||||
basalGlucose?.let {
|
||||
for (hour in 0..23) {
|
||||
for (i in 0..(basalGlucose.size-1)) {
|
||||
for (i in basalGlucose.indices) {
|
||||
val myHour = ((basalGlucose[i].date - MidnightTime.calc(basalGlucose[i].date)) / T.hours(1).msecs()).toInt()
|
||||
if (hour == myHour) {
|
||||
sqrtDeviations += Math.pow(Math.abs(basalGlucose[i].deviation), 0.5)
|
||||
deviations += Math.abs(basalGlucose[i].deviation)
|
||||
deviationsSq += Math.pow(basalGlucose[i].deviation, 2.0)
|
||||
sqrtDeviations += abs(basalGlucose[i].deviation).pow(0.5)
|
||||
deviations += abs(basalGlucose[i].deviation)
|
||||
deviationsSq += basalGlucose[i].deviation.pow(2.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val meanDeviation = Round.roundTo(Math.abs(deviations / basalGlucose.size), 0.001)
|
||||
val smrDeviation = Round.roundTo(Math.pow(sqrtDeviations / basalGlucose.size, 2.0), 0.001)
|
||||
val rmsDeviation = Round.roundTo(Math.pow(deviationsSq / basalGlucose.size, 0.5), 0.001)
|
||||
val meanDeviation = Round.roundTo(abs(deviations / basalGlucose.size), 0.001)
|
||||
val smrDeviation = Round.roundTo((sqrtDeviations / basalGlucose.size).pow(2.0), 0.001)
|
||||
val rmsDeviation = Round.roundTo((deviationsSq / basalGlucose.size).pow(0.5), 0.001)
|
||||
log("insulinEndTime $dia meanDeviation: $meanDeviation SMRDeviation: $smrDeviation RMSDeviation: $rmsDeviation (mg/dL)")
|
||||
diaDeviations.add(
|
||||
DiaDeviation(
|
||||
|
@ -85,31 +90,30 @@ class AutotunePrep @Inject constructor(
|
|||
minDeviations = 1000000.0
|
||||
var peak = currentPeak - 10
|
||||
val endPeak = currentPeak + 10
|
||||
while (peak <= endPeak)
|
||||
{
|
||||
while (peak <= endPeak) {
|
||||
var sqrtDeviations = 0.0
|
||||
var deviations = 0.0
|
||||
var deviationsSq = 0.0
|
||||
val localInsulin = LocalInsulin("Ins_$peak-$currentDIA", peak, currentDIA)
|
||||
val curve_output = categorizeBGDatums(tunedprofile, localInsulin, false)
|
||||
val basalGlucose = curve_output?.basalGlucoseData
|
||||
val curveOutput = categorizeBGDatums(tunedProfile, localInsulin, false)
|
||||
val basalGlucose = curveOutput?.basalGlucoseData
|
||||
|
||||
basalGlucose?.let {
|
||||
for (hour in 0..23) {
|
||||
for (i in 0..(basalGlucose.size - 1)) {
|
||||
for (i in basalGlucose.indices) {
|
||||
val myHour = ((basalGlucose[i].date - MidnightTime.calc(basalGlucose[i].date)) / T.hours(1).msecs()).toInt()
|
||||
if (hour == myHour) {
|
||||
//console.error(basalGlucose[i].deviation);
|
||||
sqrtDeviations += Math.pow(Math.abs(basalGlucose[i].deviation), 0.5)
|
||||
deviations += Math.abs(basalGlucose[i].deviation)
|
||||
deviationsSq += Math.pow(basalGlucose[i].deviation, 2.0)
|
||||
sqrtDeviations += abs(basalGlucose[i].deviation).pow(0.5)
|
||||
deviations += abs(basalGlucose[i].deviation)
|
||||
deviationsSq += basalGlucose[i].deviation.pow(2.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val meanDeviation = Round.roundTo(deviations / basalGlucose.size, 0.001)
|
||||
val smrDeviation = Round.roundTo(Math.pow(sqrtDeviations / basalGlucose.size, 2.0), 0.001)
|
||||
val rmsDeviation = Round.roundTo(Math.pow(deviationsSq / basalGlucose.size, 0.5), 0.001)
|
||||
val smrDeviation = Round.roundTo((sqrtDeviations / basalGlucose.size).pow(2.0), 0.001)
|
||||
val rmsDeviation = Round.roundTo((deviationsSq / basalGlucose.size).pow(0.5), 0.001)
|
||||
log("insulinPeakTime $peak meanDeviation: $meanDeviation SMRDeviation: $smrDeviation RMSDeviation: $rmsDeviation (mg/dL)")
|
||||
peakDeviations.add(
|
||||
PeakDeviation
|
||||
|
@ -122,7 +126,7 @@ class AutotunePrep @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
deviations = Round.roundTo(deviations, 0.001);
|
||||
deviations = Round.roundTo(deviations, 0.001)
|
||||
if (deviations < minDeviations)
|
||||
minDeviations = Round.roundTo(deviations, 0.001)
|
||||
peak += 5
|
||||
|
@ -136,7 +140,7 @@ class AutotunePrep @Inject constructor(
|
|||
}
|
||||
|
||||
// private static Logger log = LoggerFactory.getLogger(AutotunePlugin.class);
|
||||
fun categorizeBGDatums(tunedprofile: ATProfile, localInsulin: LocalInsulin, verbose: Boolean = true): PreppedGlucose? {
|
||||
fun categorizeBGDatums(tunedProfile: ATProfile, localInsulin: LocalInsulin, verbose: Boolean = true): PreppedGlucose? {
|
||||
//lib/meals is called before to get only meals data (in AAPS it's done in AutotuneIob)
|
||||
val treatments: MutableList<Carbs> = autotuneIob.meals
|
||||
val boluses: MutableList<Bolus> = autotuneIob.boluses
|
||||
|
@ -148,14 +152,14 @@ class AutotunePrep @Inject constructor(
|
|||
glucoseData.add(glucose[i])
|
||||
}
|
||||
}
|
||||
if (glucose.size == 0 || glucoseData.size == 0 ) {
|
||||
if (glucose.isEmpty() || glucoseData.size == 0) {
|
||||
//aapsLogger.debug(LTag.AUTOTUNE, "No BG value received")
|
||||
if (verbose)
|
||||
log("No BG value received")
|
||||
return null
|
||||
}
|
||||
|
||||
glucoseData.sortWith(object: Comparator<GlucoseValue>{ override fun compare(o1: GlucoseValue, o2: GlucoseValue): Int = (o2.timestamp - o1.timestamp).toInt() })
|
||||
glucoseData.sortWith { o1, o2 -> (o2.timestamp - o1.timestamp).toInt() }
|
||||
|
||||
// Bloc below replace bloc between #55 and #71
|
||||
// boluses and maxCarbs not used here ?,
|
||||
|
@ -189,10 +193,10 @@ class AutotunePrep @Inject constructor(
|
|||
var k = 0 // index of first value used by bucket
|
||||
//for loop to validate and bucket the data
|
||||
for (i in 1 until glucoseData.size) {
|
||||
val BGTime = glucoseData[i].timestamp
|
||||
val bgTime = glucoseData[i].timestamp
|
||||
val lastBGTime = glucoseData[k].timestamp
|
||||
val elapsedMinutes = (BGTime - lastBGTime) / (60 * 1000)
|
||||
if (Math.abs(elapsedMinutes) >= 2) {
|
||||
val elapsedMinutes = (bgTime - lastBGTime) / (60 * 1000)
|
||||
if (abs(elapsedMinutes) >= 2) {
|
||||
//j++; // move to next bucket
|
||||
k = i // store index of first value used by bucket
|
||||
bucketedData.add(BGDatum(glucoseData[i], dateUtil))
|
||||
|
@ -229,14 +233,14 @@ class AutotunePrep @Inject constructor(
|
|||
for (i in bucketedData.size - 5 downTo 1) {
|
||||
val glucoseDatum = bucketedData[i]
|
||||
//log.debug(glucoseDatum);
|
||||
val BGTime = glucoseDatum.date
|
||||
val bgTime = glucoseDatum.date
|
||||
|
||||
// As we're processing each data point, go through the treatment.carbs and see if any of them are older than
|
||||
// the current BG data point. If so, add those carbs to COB.
|
||||
val treatment = if (treatments.size > 0) treatments[treatments.size - 1] else null
|
||||
var myCarbs = 0.0
|
||||
if (treatment != null) {
|
||||
if (treatment.timestamp < BGTime) {
|
||||
if (treatment.timestamp < bgTime) {
|
||||
if (treatment.amount > 0.0) {
|
||||
mealCOB += treatment.amount
|
||||
mealCarbs += treatment.amount
|
||||
|
@ -267,7 +271,7 @@ class AutotunePrep @Inject constructor(
|
|||
glucoseDatum.avgDelta = avgDelta
|
||||
|
||||
//sens = ISF
|
||||
val sens = tunedprofile.isf
|
||||
val sens = tunedProfile.isf
|
||||
|
||||
// for IOB calculations, use the average of the last 4 hours' basals to help convergence;
|
||||
// this helps since the basal this hour could be different from previous, especially if with autotune they start to diverge.
|
||||
|
@ -280,7 +284,7 @@ class AutotunePrep @Inject constructor(
|
|||
currentPumpBasal = Round.roundTo(currentPumpBasal / 4, 0.001) //CurrentPumpBasal for iob calculation is average of 4 last pumpProfile Basal rate
|
||||
*/
|
||||
// this is the current autotuned basal, used for everything else besides IOB calculations
|
||||
val currentBasal = tunedprofile.getBasal(BGTime)
|
||||
val currentBasal = tunedProfile.getBasal(bgTime)
|
||||
|
||||
// basalBGI is BGI of basal insulin activity.
|
||||
val basalBGI = Round.roundTo(currentBasal * sens / 60 * 5, 0.01) // U/hr * mg/dL/U * 1 hr / 60 minutes * 5 = mg/dL/5m
|
||||
|
@ -289,14 +293,14 @@ class AutotunePrep @Inject constructor(
|
|||
//var iob = getIOB(IOBInputs)[0];
|
||||
// in autotune iob is calculated with 6 hours of history data, tunedProfile and average pumpProfile basal rate...
|
||||
//log("currentBasal: " + currentBasal + " BGTime: " + BGTime + " / " + dateUtil!!.timeStringWithSeconds(BGTime) + "******************************************************************************************")
|
||||
val iob = autotuneIob.getIOB(BGTime, localInsulin) // add localInsulin to be independent to InsulinPlugin
|
||||
val iob = autotuneIob.getIOB(bgTime, localInsulin) // add localInsulin to be independent to InsulinPlugin
|
||||
|
||||
// activity times ISF times 5 minutes is BGI
|
||||
val BGI = Round.roundTo(-iob.activity * sens * 5, 0.01)
|
||||
val bgi = Round.roundTo(-iob.activity * sens * 5, 0.01)
|
||||
// datum = one glucose data point (being prepped to store in output)
|
||||
glucoseDatum.bgi = BGI
|
||||
glucoseDatum.bgi = bgi
|
||||
// calculating deviation
|
||||
var deviation = avgDelta - BGI
|
||||
var deviation = avgDelta - bgi
|
||||
|
||||
// set positive deviations to zero if BG is below 80
|
||||
if (bg < 80 && deviation > 0) {
|
||||
|
@ -309,10 +313,10 @@ class AutotunePrep @Inject constructor(
|
|||
|
||||
// Then, calculate carb absorption for that 5m interval using the deviation.
|
||||
if (mealCOB > 0) {
|
||||
val ci = Math.max(deviation, sp.getDouble(R.string.key_openapsama_min_5m_carbimpact, 3.0))
|
||||
val absorbed = ci * tunedprofile.ic / sens
|
||||
val ci = max(deviation, sp.getDouble(R.string.key_openapsama_min_5m_carbimpact, 3.0))
|
||||
val absorbed = ci * tunedProfile.ic / sens
|
||||
// Store the COB, and use it as the starting point for the next data point.
|
||||
mealCOB = Math.max(0.0, mealCOB - absorbed)
|
||||
mealCOB = max(0.0, mealCOB - absorbed)
|
||||
}
|
||||
|
||||
// Calculate carb ratio (CR) independently of CSF and ISF
|
||||
|
@ -323,7 +327,7 @@ class AutotunePrep @Inject constructor(
|
|||
if (mealCOB > 0 || calculatingCR) {
|
||||
// set initial values when we first see COB
|
||||
crCarbs += myCarbs
|
||||
if (calculatingCR == false) {
|
||||
if (!calculatingCR) {
|
||||
crInitialIOB = iob.iob
|
||||
crInitialBG = glucoseDatum.value
|
||||
crInitialCarbTime = glucoseDatum.date
|
||||
|
@ -354,13 +358,13 @@ class AutotunePrep @Inject constructor(
|
|||
crDatum.crCarbs = crCarbs
|
||||
//log.debug(CRDatum);
|
||||
//String crDataString = "{\"CRInitialIOB\": " + CRInitialIOB + ", \"CRInitialBG\": " + CRInitialBG + ", \"CRInitialCarbTime\": " + CRInitialCarbTime + ", \"CREndIOB\": " + CREndIOB + ", \"CREndBG\": " + CREndBG + ", \"CREndTime\": " + CREndTime + ", \"CRCarbs\": " + CRCarbs + "}";
|
||||
val CRElapsedMinutes = Math.round((crEndTime - crInitialCarbTime) / (1000 * 60).toFloat())
|
||||
val crElapsedMinutes = ((crEndTime - crInitialCarbTime) / (1000 * 60).toFloat()).roundToInt()
|
||||
|
||||
//log.debug(CREndTime - CRInitialCarbTime, CRElapsedMinutes);
|
||||
if (CRElapsedMinutes < 60 || i == 1 && mealCOB > 0) {
|
||||
if (crElapsedMinutes < 60 || i == 1 && mealCOB > 0) {
|
||||
//aapsLogger.debug(LTag.AUTOTUNE, "Ignoring $CRElapsedMinutes m CR period.")
|
||||
if (verbose)
|
||||
log("Ignoring $CRElapsedMinutes m CR period.")
|
||||
log("Ignoring $crElapsedMinutes m CR period.")
|
||||
} else {
|
||||
crData.add(crDatum)
|
||||
}
|
||||
|
@ -376,11 +380,7 @@ class AutotunePrep @Inject constructor(
|
|||
absorbing = if (iob.iob < currentBasal / 2) {
|
||||
false
|
||||
// otherwise, as long as deviations are positive, keep tracking carb deviations
|
||||
} else if (deviation > 0) {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else deviation > 0
|
||||
if (!absorbing && mealCOB == 0.0) {
|
||||
mealCarbs = 0.0
|
||||
}
|
||||
|
@ -405,11 +405,7 @@ class AutotunePrep @Inject constructor(
|
|||
log("${csfGlucoseData[csfGlucoseData.size - 1].mealAbsorption} carb absorption")
|
||||
}
|
||||
if (iob.iob > 2 * currentBasal || deviation > 6 || uam) {
|
||||
uam = if (deviation > 0) {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
uam = deviation > 0
|
||||
if (type != "uam") {
|
||||
glucoseDatum.uamAbsorption = "start"
|
||||
//aapsLogger.debug(LTag.AUTOTUNE, "${glucoseDatum.uamAbsorption} unannnounced meal absorption")
|
||||
|
@ -431,11 +427,11 @@ class AutotunePrep @Inject constructor(
|
|||
// When BGI is smaller than about 1/4 of basalBGI, we want to use that data to tune basals
|
||||
// When BGI is negative and more than about 1/4 of basalBGI, we can use that data to tune ISF,
|
||||
// unless avgDelta is positive: then that's some sort of unexplained rise we don't want to use for ISF, so that means basals
|
||||
if (basalBGI > -4 * BGI) {
|
||||
if (basalBGI > -4 * bgi) {
|
||||
type = "basal"
|
||||
basalGlucoseData.add(glucoseDatum)
|
||||
} else {
|
||||
if (avgDelta > 0 && avgDelta > -2 * BGI) {
|
||||
if (avgDelta > 0 && avgDelta > -2 * bgi) {
|
||||
//type="unknown"
|
||||
type = "basal"
|
||||
basalGlucoseData.add(glucoseDatum)
|
||||
|
@ -449,8 +445,12 @@ class AutotunePrep @Inject constructor(
|
|||
// debug line to print out all the things
|
||||
//aapsLogger.debug(LTag.AUTOTUNE, "${(if (absorbing) 1 else 0)} mealCOB: ${Round.roundTo(mealCOB, 0.1)} mealCarbs: ${Math.round(mealCarbs)} basalBGI: ${Round.roundTo(basalBGI, 0.1)} BGI: ${Round.roundTo(BGI, 0.1)} IOB: ${iob.iob} Activity: ${iob.activity} at ${dateUtil.timeStringWithSeconds(BGTime)} dev: $deviation avgDelta: $avgDelta $type")
|
||||
if (verbose)
|
||||
log("${(if (absorbing) 1 else 0)} mealCOB: ${Round.roundTo(mealCOB, 0.1)} mealCarbs: ${Math.round(mealCarbs)} basalBGI: ${Round.roundTo(basalBGI, 0.1)} BGI: ${Round
|
||||
.roundTo(BGI, 0.1)} IOB: ${iob.iob} Activity: ${iob.activity} at ${dateUtil.timeStringWithSeconds(BGTime)} dev: $deviation avgDelta: $avgDelta $type")
|
||||
log(
|
||||
"${(if (absorbing) 1 else 0)} mealCOB: ${Round.roundTo(mealCOB, 0.1)} mealCarbs: ${mealCarbs.roundToInt()} basalBGI: ${Round.roundTo(basalBGI, 0.1)} BGI: ${
|
||||
Round
|
||||
.roundTo(bgi, 0.1)
|
||||
} IOB: ${iob.iob} Activity: ${iob.activity} at ${dateUtil.timeStringWithSeconds(bgTime)} dev: $deviation avgDelta: $avgDelta $type"
|
||||
)
|
||||
}
|
||||
|
||||
//****************************************************************************************************************************************
|
||||
|
@ -460,33 +460,33 @@ class AutotunePrep @Inject constructor(
|
|||
crDatum.crInsulin = dosed(crDatum.crInitialCarbTime, crDatum.crEndTime, boluses)
|
||||
}
|
||||
// categorize.js Lines 384-436
|
||||
val CSFLength = csfGlucoseData.size
|
||||
var ISFLength = isfGlucoseData.size
|
||||
val UAMLength = uamGlucoseData.size
|
||||
val csfLength = csfGlucoseData.size
|
||||
var isfLength = isfGlucoseData.size
|
||||
val uamLength = uamGlucoseData.size
|
||||
var basalLength = basalGlucoseData.size
|
||||
if (sp.getBoolean(R.string.key_autotune_categorize_uam_as_basal, false)) {
|
||||
//aapsLogger.debug(LTag.AUTOTUNE, "Categorizing all UAM data as basal.")
|
||||
if (verbose)
|
||||
log("Categorizing all UAM data as basal.")
|
||||
basalGlucoseData.addAll(uamGlucoseData)
|
||||
} else if (CSFLength > 12) {
|
||||
} else if (csfLength > 12) {
|
||||
//aapsLogger.debug(LTag.AUTOTUNE, "Found at least 1h of carb: assuming meals were announced, and categorizing UAM data as basal.")
|
||||
if (verbose)
|
||||
log("Found at least 1h of carb: assuming meals were announced, and categorizing UAM data as basal.")
|
||||
basalGlucoseData.addAll(uamGlucoseData)
|
||||
} else {
|
||||
if (2 * basalLength < UAMLength) {
|
||||
if (2 * basalLength < uamLength) {
|
||||
//log.debug(basalGlucoseData, UAMGlucoseData);
|
||||
//aapsLogger.debug(LTag.AUTOTUNE, "Warning: too many deviations categorized as UnAnnounced Meals")
|
||||
//aapsLogger.debug(LTag.AUTOTUNE, "Adding $UAMLength UAM deviations to $basalLength basal ones")
|
||||
if (verbose) {
|
||||
log("Warning: too many deviations categorized as UnAnnounced Meals")
|
||||
log("Adding $UAMLength UAM deviations to $basalLength basal ones")
|
||||
log("Adding $uamLength UAM deviations to $basalLength basal ones")
|
||||
}
|
||||
basalGlucoseData.addAll(uamGlucoseData)
|
||||
//log.debug(basalGlucoseData);
|
||||
// if too much data is excluded as UAM, add in the UAM deviations, but then discard the highest 50%
|
||||
basalGlucoseData.sortWith(object: Comparator<BGDatum>{ override fun compare(o1: BGDatum, o2: BGDatum): Int = (100 * o1.deviation - 100 * o2.deviation).toInt() }) //deviation rouded to 0.01, so *100 to avoid crash during sort
|
||||
basalGlucoseData.sortWith { o1, o2 -> (100 * o1.deviation - 100 * o2.deviation).toInt() } //deviation rouded to 0.01, so *100 to avoid crash during sort
|
||||
val newBasalGlucose: MutableList<BGDatum> = ArrayList()
|
||||
for (i in 0 until basalGlucoseData.size / 2) {
|
||||
newBasalGlucose.add(basalGlucoseData[i])
|
||||
|
@ -497,13 +497,13 @@ class AutotunePrep @Inject constructor(
|
|||
if (verbose)
|
||||
log("and selecting the lowest 50%, leaving ${basalGlucoseData.size} basal+UAM ones")
|
||||
}
|
||||
if (2 * ISFLength < UAMLength) {
|
||||
if (2 * isfLength < uamLength) {
|
||||
//aapsLogger.debug(LTag.AUTOTUNE, "Adding $UAMLength UAM deviations to $ISFLength ISF ones")
|
||||
if (verbose)
|
||||
log("Adding $UAMLength UAM deviations to $ISFLength ISF ones")
|
||||
log("Adding $uamLength UAM deviations to $isfLength ISF ones")
|
||||
isfGlucoseData.addAll(uamGlucoseData)
|
||||
// if too much data is excluded as UAM, add in the UAM deviations to ISF, but then discard the highest 50%
|
||||
isfGlucoseData.sortWith(object: Comparator<BGDatum>{ override fun compare(o1: BGDatum, o2: BGDatum): Int = (100 * o1.deviation - 100 * o2.deviation).toInt() }) //deviation rouded to 0.01, so *100 to avoid crash during sort
|
||||
isfGlucoseData.sortWith { o1, o2 -> (100 * o1.deviation - 100 * o2.deviation).toInt() } //deviation rouded to 0.01, so *100 to avoid crash during sort
|
||||
val newISFGlucose: MutableList<BGDatum> = ArrayList()
|
||||
for (i in 0 until isfGlucoseData.size / 2) {
|
||||
newISFGlucose.add(isfGlucoseData[i])
|
||||
|
@ -517,15 +517,15 @@ class AutotunePrep @Inject constructor(
|
|||
}
|
||||
}
|
||||
basalLength = basalGlucoseData.size
|
||||
ISFLength = isfGlucoseData.size
|
||||
if (4 * basalLength + ISFLength < CSFLength && ISFLength < 10) {
|
||||
isfLength = isfGlucoseData.size
|
||||
if (4 * basalLength + isfLength < csfLength && isfLength < 10) {
|
||||
//aapsLogger.debug(LTag.AUTOTUNE, "Warning: too many deviations categorized as meals")
|
||||
//aapsLogger.debug(LTag.AUTOTUNE, "Adding $CSFLength CSF deviations to $ISFLength ISF ones")
|
||||
if (verbose) {
|
||||
log("Warning: too many deviations categorized as meals")
|
||||
//log.debug("Adding",CSFLength,"CSF deviations to",basalLength,"basal ones");
|
||||
//var basalGlucoseData = basalGlucoseData.concat(CSFGlucoseData);
|
||||
log("Adding $CSFLength CSF deviations to $ISFLength ISF ones")
|
||||
log("Adding $csfLength CSF deviations to $isfLength ISF ones")
|
||||
}
|
||||
isfGlucoseData.addAll(csfGlucoseData)
|
||||
csfGlucoseData = ArrayList()
|
||||
|
@ -543,7 +543,7 @@ class AutotunePrep @Inject constructor(
|
|||
private fun dosed(start: Long, end: Long, treatments: List<Bolus>): Double {
|
||||
var insulinDosed = 0.0
|
||||
//aapsLogger.debug(LTag.AUTOTUNE, "No treatments to process.")
|
||||
if (treatments.size == 0) {
|
||||
if (treatments.isEmpty()) {
|
||||
log("No treatments to process.")
|
||||
return 0.0
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.general.autotune.data
|
||||
package info.nightscout.plugins.general.autotune.data
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.core.R
|
||||
|
@ -8,7 +8,14 @@ import info.nightscout.androidaps.data.PureProfile
|
|||
import info.nightscout.androidaps.database.data.Block
|
||||
import info.nightscout.androidaps.extensions.blockValueBySeconds
|
||||
import info.nightscout.androidaps.extensions.pureProfileFromJson
|
||||
import info.nightscout.androidaps.interfaces.*
|
||||
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||
import info.nightscout.androidaps.interfaces.Config
|
||||
import info.nightscout.androidaps.interfaces.GlucoseUnit
|
||||
import info.nightscout.androidaps.interfaces.Insulin
|
||||
import info.nightscout.androidaps.interfaces.Profile
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.interfaces.ProfileStore
|
||||
import info.nightscout.androidaps.interfaces.ResourceHelper
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.Round
|
||||
|
@ -19,7 +26,7 @@ import org.json.JSONArray
|
|||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import java.util.TimeZone
|
||||
import javax.inject.Inject
|
||||
|
||||
class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector: HasAndroidInjector) {
|
||||
|
@ -56,18 +63,19 @@ class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector:
|
|||
val avgIC: Double
|
||||
get() = if (profile.getIcsValues().size == 1) profile.getIcsValues().get(0).value else Round.roundTo(averageProfileValue(profile.getIcsValues()), 0.01)
|
||||
|
||||
fun getBasal(timestamp: Long): Double = basal[Profile.secondsFromMidnight(timestamp)/3600]
|
||||
fun getBasal(timestamp: Long): Double = basal[Profile.secondsFromMidnight(timestamp) / 3600]
|
||||
|
||||
// for localProfilePlugin Synchronisation
|
||||
fun basal() = jsonArray(basal)
|
||||
fun ic(circadian: Boolean = false): JSONArray {
|
||||
if(circadian)
|
||||
return jsonArray(pumpProfile.icBlocks, avgIC/pumpProfileAvgIC)
|
||||
if (circadian)
|
||||
return jsonArray(pumpProfile.icBlocks, avgIC / pumpProfileAvgIC)
|
||||
return jsonArray(ic)
|
||||
}
|
||||
|
||||
fun isf(circadian: Boolean = false): JSONArray {
|
||||
if(circadian)
|
||||
return jsonArray(pumpProfile.isfBlocks, avgISF/pumpProfileAvgISF)
|
||||
if (circadian)
|
||||
return jsonArray(pumpProfile.isfBlocks, avgISF / pumpProfileAvgISF)
|
||||
return jsonArray(Profile.fromMgdlToUnits(isf, profile.units))
|
||||
}
|
||||
|
||||
|
@ -88,7 +96,7 @@ class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector:
|
|||
fun profiletoOrefJSON(): String {
|
||||
var jsonString = ""
|
||||
val json = JSONObject()
|
||||
val insulinInterface: Insulin = activePlugin.activeInsulin
|
||||
val insulinInterface: Insulin = activePlugin.activeInsulin
|
||||
try {
|
||||
json.put("name", profilename)
|
||||
json.put("min_5m_carbimpact", sp.getDouble("openapsama_min_5m_carbimpact", 3.0))
|
||||
|
@ -115,7 +123,8 @@ class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector:
|
|||
JSONObject()
|
||||
.put("start", time)
|
||||
.put("minutes", h * 60)
|
||||
.put("rate", profile.getBasalTimeFromMidnight(secondfrommidnight)
|
||||
.put(
|
||||
"rate", profile.getBasalTimeFromMidnight(secondfrommidnight)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -134,7 +143,8 @@ class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector:
|
|||
json.put("units", GlucoseUnit.MGDL.asText)
|
||||
json.put("timezone", TimeZone.getDefault().id)
|
||||
jsonString = json.toString(2).replace("\\/", "/")
|
||||
} catch (e: JSONException) {}
|
||||
} catch (e: JSONException) {
|
||||
}
|
||||
|
||||
return jsonString
|
||||
}
|
||||
|
@ -144,8 +154,8 @@ class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector:
|
|||
try {
|
||||
json.put("dia", dia)
|
||||
if (circadian) {
|
||||
json.put("sens", jsonArray(pumpProfile.isfBlocks, avgISF/pumpProfileAvgISF))
|
||||
json.put("carbratio", jsonArray(pumpProfile.icBlocks, avgIC/pumpProfileAvgIC))
|
||||
json.put("sens", jsonArray(pumpProfile.isfBlocks, avgISF / pumpProfileAvgISF))
|
||||
json.put("carbratio", jsonArray(pumpProfile.icBlocks, avgIC / pumpProfileAvgIC))
|
||||
} else {
|
||||
json.put("sens", jsonArray(Profile.fromMgdlToUnits(isf, profile.units)))
|
||||
json.put("carbratio", jsonArray(ic))
|
||||
|
@ -156,8 +166,7 @@ class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector:
|
|||
return pureProfileFromJson(json, dateUtil, profile.units.asText)
|
||||
}
|
||||
|
||||
fun profileStore(circadian: Boolean = false): ProfileStore?
|
||||
{
|
||||
fun profileStore(circadian: Boolean = false): ProfileStore? {
|
||||
var profileStore: ProfileStore? = null
|
||||
val json = JSONObject()
|
||||
val store = JSONObject()
|
||||
|
@ -170,7 +179,8 @@ class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector:
|
|||
json.put("store", store)
|
||||
json.put("startDate", dateUtil.toISOAsUTC(dateUtil.now()))
|
||||
profileStore = ProfileStore(injector, json, dateUtil)
|
||||
} catch (e: JSONException) { }
|
||||
} catch (e: JSONException) {
|
||||
}
|
||||
return profileStore
|
||||
}
|
||||
|
|
@ -1,17 +1,18 @@
|
|||
package info.nightscout.androidaps.plugins.general.autotune.data
|
||||
package info.nightscout.plugins.general.autotune.data
|
||||
|
||||
import info.nightscout.androidaps.database.entities.GlucoseValue.TrendArrow
|
||||
import info.nightscout.androidaps.database.entities.GlucoseValue
|
||||
import info.nightscout.androidaps.database.entities.GlucoseValue.TrendArrow
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.T
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
import java.util.TimeZone
|
||||
|
||||
/**
|
||||
* Created by Rumen Georgiev on 2/24/2018.
|
||||
*/
|
||||
class BGDatum {
|
||||
|
||||
//Added by Rumen for autotune
|
||||
var id: Long = 0
|
||||
var date = 0L
|
||||
|
@ -27,7 +28,10 @@ class BGDatum {
|
|||
private set
|
||||
var dateUtil: DateUtil
|
||||
|
||||
constructor(dateUtil: DateUtil) { this.dateUtil = dateUtil}
|
||||
constructor(dateUtil: DateUtil) {
|
||||
this.dateUtil = dateUtil
|
||||
}
|
||||
|
||||
constructor(json: JSONObject, dateUtil: DateUtil) {
|
||||
this.dateUtil = dateUtil
|
||||
try {
|
|
@ -1,4 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.general.autotune.data
|
||||
package info.nightscout.plugins.general.autotune.data
|
||||
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import org.json.JSONException
|
||||
|
@ -20,7 +20,10 @@ class CRDatum {
|
|||
var crInsulinTotal = 0.0
|
||||
var dateUtil: DateUtil
|
||||
|
||||
constructor(dateUtil: DateUtil) { this.dateUtil = dateUtil}
|
||||
constructor(dateUtil: DateUtil) {
|
||||
this.dateUtil = dateUtil
|
||||
}
|
||||
|
||||
constructor(json: JSONObject, dateUtil: DateUtil) {
|
||||
this.dateUtil = dateUtil
|
||||
try {
|
|
@ -1,4 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.general.autotune.data
|
||||
package info.nightscout.plugins.general.autotune.data
|
||||
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
|
@ -1,4 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.general.autotune.data
|
||||
package info.nightscout.plugins.general.autotune.data
|
||||
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
|
@ -1,10 +1,9 @@
|
|||
package info.nightscout.androidaps.plugins.general.autotune.data
|
||||
package info.nightscout.plugins.general.autotune.data
|
||||
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
|
||||
class PreppedGlucose {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.general.autotune.events
|
||||
package info.nightscout.plugins.general.autotune.events
|
||||
|
||||
import info.nightscout.androidaps.events.Event
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package info.nightscout.androidaps.plugins.general.maintenance
|
||||
package info.nightscout.plugins.general.maintenance
|
||||
|
||||
import info.nightscout.androidaps.annotations.OpenForTesting
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.PrefFileListProvider
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
|
@ -21,15 +22,15 @@ class LoggerUtils @Inject constructor(
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
/*
|
||||
This is failing after slf4j update to 2.0.0
|
||||
It would be better to find a way to read the value from xml
|
||||
So far replaced by static value
|
||||
val logDirectory: String
|
||||
get() {
|
||||
val lc = LoggerFactory.getILoggerFactory() as LoggerContext
|
||||
return lc.getProperty("EXT_FILES_DIR")
|
||||
}
|
||||
*/
|
||||
/*
|
||||
This is failing after slf4j update to 2.0.0
|
||||
It would be better to find a way to read the value from xml
|
||||
So far replaced by static value
|
||||
val logDirectory: String
|
||||
get() {
|
||||
val lc = LoggerFactory.getILoggerFactory() as LoggerContext
|
||||
return lc.getProperty("EXT_FILES_DIR")
|
||||
}
|
||||
*/
|
||||
val logDirectory get() = prefFileListProvider.logsPath
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package info.nightscout.plugins.utils
|
||||
|
||||
import kotlin.math.floor
|
||||
|
||||
object Percentile {
|
||||
|
||||
// From https://gist.github.com/IceCreamYou/6ffa1b18c4c8f6aeaad2
|
||||
// Returns the value at a given percentile in a sorted numeric array.
|
||||
// "Linear interpolation between closest ranks" method
|
||||
fun percentile(arr: Array<Double>, p: Double): Double {
|
||||
if (arr.isEmpty()) return 0.0
|
||||
if (p <= 0) return arr[0]
|
||||
if (p >= 1) return arr[arr.size - 1]
|
||||
val index = arr.size * p
|
||||
val lower = floor(index)
|
||||
val upper = lower + 1
|
||||
val weight = index % 1
|
||||
return if (upper >= arr.size) arr[lower.toInt()] else arr[lower.toInt()] * (1 - weight) + arr[upper.toInt()] * weight
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".plugins.general.autotune.AutotuneFragment">
|
||||
tools:context="info.nightscout.plugins.general.autotune.AutotuneFragment">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
@ -133,7 +133,7 @@
|
|||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tune_lastrun"
|
||||
android:id="@+id/tune_last_run"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
|
@ -246,7 +246,7 @@
|
|||
app:layout_row="0" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/autotune_copylocal"
|
||||
android:id="@+id/autotune_copy_local"
|
||||
style="@style/GrayButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
|
@ -1,18 +1,19 @@
|
|||
package info.nightscout.androidaps.plugins.general.autotune
|
||||
package info.nightscout.plugins.general.autotune
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.TestBaseWithProfile
|
||||
import info.nightscout.androidaps.data.LocalInsulin
|
||||
import info.nightscout.androidaps.data.ProfileSealed
|
||||
import info.nightscout.androidaps.data.PureProfile
|
||||
import info.nightscout.androidaps.database.data.Block
|
||||
import info.nightscout.androidaps.database.data.TargetBlock
|
||||
import info.nightscout.androidaps.interfaces.*
|
||||
import info.nightscout.androidaps.plugins.general.autotune.data.*
|
||||
import info.nightscout.androidaps.interfaces.GlucoseUnit
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.JsonHelper
|
||||
import info.nightscout.androidaps.utils.T
|
||||
import info.nightscout.plugins.R
|
||||
import info.nightscout.plugins.general.autotune.data.ATProfile
|
||||
import info.nightscout.plugins.general.autotune.data.PreppedGlucose
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
|
@ -22,14 +23,13 @@ import org.junit.Test
|
|||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.`when`
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import java.util.TimeZone
|
||||
|
||||
class AutotuneCoreTest : TestBaseWithProfile() {
|
||||
|
||||
@Mock lateinit var sp: SP
|
||||
@Mock lateinit var autotuneFS: AutotuneFS
|
||||
@Mock lateinit var injector: HasAndroidInjector
|
||||
@Mock lateinit var activePlugin: ActivePlugin
|
||||
private lateinit var autotuneCore: AutotuneCore
|
||||
private var min5mCarbImpact = 0.0
|
||||
private var autotuneMin = 0.0
|
|
@ -1,7 +1,6 @@
|
|||
package info.nightscout.androidaps.plugins.general.autotune
|
||||
package info.nightscout.plugins.general.autotune
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.TestBaseWithProfile
|
||||
import info.nightscout.androidaps.data.IobTotal
|
||||
import info.nightscout.androidaps.data.LocalInsulin
|
||||
|
@ -14,11 +13,14 @@ import info.nightscout.androidaps.database.entities.Bolus
|
|||
import info.nightscout.androidaps.database.entities.Carbs
|
||||
import info.nightscout.androidaps.database.entities.GlucoseValue
|
||||
import info.nightscout.androidaps.extensions.shiftBlock
|
||||
import info.nightscout.androidaps.interfaces.*
|
||||
import info.nightscout.androidaps.plugins.general.autotune.data.*
|
||||
import info.nightscout.androidaps.interfaces.GlucoseUnit
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.JsonHelper
|
||||
import info.nightscout.androidaps.utils.T
|
||||
import info.nightscout.plugins.R
|
||||
import info.nightscout.plugins.general.autotune.data.ATProfile
|
||||
import info.nightscout.plugins.general.autotune.data.PreppedGlucose
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
import org.json.JSONArray
|
||||
|
@ -29,14 +31,13 @@ import org.junit.Test
|
|||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.`when`
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import java.util.TimeZone
|
||||
|
||||
class AutotunePrepTest : TestBaseWithProfile() {
|
||||
|
||||
@Mock lateinit var sp: SP
|
||||
@Mock lateinit var autotuneFS: AutotuneFS
|
||||
@Mock lateinit var injector: HasAndroidInjector
|
||||
@Mock lateinit var activePlugin: ActivePlugin
|
||||
@Mock lateinit var repository: AppRepository
|
||||
private lateinit var autotunePrep: AutotunePrep
|
||||
private lateinit var autotuneIob: TestAutotuneIob
|
||||
|
@ -55,8 +56,8 @@ class AutotunePrepTest : TestBaseWithProfile() {
|
|||
fun autotunePrepTest1() { // Test if categorisation with standard treatments with carbs is Ok
|
||||
val inputIobJson = File("src/test/res/autotune/test1/oaps-iobCalc.2022-05-21.json").readText() //json files build with iob/activity calculated by OAPS
|
||||
val iobOapsCalculation = buildIobOaps(JSONArray(inputIobJson))
|
||||
autotuneIob = TestAutotuneIob(aapsLogger, repository, profileFunction, sp, dateUtil, activePlugin, autotuneFS, iobOapsCalculation)
|
||||
autotunePrep = AutotunePrep(aapsLogger, sp, dateUtil, autotuneFS, autotuneIob)
|
||||
autotuneIob = TestAutotuneIob(aapsLogger, repository, profileFunction, sp, dateUtil, autotuneFS, iobOapsCalculation)
|
||||
autotunePrep = AutotunePrep(sp, dateUtil, autotuneFS, autotuneIob)
|
||||
val inputProfileJson = File("src/test/res/autotune/test1/profile.pump.json").readText()
|
||||
val inputProfile = atProfileFromOapsJson(JSONObject(inputProfileJson), dateUtil)!!
|
||||
val prepJson = File("src/test/res/autotune/test1/autotune.2022-05-21.json").readText()
|
||||
|
@ -94,8 +95,8 @@ class AutotunePrepTest : TestBaseWithProfile() {
|
|||
fun autotunePrepTest2() { // Test if categorisation without carbs (full UAM) and categorize UAM as basal false is Ok
|
||||
val inputIobJson = File("src/test/res/autotune/test2/oaps-iobCalc.2022-05-21.json").readText() //json files build with iob/activity calculated by OAPS
|
||||
val iobOapsCalculation = buildIobOaps(JSONArray(inputIobJson))
|
||||
autotuneIob = TestAutotuneIob(aapsLogger, repository, profileFunction, sp, dateUtil, activePlugin, autotuneFS, iobOapsCalculation)
|
||||
autotunePrep = AutotunePrep(aapsLogger, sp, dateUtil, autotuneFS, autotuneIob)
|
||||
autotuneIob = TestAutotuneIob(aapsLogger, repository, profileFunction, sp, dateUtil, autotuneFS, iobOapsCalculation)
|
||||
autotunePrep = AutotunePrep(sp, dateUtil, autotuneFS, autotuneIob)
|
||||
val inputProfileJson = File("src/test/res/autotune/test2/profile.pump.json").readText()
|
||||
val inputProfile = atProfileFromOapsJson(JSONObject(inputProfileJson), dateUtil)!!
|
||||
val prepJson = File("src/test/res/autotune/test2/autotune.2022-05-21.json").readText()
|
||||
|
@ -133,8 +134,8 @@ class AutotunePrepTest : TestBaseWithProfile() {
|
|||
fun autotunePrepTest3() { // Test if categorisation without carbs (full UAM) and categorize UAM as basal true is Ok
|
||||
val inputIobJson = File("src/test/res/autotune/test3/oaps-iobCalc.2022-05-21.json").readText() //json files build with iob/activity calculated by OAPS
|
||||
val iobOapsCalculation = buildIobOaps(JSONArray(inputIobJson))
|
||||
autotuneIob = TestAutotuneIob(aapsLogger, repository, profileFunction, sp, dateUtil, activePlugin, autotuneFS, iobOapsCalculation)
|
||||
autotunePrep = AutotunePrep(aapsLogger, sp, dateUtil, autotuneFS, autotuneIob)
|
||||
autotuneIob = TestAutotuneIob(aapsLogger, repository, profileFunction, sp, dateUtil, autotuneFS, iobOapsCalculation)
|
||||
autotunePrep = AutotunePrep(sp, dateUtil, autotuneFS, autotuneIob)
|
||||
val inputProfileJson = File("src/test/res/autotune/test3/profile.pump.json").readText()
|
||||
val inputProfile = atProfileFromOapsJson(JSONObject(inputProfileJson), dateUtil)!!
|
||||
val prepJson = File("src/test/res/autotune/test3/autotune.2022-05-21.json").readText()
|
||||
|
@ -305,10 +306,9 @@ class AutotunePrepTest : TestBaseWithProfile() {
|
|||
class TestAutotuneIob(
|
||||
val aapsLogger: AAPSLogger,
|
||||
repository: AppRepository,
|
||||
val profileFunction: ProfileFunction,
|
||||
val sp: SP,
|
||||
val dateUtil: DateUtil,
|
||||
val activePlugin: ActivePlugin,
|
||||
profileFunction: ProfileFunction,
|
||||
sp: SP,
|
||||
dateUtil: DateUtil,
|
||||
autotuneFS: AutotuneFS,
|
||||
private val iobOapsCalculation: ArrayList<IobTotal>
|
||||
) : AutotuneIob(
|
|
@ -1,9 +1,9 @@
|
|||
package info.nightscout.androidaps.plugins.general.autotune
|
||||
package info.nightscout.plugins.general.autotune
|
||||
|
||||
import info.nightscout.androidaps.TestBaseWithProfile
|
||||
import info.nightscout.androidaps.plugins.general.autotune.data.BGDatum
|
||||
import info.nightscout.androidaps.plugins.general.autotune.data.CRDatum
|
||||
import info.nightscout.androidaps.plugins.general.autotune.data.PreppedGlucose
|
||||
import info.nightscout.plugins.general.autotune.data.BGDatum
|
||||
import info.nightscout.plugins.general.autotune.data.CRDatum
|
||||
import info.nightscout.plugins.general.autotune.data.PreppedGlucose
|
||||
import org.json.JSONObject
|
||||
import org.junit.Assert
|
||||
import org.junit.Before
|
|
@ -28,7 +28,6 @@
|
|||
<string name="invalid_weight">Invalid weight entry</string>
|
||||
<string name="id">ID:</string>
|
||||
<string name="submit">Submit</string>
|
||||
<string name="profile">Profile</string>
|
||||
<string name="age">Age</string>
|
||||
<string name="weight_label">Weight</string>
|
||||
<string name="most_common_profile">Most common profile:</string>
|
||||
|
|
Loading…
Reference in a new issue