gitee.com/quant1x/num@v0.3.2/wave.go (about)

     1  package num
     2  
     3  import "cmp"
     4  
     5  // QuantizationFactor 量化因子接口
     6  type QuantizationFactor interface {
     7  	// Normalize 归一化, 标准化, 数据预处理
     8  	Normalize()
     9  }
    10  
    11  func PeeksAndValleys[E Number](x []E) (peeks, valleys []int) {
    12  	return
    13  }
    14  
    15  // 波浪 wave 波峰波谷
    16  type wave struct {
    17  	data        []float64 // 原始数据
    18  	diff        []int     // 一阶差分
    19  	peakIndex   []int     // 波峰位置存储
    20  	valleyIndex []int     // 波谷位置存储
    21  	peakCount   int       // 所识别的波峰计数
    22  	valleyCount int       // 所识别的波谷计数
    23  }
    24  
    25  // InitPV 创建并初始化波峰波谷
    26  func initWave(data []float64) *wave {
    27  	n := len(data)
    28  	if n == 0 {
    29  		return nil
    30  	}
    31  	pv := wave{
    32  		data:        data,
    33  		diff:        make([]int, n),
    34  		peakIndex:   make([]int, n),
    35  		valleyIndex: make([]int, n),
    36  	}
    37  	for i := 0; i < n; i++ {
    38  		pv.diff[i] = 0
    39  		pv.peakIndex[i] = -1
    40  		pv.valleyIndex[i] = -1
    41  	}
    42  	pv.peakCount = 0
    43  	pv.valleyCount = 0
    44  	return &pv
    45  }
    46  
    47  // Normalize 归一化, 预处理
    48  // 前向差分
    49  func (this *wave) Normalize() {
    50  	n := len(this.data)
    51  	//step 1: 首先进行前向差分,并归一化
    52  	for i := 0; i < n-1; i++ {
    53  		c := this.data[i]
    54  		b := this.data[i+1]
    55  		if b-c > 0 {
    56  			this.diff[i] = 1
    57  		} else if b-c < 0 {
    58  			this.diff[i] = -1
    59  		} else {
    60  			this.diff[i] = 0
    61  		}
    62  		this.diff[i] = cmp.Compare(b, c)
    63  	}
    64  }
    65  
    66  // Find 找波峰波谷
    67  func (this *wave) Find() {
    68  	n := len(this.data)
    69  	//step 1: 首先进行前向差分,并归一化
    70  	for i := 0; i < n-1; i++ {
    71  		c := this.data[i]
    72  		b := this.data[i+1]
    73  		sampleDiff := b - c
    74  		if sampleDiff > 0 {
    75  			this.diff[i] = 1
    76  		} else if sampleDiff < 0 {
    77  			this.diff[i] = -1
    78  		} else {
    79  			this.diff[i] = 0
    80  		}
    81  	}
    82  
    83  	// step 2: 对相邻相等的点进行领边坡度处理
    84  	for i := 0; i < n-1; i++ {
    85  		if this.diff[i] == 0 {
    86  			if i == (n - 2) {
    87  				if this.diff[i-1] >= 0 {
    88  					this.diff[i] = 1
    89  				} else {
    90  					this.diff[i] = -1
    91  				}
    92  			} else {
    93  				if this.diff[i+1] >= 0 {
    94  					this.diff[i] = 1
    95  				} else {
    96  					this.diff[i] = -1
    97  				}
    98  			}
    99  		}
   100  	}
   101  	// step 3: 对相邻相等的点进行领边坡度处理
   102  	for i := 0; i < n-1; i++ {
   103  		sampleDiff := this.diff[i+1] - this.diff[i]
   104  		if sampleDiff == -2 {
   105  			// 波峰识别
   106  			this.peakIndex[this.peakCount] = i + 1
   107  			this.peakCount++
   108  		} else if sampleDiff == 2 {
   109  			// 波谷识别
   110  			this.valleyIndex[this.valleyCount] = i + 1
   111  			this.valleyCount++
   112  		}
   113  	}
   114  }