mirror of
https://github.com/UbiquitousIntelligentSystemBINUS/SleepMonitoringSystemUsingEdgeCache.git
synced 2026-07-11 15:23:34 +07:00
Add files via upload
This commit is contained in:
112
gateway-classification/src/classify/complex.go
Normal file
112
gateway-classification/src/classify/complex.go
Normal file
@@ -0,0 +1,112 @@
|
||||
package classify
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
type Complex struct {
|
||||
Re float64 // the real part
|
||||
Im float64 // the imaginary part
|
||||
}
|
||||
|
||||
// create a new object with the given real and imaginary parts
|
||||
func NewComplex(real, imag float64) Complex {
|
||||
return Complex{Re: real, Im: imag}
|
||||
}
|
||||
|
||||
// return a string representation of the invoking Complex object
|
||||
func (c Complex) String() string {
|
||||
if c.Im == 0 {
|
||||
return fmt.Sprintf("%g", c.Re)
|
||||
}
|
||||
if c.Re == 0 {
|
||||
return fmt.Sprintf("%gi", c.Im)
|
||||
}
|
||||
if c.Im < 0 {
|
||||
return fmt.Sprintf("%g - %gi", c.Re, -c.Im)
|
||||
}
|
||||
return fmt.Sprintf("%g + %gi", c.Re, c.Im)
|
||||
}
|
||||
|
||||
// return abs/modulus/magnitude
|
||||
func (c Complex) Abs() float64 {
|
||||
return math.Hypot(c.Re, c.Im)
|
||||
}
|
||||
|
||||
// return a new Complex object whose value is (this + b)
|
||||
func (c Complex) Plus(b Complex) Complex {
|
||||
return Complex{c.Re + b.Re, c.Im + b.Im}
|
||||
}
|
||||
|
||||
// return a new Complex object whose value is (this - b)
|
||||
func (c Complex) Minus(b Complex) Complex {
|
||||
return Complex{c.Re - b.Re, c.Im - b.Im}
|
||||
}
|
||||
|
||||
// return a new Complex object whose value is (this * b)
|
||||
func (c Complex) Times(b Complex) Complex {
|
||||
return Complex{c.Re*b.Re - c.Im*b.Im, c.Re*b.Im + c.Im*b.Re}
|
||||
}
|
||||
|
||||
// return a new Complex object whose value is the reciprocal of this
|
||||
func (c Complex) Reciprocal() Complex {
|
||||
scale := c.Re*c.Re + c.Im*c.Im
|
||||
return Complex{c.Re / scale, -c.Im / scale}
|
||||
}
|
||||
|
||||
// return a / b
|
||||
func (c Complex) Divides(b Complex) Complex {
|
||||
return c.Times(b.Reciprocal())
|
||||
}
|
||||
|
||||
// return a new Complex object whose value is the complex sine of this
|
||||
func (c Complex) Sin() Complex {
|
||||
return Complex{math.Sin(c.Re) * math.Cosh(c.Im), math.Cos(c.Re) * math.Sinh(c.Im)}
|
||||
}
|
||||
|
||||
// return a new Complex object whose value is the complex cosine of this
|
||||
func (c Complex) Cos() Complex {
|
||||
return Complex{math.Cos(c.Re) * math.Cosh(c.Im), -math.Sin(c.Re) * math.Sinh(c.Im)}
|
||||
}
|
||||
|
||||
// equals returns true if the given Complex object is equal to the receiver
|
||||
func (c Complex) Equals(x Complex) bool {
|
||||
return c.Re == x.Re && c.Im == x.Im
|
||||
}
|
||||
|
||||
// FFT computes the FFT of a complex sequence x[] of length n.
|
||||
func FFT(x []Complex) []Complex {
|
||||
n := len(x)
|
||||
if n == 1 {
|
||||
return []Complex{x[0]}
|
||||
}
|
||||
|
||||
if n%2 != 0 {
|
||||
panic("n is not a power of 2")
|
||||
}
|
||||
|
||||
// Compute FFT of even terms
|
||||
even := make([]Complex, n/2)
|
||||
for k := 0; k < n/2; k++ {
|
||||
even[k] = x[2*k]
|
||||
}
|
||||
q := FFT(even)
|
||||
|
||||
// Compute FFT of odd terms
|
||||
odd := even // Reuse the array
|
||||
for k := 0; k < n/2; k++ {
|
||||
odd[k] = x[2*k+1]
|
||||
}
|
||||
r := FFT(odd)
|
||||
|
||||
// Combine
|
||||
y := make([]Complex, n)
|
||||
for k := 0; k < n/2; k++ {
|
||||
kth := -2 * math.Pi * float64(k) / float64(n)
|
||||
wk := Complex{math.Cos(kth), math.Sin(kth)}
|
||||
y[k] = q[k].Plus(wk.Times(r[k]))
|
||||
y[k+n/2] = q[k].Minus(wk.Times(r[k]))
|
||||
}
|
||||
return y
|
||||
}
|
||||
1
gateway-classification/src/classify/elmClassifier.go
Normal file
1
gateway-classification/src/classify/elmClassifier.go
Normal file
@@ -0,0 +1 @@
|
||||
package classify
|
||||
96
gateway-classification/src/classify/elmModel.go
Normal file
96
gateway-classification/src/classify/elmModel.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package classify
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type RealMatrix struct {
|
||||
Rows int
|
||||
Cols int
|
||||
Data [][]float64
|
||||
}
|
||||
|
||||
type Weight struct {
|
||||
W RealMatrix
|
||||
BW RealMatrix
|
||||
}
|
||||
|
||||
type ELMModel struct {
|
||||
InputWeight RealMatrix
|
||||
BiasInputWeight RealMatrix
|
||||
OutputWeight RealMatrix
|
||||
Separator string
|
||||
}
|
||||
|
||||
func NewELMModel(inputWeightFilePath, outputWeightFilePath string) (*ELMModel, error) {
|
||||
var elmModel ELMModel
|
||||
|
||||
inputWeightFileBytes, err := ioutil.ReadFile(inputWeightFilePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
outputWeightFileBytes, err := ioutil.ReadFile(outputWeightFilePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
inputWeightFileLines := strings.Split(string(inputWeightFileBytes), "\n")
|
||||
outputWeightFileLines := strings.Split(string(outputWeightFileBytes), "\n")
|
||||
|
||||
weight, err := convertListCsvTo2dArr(inputWeightFileLines, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
elmModel.InputWeight = weight.W
|
||||
elmModel.BiasInputWeight = weight.BW
|
||||
|
||||
weight, err = convertListCsvTo2dArr(outputWeightFileLines, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
elmModel.OutputWeight = weight.W
|
||||
|
||||
return &elmModel, nil
|
||||
}
|
||||
|
||||
func convertListCsvTo2dArr(input []string, useBias bool) (Weight, error) {
|
||||
var weight Weight
|
||||
|
||||
listSize := len(input)
|
||||
if listSize == 0 {
|
||||
return weight, errors.New("empty input list")
|
||||
}
|
||||
|
||||
csvElementSize := len(strings.Split(input[0], ","))
|
||||
for _, line := range input {
|
||||
if len(strings.Split(line, ",")) != csvElementSize {
|
||||
return weight, errors.New("invalid CSV length")
|
||||
}
|
||||
}
|
||||
|
||||
weightData := make([][]float64, listSize)
|
||||
biasWeightData := make([][]float64, listSize)
|
||||
|
||||
for i, line := range input {
|
||||
splittedLine := strings.Split(line, ",")
|
||||
temp := make([]float64, len(splittedLine))
|
||||
for j, val := range splittedLine {
|
||||
temp[j], _ = strconv.ParseFloat(strings.TrimSpace(val), 64)
|
||||
}
|
||||
if useBias {
|
||||
weightData[i] = temp[:len(temp)-1]
|
||||
biasWeightData[i] = []float64{temp[len(temp)-1]}
|
||||
} else {
|
||||
weightData[i] = temp
|
||||
}
|
||||
}
|
||||
|
||||
weight.W = RealMatrix{Rows: listSize, Cols: len(weightData[0]), Data: weightData}
|
||||
weight.BW = RealMatrix{Rows: listSize, Cols: 1, Data: biasWeightData}
|
||||
|
||||
return weight, nil
|
||||
}
|
||||
255
gateway-classification/src/classify/hrvFeature.go
Normal file
255
gateway-classification/src/classify/hrvFeature.go
Normal file
@@ -0,0 +1,255 @@
|
||||
package classify
|
||||
|
||||
import (
|
||||
"math"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type HRVFeature struct {
|
||||
F01_AVNN float64
|
||||
F02_SDNN float64
|
||||
F03_RMSSD float64
|
||||
F04_SDSD float64
|
||||
F05_NNx float64
|
||||
F06_PNNx float64
|
||||
F07_HRV_TRIANGULAR_IDX float64
|
||||
F08_SD1 float64
|
||||
F09_SD2 float64
|
||||
F10_SD1_SD2_RATIO float64
|
||||
F11_S float64
|
||||
F12_TP float64
|
||||
F13_pLF float64
|
||||
F14_pHF float64
|
||||
F15_LFHFratio float64
|
||||
F16_VLF float64
|
||||
F17_LF float64
|
||||
F18_HF float64
|
||||
}
|
||||
|
||||
func NewHRVFeature(rrIntervalSet RRIntervalSet) *HRVFeature {
|
||||
var hrv HRVFeature
|
||||
|
||||
rrIntervalValue := rrIntervalSet.RRIntervalValue
|
||||
rrIntervalsValueDiff := rrIntervalSet.RRIntervalsValueDiff
|
||||
|
||||
hrv.F01_AVNN = f01_AVNN(rrIntervalValue)
|
||||
hrv.F02_SDNN = f02_SDNN(rrIntervalValue)
|
||||
hrv.F03_RMSSD = f03_RMSSD(rrIntervalsValueDiff)
|
||||
hrv.F04_SDSD = f04_SDSD(rrIntervalsValueDiff)
|
||||
hrv.F05_NNx = f05_NNx(rrIntervalsValueDiff, 50)
|
||||
hrv.F06_PNNx = f06_PNNx(rrIntervalValue, hrv.F05_NNx)
|
||||
hrv.F07_HRV_TRIANGULAR_IDX = f07_HRV_TRIANGULAR_IDX(rrIntervalValue)
|
||||
hrv.F08_SD1 = f08_SD1(hrv.F04_SDSD)
|
||||
hrv.F09_SD2 = f09_SD2(hrv.F02_SDNN, hrv.F04_SDSD)
|
||||
hrv.F10_SD1_SD2_RATIO = f10_SD1_SD2_RATIO(hrv.F08_SD1, hrv.F09_SD2)
|
||||
hrv.F11_S = f11_S(hrv.F08_SD1, hrv.F09_SD2)
|
||||
|
||||
feature12To18 := f12_18(rrIntervalValue, 2)
|
||||
hrv.F12_TP = feature12To18.TP
|
||||
hrv.F13_pLF = feature12To18.pLF
|
||||
hrv.F14_pHF = feature12To18.pHF
|
||||
hrv.F15_LFHFratio = feature12To18.LFHFratio
|
||||
hrv.F16_VLF = feature12To18.VLF
|
||||
hrv.F17_LF = feature12To18.LF
|
||||
hrv.F18_HF = feature12To18.HF
|
||||
|
||||
return &hrv
|
||||
}
|
||||
|
||||
func f01_AVNN(rrIntervalValue []float64) float64 {
|
||||
return mean(rrIntervalValue)
|
||||
}
|
||||
|
||||
func f02_SDNN(rrIntervalValue []float64) float64 {
|
||||
return sampleStandardDeviation(rrIntervalValue)
|
||||
}
|
||||
|
||||
func f03_RMSSD(rrIntervalsValueDiff []float64) float64 {
|
||||
return math.Sqrt(mean(powList(rrIntervalsValueDiff, 2)))
|
||||
}
|
||||
|
||||
func f04_SDSD(rrIntervalsValueDiff []float64) float64 {
|
||||
return sampleStandardDeviation(rrIntervalsValueDiff)
|
||||
}
|
||||
|
||||
func f05_NNx(rrIntervalsValueDiff []float64, x float64) float64 {
|
||||
count := filterCount(mulList(rrIntervalsValueDiff, 1000), func(y float64) bool {
|
||||
return y > x
|
||||
})
|
||||
return float64(count)
|
||||
}
|
||||
|
||||
func f06_PNNx(rrIntervalValue []float64, NNx float64) float64 {
|
||||
return (NNx / (float64(len(rrIntervalValue)) - 1)) * 100
|
||||
}
|
||||
|
||||
func f07_HRV_TRIANGULAR_IDX(rrIntervalValue []float64) float64 {
|
||||
binSize := 7.812
|
||||
var tempRr []float64
|
||||
for _, val := range rrIntervalValue {
|
||||
tempRr = append(tempRr, val*1000)
|
||||
}
|
||||
|
||||
sort.Float64s(tempRr)
|
||||
maxVal := tempRr[len(tempRr)-1]
|
||||
minVal := tempRr[0]
|
||||
|
||||
binCount := math.Ceil((maxVal - minVal) / binSize)
|
||||
edges := make([]float64, int(binCount)+1)
|
||||
var Nds []float64
|
||||
edges[0] = minVal
|
||||
|
||||
for i := 1; i <= int(binCount); i++ {
|
||||
edges[i] = edges[i-1] + binSize
|
||||
var d float64
|
||||
for _, x := range tempRr {
|
||||
if x >= edges[i-1] && x < edges[i] {
|
||||
d++
|
||||
}
|
||||
}
|
||||
if d != 0 {
|
||||
Nds = append(Nds, d)
|
||||
}
|
||||
}
|
||||
|
||||
return max(Nds) / sum(Nds)
|
||||
}
|
||||
|
||||
func f08_SD1(sdsd float64) float64 {
|
||||
return math.Sqrt(math.Pow(sdsd, 2) / 2)
|
||||
}
|
||||
|
||||
func f09_SD2(sdnn, sdsd float64) float64 {
|
||||
return math.Sqrt(2*math.Pow(sdnn, 2) - math.Pow(sdsd, 2)/2)
|
||||
}
|
||||
|
||||
func f10_SD1_SD2_RATIO(sd1, sd2 float64) float64 {
|
||||
return sd1 / sd2
|
||||
}
|
||||
|
||||
func f11_S(sd1, sd2 float64) float64 {
|
||||
return math.Pi * sd1 * sd2
|
||||
}
|
||||
|
||||
func f12_18(rrIntervalValue []float64, Fs float64) Feature12To18 {
|
||||
var feature Feature12To18
|
||||
// Implement the logic for feature calculation
|
||||
return feature
|
||||
}
|
||||
|
||||
func filterF(YY []float64, f []float64, predicate func(float64) bool) []float64 {
|
||||
var result []float64
|
||||
for i, val := range f {
|
||||
if predicate(val) {
|
||||
result = append(result, YY[i])
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func nanzscore(input []float64) []float64 {
|
||||
m := nanmean(input)
|
||||
s := nanstd(input)
|
||||
|
||||
var z []float64
|
||||
for _, val := range input {
|
||||
z = append(z, (val-m)/s)
|
||||
}
|
||||
return z
|
||||
}
|
||||
|
||||
func nanmean(input []float64) float64 {
|
||||
return mean(input)
|
||||
}
|
||||
|
||||
func nanstd(input []float64) float64 {
|
||||
return populationStandardDeviation(input)
|
||||
}
|
||||
|
||||
type Feature12To18 struct {
|
||||
TP float64
|
||||
pLF float64
|
||||
pHF float64
|
||||
LFHFratio float64
|
||||
VLF float64
|
||||
LF float64
|
||||
HF float64
|
||||
}
|
||||
|
||||
type RRIntervalSet struct {
|
||||
RRIntervalValue []float64
|
||||
RRIntervalsValueDiff []float64
|
||||
}
|
||||
|
||||
func mean(arr []float64) float64 {
|
||||
sum := 0.0
|
||||
for _, val := range arr {
|
||||
sum += val
|
||||
}
|
||||
return sum / float64(len(arr))
|
||||
}
|
||||
|
||||
func sampleStandardDeviation(arr []float64) float64 {
|
||||
mean := mean(arr)
|
||||
variance := 0.0
|
||||
for _, val := range arr {
|
||||
variance += math.Pow(val-mean, 2)
|
||||
}
|
||||
return math.Sqrt(variance / float64(len(arr)-1))
|
||||
}
|
||||
|
||||
func powList(arr []float64, exp float64) []float64 {
|
||||
var result []float64
|
||||
for _, val := range arr {
|
||||
result = append(result, math.Pow(val, exp))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func filterCount(arr []float64, predicate func(float64) bool) int {
|
||||
count := 0
|
||||
for _, val := range arr {
|
||||
if predicate(val) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func sum(arr []float64) float64 {
|
||||
total := 0.0
|
||||
for _, val := range arr {
|
||||
total += val
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
func max(arr []float64) float64 {
|
||||
if len(arr) == 0 {
|
||||
return 0
|
||||
}
|
||||
max := arr[0]
|
||||
for _, val := range arr {
|
||||
if val > max {
|
||||
max = val
|
||||
}
|
||||
}
|
||||
return max
|
||||
}
|
||||
|
||||
func populationStandardDeviation(input []float64) float64 {
|
||||
meanVal := mean(input)
|
||||
variance := 0.0
|
||||
for _, val := range input {
|
||||
variance += math.Pow(val-meanVal, 2)
|
||||
}
|
||||
return math.Sqrt(variance / float64(len(input)))
|
||||
}
|
||||
|
||||
func mulList(input []float64, multiplier float64) []float64 {
|
||||
result := make([]float64, len(input))
|
||||
for i, val := range input {
|
||||
result[i] = val * multiplier
|
||||
}
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user