Add files via upload

This commit is contained in:
dije07
2024-04-01 16:31:24 +07:00
committed by GitHub
parent e1c8cb365f
commit 0193e344c7
17 changed files with 1751 additions and 0 deletions

View 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
}

View File

@@ -0,0 +1 @@
package classify

View 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
}

View 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
}