ssa
1package ssaApp2
3import (4"fmt"5"math"6"time"7
8"github.com/RB-PRO/ssa/pkg/blackmanharris"9"github.com/RB-PRO/ssa/pkg/oss"10"github.com/RB-PRO/ssa/pkg/periodogram"11"github.com/RB-PRO/ssa/pkg/ssa"12"gonum.org/v1/gonum/mat"13)
14
15func SSS_spw2(pw, fmp []float64) {16s := ssa.New("File")17s.Graph = true // Создавать графики18s.Xlsx = true // Сохранять в Xlsx19s.Var(pw, fmp)20s.Spw_Form(pw) // Создать spw21
22// # 1, 2, 3, 423s.SET_Form() // SSA - анализ сегментов pw24
25// # 526// Оценка АКФ сингулярных троек для сегментов pw27// Визуализация АКФ сингулярных троек для сегментов pw28s.AKF_Form() // Оценка АКФ сингулярных троек для сегментов pw29
30// # 6, 731// Огибающие АКФ сингулярных троек sET12 сегментов pw32// Нормированные АКФ сингулярных троек sET12 сегментов pw33s.Envelope()34
35// # 836// Мгновенная частота нормированной АКФ сингулярных троек sET12 для сегментов pw37s.MomentFrequency()38
39// # 940// Визуализация СПМ сингулярных троек сегменов pw41s.VisibleSPM()42
43// # 1044// Агрегирование сегментов очищенной пульсовой волны cpw45s.AggregationPW()46
47}
48
49/*
50func SSA_spw(pw, fmp []float64) {
51defer timer("SSA_spw")()
52// Сегменты отсчётов pw
53N := len(pw) // Количество отсчетов pw
54win := 1024
55res := N - win*int(math.Floor(float64(N)/float64(win)))
56nPart := 20 // Количество долей res
57res = int(math.Floor(float64(res) / float64(nPart)))
58//overlap := (float64(win) - float64(res)) / float64(win)
59S := 1
60Imin := 1
61Imax := win
62
63var ns []float64
64for Imax <= N {
65ns = append(ns, float64(S)) // номер текущего сегмента pw
66Imin = Imin + res
67Imax = Imax + res
68S++
69}
70S-- // кол-во перекрывающихся сегментов pw в пределах N
71
72spw := mat.NewDense(win, S, nil)
73//fmt.Println("Размеры spw:", win, S)
74for j := 0; j < S; j++ {
75for i := 0; i < win; i++ {
76k := (j) * res
77spw.Set(i, j, pw[k+i])
78}
79}
80
81// Set general parameters
82cad := 30 // 30 кадров/сек
83dt := 1 / float64(cad) // интервал дискретизации времени, сек
84tim := make([]float64, N)
85for index := 1; index < N; index++ {
86tim[index] = tim[index-1] + dt
87}
88
89ns2 := make([]int, S)
90for index := range ns2 {
91ns2[index] = (index + 1)
92}
93
94L := make([]float64, S)
95for index := range L { // цикл по сегментам pw
96L[index] = math.Floor(float64(cad) / fmp[index]) // кол-во отсчетов основного тона pw
97}
98
99K := 5
100M := int(float64(K) * oss.Max(L)) // параметр вложения в траекторное пространство
101// SSA - анализ сегментов pw
102seg := 100 // номер сегмента pw для визуализации
103nET := 4 // кол-во сингулярных троек для сегментов pw
104
105//var sET12 mat.Dense
106sET12_sum2 := mat.NewDense(win, 2, nil) // НЕ ФАКТ, ЧТО К-во строк win
107sET34_sum2 := mat.NewDense(win, 2, nil) // НЕ ФАКТ, ЧТО К-во строк win
108sET12 := mat.NewDense(win, S, nil) // НЕ ФАКТ, ЧТО К-во строк win
109sET34 := mat.NewDense(win, S, nil) // НЕ ФАКТ, ЧТО К-во строк win
110
111for j := 0; j < S; j++ {
112C, LBD, RC := ssa.SSA(win, M, spw.ColView(j), nET)
113//fmt.Println(j, S)
114RC_T := mat.DenseCopyOf(RC.T())
115
116sET12_sum2.SetCol(0, RC_T.RawRowView(0))
117sET12_sum2.SetCol(1, RC_T.RawRowView(1))
118sET12.SetCol(j, oss.Sum2(*sET12_sum2))
119sET12_sum2.Zero()
120
121sET34_sum2.SetCol(0, RC_T.RawRowView(2))
122sET34_sum2.SetCol(1, RC_T.RawRowView(3))
123sET34.SetCol(j, oss.Sum2(*sET34_sum2))
124sET34_sum2.Zero()
125
126if j == seg {
127graph.Imagesc(C, "C")
128oss.Matlab_mat_Dense(&C, 1, "C", "")
129log.Println("Covariance matrix")
130graph.MakeGraphOfArray(LBD, "LBD")
131
132oss.Matlab_arr_float(LBD, 2, "LBD", "")
133log.Println("Eigenvalues")
134
135err_makeGraphYX_sET12 := graph.MakeGraphYX_VecDense(
136*mat.NewVecDense(win, tim[0:win]),
137*(mat.VecDenseCopyOf(spw.ColView(j))),
138*(mat.NewVecDense(len(oss.Vec_in_ArrFloat(sET12.ColView(j))), oss.Vec_in_ArrFloat(sET12.ColView(j)))),
139"origin", "sET12")
140oss.Matlab_arr_float(tim, 3, "tim", "")
141oss.Matlab_mat_Dense(spw, 3, "spw", "")
142oss.Matlab_mat_Dense(sET12, 3, "sET12", "")
143log.Println("Original time series and reconstruction sET12")
144
145err_makeGraphYX_sET34 := graph.MakeGraphYX_VecDense(
146*mat.NewVecDense(win, tim[0:win]),
147*(mat.VecDenseCopyOf(spw.ColView(j))),
148*(mat.NewVecDense(len(oss.Vec_in_ArrFloat(sET34.ColView(j))), oss.Vec_in_ArrFloat(sET34.ColView(j)))),
149"origin", "sET34")
150oss.Matlab_arr_float(tim, 4, "tim", "")
151oss.Matlab_mat_Dense(spw, 4, "spw", "")
152oss.Matlab_mat_Dense(sET34, 4, "sET34", "")
153log.Println("Original time series and reconstruction sET34")
154
155if err_makeGraphYX_sET12 != nil {
156fmt.Println(err_makeGraphYX_sET12)
157}
158if err_makeGraphYX_sET34 != nil {
159fmt.Println(err_makeGraphYX_sET34)
160}
161}
162}
163
164oss.SafeToXlsxMatrix(sET12, "sET12")
165oss.SafeToXlsxMatrix(sET34, "sET34")
166
167// *****************
168// Оценка АКФ сингулярных троек для сегментов pw
169lag := int(math.Floor(float64(win) / 10.0)) // % наибольший лаг АКФ <= win/10
170lagS := 2 * lag
171Acf_sET12 := ssa.ACF_estimation_of_singular_triples(lagS, win, S, *sET12)
172oss.SafeToXlsxM(*Acf_sET12, "Acf_sET12")
173// *****************
174// Визуализация АКФ сингулярных троек для сегментов pw
175lgl := make([]float64, lag)
176for m := 0; m < len(lgl); m++ {
177lgl[m] = float64(m + 1)
178}
179time := make([]float64, lag)
180for m := 1; m < len(time); m++ {
181time[m] = time[m-1] + dt
182}
183oss.Matlab_arr_float(ns, 5, "ns", "")
184oss.Matlab_arr_float(time, 5, "time", "")
185oss.Matlab_mat_Dense(Acf_sET12, 5, "Acf_sET12", "")
186log.Println("Визуализация АКФ сингулярных троек для сегментов pw")
187
188// *****************
189// Огибающая по критерию локальных максимумов abs(acf_sET12)
190//power := 0.75 // параметр спрямляющего преобразования
191EnvAcf_sET12 := *mat.NewDense(lag, S, nil)
192AcfNrm_sET12 := *mat.NewDense(lag, S, nil)
193//for j := 16; j <= 16; j++ { // цикл по сегментам АКФ
194for j := 0; j < S; j++ { // цикл по сегментам АКФ
195Acf_sET12_col := *mat.VecDenseCopyOf(Acf_sET12.ColView(j))
196absTS := oss.AbsVector(Acf_sET12_col)
197at1 := absTS.AtVec(0)
198at2 := absTS.AtVec(1)
199
200maxTS := *mat.NewVecDense(lag, nil)
201maxTS.SetVec(0, at1)
202
203maxN := *mat.NewVecDense(lag, nil)
204maxN.SetVec(0, 1)
205
206var Nmax int
207
208for m := 2; m < lag; m++ {
209at3 := absTS.AtVec(m)
210if (at1 <= at2) && (at2 >= at3) {
211Nmax++ // номер очередного узла интерполяции (счетчик максимумов)
212maxN.SetVec(Nmax, float64(m)) // номер очередного максимума для ряда absTS
213maxTS.SetVec(Nmax, at2) // отсчет очередного узла интерполяции
214}
215at1 = at2
216at2 = at3
217}
218Nmax++ // количество узлов интерполяции
219maxN.SetVec(Nmax, float64(lag)) // номер отсчета absTS финального узла интерполяции
220maxTS.SetVec(Nmax, absTS.AtVec(lag)) // отсчет absTS финального узла интерполяции
221NumMax := maxN.SliceVec(0, Nmax+1)
222
223// Интерполяция огибающей АКФ
224
225// acfEnvelope := pchip.Pchip(Vec_in_ArrFloat(NumMax),
226// oss.Vec_in_ArrFloat(maxTS.SliceVec(0, Nmax+1)),
227// (lgl),
228// NumMax.Len(), len(lgl))
229
230acfEnvelope, _, _ := pchip.Pchip(oss.Vec_in_ArrFloat(NumMax), oss.Vec_in_ArrFloat(maxTS.SliceVec(0, Nmax+1)), lgl, NumMax.Len(), len(lgl))
231
232//fmt.Println(len(lgl), NumMax.Len())
233//acfEnvelope := pchip.Pchip2(lgl, oss.Vec_in_ArrFloat(NumMax))
234
235//fmt.Println(Nmax, len(lgl))
236
237EnvAcf_sET12.SetCol(j, acfEnvelope)
238
239// нормированные АКФ
240AcfNrm_sET12.SetCol(j, oss.VecDense_in_float64(oss.Vector_DivElemVec((Acf_sET12.Slice(0, lag, j, j+1)), EnvAcf_sET12.ColView(j))))
241
242//fmt.Println(AcfNrm_sET12.At(lag-1, j)) // Тут возникает 850+ для 16-ти
243}
244
245// Обход ошибки вывода с 856, заменив последнюю строку
246EnvAcf_sET12 = oss.EditLastRow(EnvAcf_sET12)
247AcfNrm_sET12 = oss.EditLastRow(AcfNrm_sET12)
248
249// *****************
250oss.SafeToXlsxM(EnvAcf_sET12, "EnvAcf_sET12")
251oss.SafeToXlsxM(AcfNrm_sET12, "AcfNrm_sET12")
252
253// 6 - Огибающие АКФ сингулярных троек sET12 сегментов pw
254oss.Matlab_arr_float(ns, 6, "ns", "")
255oss.Matlab_arr_float(time, 6, "time", "")
256oss.Matlab_mat_Dense(&EnvAcf_sET12, 6, "EnvAcf_sET12", "")
257log.Println("Огибающие АКФ сингулярных троек sET12 сегментов pw")
258graph.SaveDat_2(EnvAcf_sET12, "File_For_MatLab"+oss.OpSystemFilder+strconv.Itoa(6)+oss.OpSystemFilder+"EnvAcf_sET12"+".dat")
259graph.SaveDat(ns, "File_For_MatLab"+oss.OpSystemFilder+strconv.Itoa(6)+oss.OpSystemFilder+"ns"+".dat")
260graph.SaveDat(time, "File_For_MatLab"+oss.OpSystemFilder+strconv.Itoa(6)+oss.OpSystemFilder+"time"+".dat")
261
262// 7 - Нормированные АКФ сингулярных троек sET12 сегментов pw
263oss.Matlab_arr_float(ns, 7, "ns", "")
264oss.Matlab_arr_float(time, 7, "time", "")
265oss.Matlab_mat_Dense(&AcfNrm_sET12, 7, "AcfNrm_sET12", "")
266Folder7 := "File_For_MatLab" + oss.OpSystemFilder + strconv.Itoa(7) + oss.OpSystemFilder
267graph.SaveDat_2(AcfNrm_sET12, Folder7+"AcfNrm_sET12"+".dat")
268graph.SaveDat(ns, Folder7+"ns"+".dat")
269graph.SaveDat(time, Folder7+"time"+".dat")
270graph.SplotMatrixFromFile(graph.Option3D{ // Задаём настройки 3D графика
271FileNameDat: Folder7 + "AcfNrm_sET12.dat",
272FileNameOut: Folder7 + "AcfNrm_sET12.png",
273Titile: "Нормированные АКФ сингулярных троек sET12 сегментов pw",
274Xlabel: "ns",
275Ylabel: "lag,s",
276Zlabel: "Acf_Nrm",
277}) // Делаем график
278log.Println("Нормированные АКФ сингулярных троек sET12 сегментов pw")
279
280// ********************************************************************
281// Мгновенная частота нормированной АКФ сингулярных троек sET12 для сегментов pw
282insFrc_AcfNrm, insFrc_AcfNrmErr := Instantaneous_frequency_of_normalized_ACF_sET12(AcfNrm_sET12, S, lag, dt, lgl)
283if insFrc_AcfNrmErr != nil {
284log.Println(insFrc_AcfNrmErr)
285}
286
287// filter savitzky-goley
288filter, savitzky_goley_Error := savitzkygolay.NewFilterWindow(53)
289if savitzky_goley_Error != nil {
290log.Fatalln(savitzky_goley_Error)
291}
292smo_insFrc_AcfNrm, _ := filter.Process(insFrc_AcfNrm, lgl)
293//smo_insFrc_AcfNrm := insFrc_AcfNrm
294
295//smo_insFrc_AcfNrm := savitzky_goley(insFrc_AcfNrm, 33, 2)
296
297oss.Matlab_arr_float(ns, 8, "ns", "")
298oss.Matlab_arr_float(insFrc_AcfNrm, 8, "insFrc_AcfNrm", "")
299oss.Matlab_arr_float(smo_insFrc_AcfNrm, 8, "smo_insFrc_AcfNrm", "")
300err_insFrc_AcfNrm := graph.MakeGraphYX_float64(
301insFrc_AcfNrm,
302ns,
303"insFrc_AcfNrm")
304if err_insFrc_AcfNrm != nil {
305fmt.Println(err_insFrc_AcfNrm)
306}
307err_insFrc_AcfNrm = graph.MakeGraphYX_float64(
308smo_insFrc_AcfNrm,
309ns,
310"smo_insFrc_AcfNrm")
311if err_insFrc_AcfNrm != nil {
312fmt.Println(err_insFrc_AcfNrm)
313}
314err_insFrc_AcfNrm = graph.MakeGraphYX_VecDense(
315*mat.NewVecDense(len(ns), ns),
316*mat.NewVecDense(len(insFrc_AcfNrm), insFrc_AcfNrm),
317*mat.NewVecDense(len(smo_insFrc_AcfNrm), smo_insFrc_AcfNrm),
318"origin", "insFrc_AcfNrm")
319if err_insFrc_AcfNrm != nil {
320fmt.Println(err_insFrc_AcfNrm)
321}
322
323// Оценки СПМ сингулярных троек для сегменов pw
324var iGmin, iGmax int
325smopto := 3 // параметр сглаживания периодограммы Томсона
326// Визуализация СПМ сингулярных троек сегменов pw
327fmi := 40.0 / 60.0 // частота среза для 40 уд/мин (0.6667 Гц)
328fma := 240.0 / 60.0 // частота среза для 240 уд/мин (4.0 Гц)
329Nf := 1 + win/2 // кол-во отсчетов частоты
330df := float64(cad) / float64(win-1) // интервал дискретизации частоты, Гц
331Fmin := fmi - float64(10*df) // частота в Гц, min
332Fmax := fma + float64(10*df) // частота в Гц, max
333pto_sET12 := pto_sET12_init(*sET12, *spw, smopto, win, Nf, S) // Расчёт оценки СПМ сингулярных троек для сегменов pw
334oss.SafeToXlsxMatrix(pto_sET12, "pto_sET12") // Сохранить в Xlsx матрицу оценки СПМ
335
336f := make([]float64, Nf)
337for i := 2; i < Nf; i++ {
338f[i] = f[i-1] + df // частота в герцах
339if math.Abs(f[i]-Fmin) <= df {
340iGmin = i
341}
342if math.Abs(f[i]-Fmax) <= df {
343iGmax = i
344}
345}
346fG := make([]float64, iGmax)
347for i := 0; i < iGmax; i++ {
348fG[i] = f[i] // сетка частот 3D-графика
349}
350oss.Matlab_arr_float(ns, 9, "ns", "")
351oss.Matlab_arr_float(fG, 9, "fG", "")
352oss.Matlab_mat_Dense(pto_sET12, 9, "pto_sET12", "")
353oss.Matlab_variable(iGmin, 9, "iGmin", "")
354oss.Matlab_variable(iGmax, 9, "iGmax", "")
355
356// Оценки средних частот основного тона сингулярных троек сегментов pw
357pto_fMAX12 := make([]float64, S)
358for index := range pto_fMAX12 {
359_, I := oss.MaxArrFloat64(oss.Vec_in_ArrFloat(pto_sET12.ColView(index))) // Поиск индекса максимального значения массива
360pto_fMAX12[index] = f[I]
361}
362oss.Matlab_arr_float(ns, 10, "ns", "")
363oss.Matlab_arr_float(pto_fMAX12, 10, "pto_fMAX12", "")
364err_pto_fMAX12 := graph.MakeGraphYX_float64(
365pto_fMAX12,
366ns,
367"pto_fMAX12")
368if err_pto_fMAX12 != nil {
369fmt.Println(err_pto_fMAX12)
370}
371Folder9 := "File_For_MatLab" + oss.OpSystemFilder + strconv.Itoa(9) + oss.OpSystemFilder
372graph.SaveDat_2(*pto_sET12, Folder9+"pto_sET12"+".dat")
373graph.SaveDat(ns, Folder9+"ns"+".dat")
374graph.SaveDat(time, Folder9+"time"+".dat")
375
376graph.SplotMatrixFromFile(graph.Option3D{ // Задаём настройки 3D графика
377FileNameDat: Folder9 + "pto_sET12.dat",
378FileNameOut: Folder9 + "pto_sET12.png",
379Titile: "Периодограмма Блэкмана–Харриса sET12 сегментов pw",
380Xlabel: "ns",
381Ylabel: "f,Hz",
382Zlabel: "P(f)",
383}) // Делаем график
384
385log.Println("Нормированные АКФ сингулярных троек sET12 сегментов pw")
386
387// oss.SafeToXlsx(f, "f")
388
389// ***
390// Агрегирование сегментов очищенной пульсовой волны cpw
391NSF := win + res*(S-1) // номер финального отсчета финального сегмента <= N
392NumS, cpw_avr, cpw_med, cpw_iqr := wav(NSF, S, win, res, *sET12)
393oss.SafeToXlsx(NumS, "NumS")
394
395oss.Matlab_variable(NSF, 10, "NSF", "")
396oss.Matlab_arr_float(tim, 10, "tim", "")
397oss.Matlab_arr_float(cpw_avr, 10, "cpw_avr", "")
398oss.Matlab_arr_float(cpw_med, 10, "cpw_med", "")
399oss.Matlab_arr_float(cpw_iqr, 10, "cpw_iqr", "")
400}
401*/
402func timer(name string) func() {403start := time.Now()404return func() {405fmt.Printf("%s took %v\n", name, time.Since(start))406}407}
408func wav(N, S, W, res int, sET mat.Dense) ([]float64, []float64, []float64, []float64) {409NS := make([]float64, N)410w_avr := make([]float64, N)411w_med := make([]float64, N)412w_iqr := make([]float64, N)413
414ET := mat.NewDense(N, S, nil)415
416for j := 0; j < S; j++ { // цикл по сегментам417for i := 0; i < W; i++ {418k := (j) * res419//fmt.Print(i, k, j, "=")420//fmt.Println(sET.At(i, j))421ET.Set(i+k, j, sET.At(i, j)) // сдвинутый сегмент ET(:,j)422}423}424
425Smp := make([]float64, N*S)426for i := 0; i < N; i++ {427var nSi int428for j := 0; j < S; j++ {429if ET.At(i, j) != 0.0 {430nSi++431Smp[nSi] = ET.At(i, j)432}433}434NS[i] = float64(nSi) // кол-во сегментов для текущего i435w_avr[i] = oss.Mean(Smp[:nSi]) // выборочная средняя436w_med[i] = oss.Median_floatArr(Smp[:nSi]) // медиана437w_iqr[i] = (oss.Prctile(Smp[:nSi], 75) - oss.Prctile(Smp[:nSi], 25)) / 2.0438}439
440return NS, w_avr, w_med, w_iqr441}
442
443// Формирование оценки СПМ сингулярных троек для сегменов pw
444func pto_sET12_init(sET12 mat.Dense, spw mat.Dense, smopto, win, Nf, S int) *mat.Dense {445pto_sET12 := mat.NewDense(Nf, S, nil)446
447// Расчёт окна Блэкмана_Харриса шириной win448// и с заданными коэффициентами449BlackManHar := blackmanharris.Blackmanharris(win, blackmanharris.Koef4_74db)450
451for j := 0; j < S; j++ {452// Периодограмма Блэкмана_Харриса453// pto_sET12(:,j) = periodogram(spw(:,j),blackmanharris(win),win); % Блэкмана-Харриса454pto_sET12.SetCol(j, periodogram.Periodogram(oss.Vec_in_ArrFloat(spw.ColView(j)), BlackManHar, win))455
456// Периодограмма Томсона457// pto_sET12.SetCol(j, pmtmMy(sET12.ColView(j), smopto, win))458}459return pto_sET12460}
461
462// func pmtmMy(sET12 mat.Vector, smopto, win int) []float64 {
463// return pmtm.Pmtm(oss.Vec_in_float64(sET12), 1024)
464// }
465
466// Расчёты вектора PhaAcfNrm, модуль от Акосинуса.
467func MakePhaAcfNrm(vect mat.Vector) *mat.VecDense {468output := mat.VecDenseCopyOf(vect)469for i := 0; i < output.Len(); i++ {470output.SetVec(i, math.Abs(math.Acos(output.AtVec(i))))471}472return output473}
474