1 #Region "Microsoft.VisualBasic::b6b463990d38f7ac9a00f014387bd5d7, Microsoft.VisualBasic.Core\Extensions\Math\ScaleMaps.vb"
2
3     ' Author:
4     
5     '       asuka (amethyst.asuka@gcmodeller.org)
6     '       xie (genetics@smrucc.org)
7     '       xieguigang (xie.guigang@live.com)
8     
9     ' Copyright (c) 2018 GPL3 Licensed
10     
11     
12     ' GNU GENERAL PUBLIC LICENSE (GPL3)
13     
14     
15     ' This program is free software: you can redistribute it and/or modify
16     ' it under the terms of the GNU General Public License as published by
17     ' the Free Software Foundation, either version 3 of the License, or
18     ' (at your option) any later version.
19     
20     ' This program is distributed in the hope that it will be useful,
21     ' but WITHOUT ANY WARRANTY; without even the implied warranty of
22     ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     ' GNU General Public License for more details.
24     
25     ' You should have received a copy of the GNU General Public License
26     ' along with this program. If not, see <http://www.gnu.org/licenses/>.
27
28
29
30     ' /********************************************************************************/
31
32     ' Summaries:
33
34     '     Module ScaleMaps
35     
36     '         Function: (+4 Overloads) GenerateMapping, (+3 Overloads) Log2Ranks, LogLevels, MapHelper, Scale
37     '                   TrimRanges
38     
39     
40     ' /********************************************************************************/
41
42 #End Region
43
44 Imports System.Runtime.CompilerServices
45 Imports Microsoft.VisualBasic.CommandLine.Reflection
46 Imports Microsoft.VisualBasic.ComponentModel.Collection.Generic
47 Imports Microsoft.VisualBasic.Language
48 Imports Microsoft.VisualBasic.Linq
49 Imports Microsoft.VisualBasic.Linq.Extensions
50 Imports Microsoft.VisualBasic.Scripting.MetaData
51 Imports sys = System.Math
52
53 Namespace Math
54
55     <Package("ScaleMaps",
56                   Category:=APICategories.UtilityTools,
57                   Publisher:="xie.guigang@live.com")>
58     Public Module ScaleMaps
59
60         ''' <summary>
61         ''' Trims the data ranges, 
62         ''' if n in <paramref name="Dbl"/> vector is less than <paramref name="min"/>, then set n = min;
63         ''' else if n is greater than <paramref name="max"/>, then set n value to max, 
64         ''' else do nothing.
65         ''' </summary>
66         ''' <param name="Dbl"></param>
67         ''' <param name="min"></param>
68         ''' <param name="max"></param>
69         ''' <returns></returns>
70         <Extension> Public Function TrimRanges(Dbl As Double(), min As Double, max As DoubleAs Double()
71             If Dbl.IsNullOrEmpty Then
72                 Return New Double() {}
73             End If
74
75             For i As Integer = 0 To Dbl.Length - 1
76                 Dim n As Double = Dbl(i)
77
78                 If n < min Then
79                     n = min
80                 ElseIf n > max Then
81                     n = max
82                 End If
83
84                 Dbl(i) = n
85             Next
86
87             Return Dbl
88         End Function
89
90         <ExportAPI("Ranks.Mapping")>
91         <Extension> Public Function GenerateMapping(Of T As INamedValue)(
92                                                     data As IEnumerable(Of T),
93                                                getSample As Func(Of T, Double),
94                                           Optional Level As Integer = 10) As Dictionary(Of StringInteger)
95
96             Dim samples As Double() = data.Select(getSample).ToArray
97             Dim levels As Integer() = samples.GenerateMapping(Level)
98             Dim hash = data _
99                 .SeqIterator _
100                 .Select(Function(x) (x.value.Key, levels(x.i))) _
101                 .ToArray
102
103             Return hash.ToDictionary(
104                 Function(tp) tp.Item1,
105                 Function(tp) tp.Item2)
106         End Function
107
108         ''' <summary>
109         ''' Linear mappings the vector elements in to another scale within specifc range from parameter <paramref name="Level"></paramref>.
110         ''' (如果每一个数值之间都是相同的大小,则返回原始数据,因为最大值与最小值的差为0,无法进行映射的创建(会出现除0的错误))
111         ''' </summary>
112         ''' <param name="data">Your input numeric vector.</param>
113         ''' <param name="Level">The scaler range.</param>
114         ''' <returns></returns>
115         ''' <remarks>为了要保持顺序,不能够使用并行拓展</remarks>
116         ''' <param name="offset">
117         ''' The default scaler range output is [1, <paramref name="Level"></paramref>], but you can modify this parameter 
118         ''' value for moving the range to [<paramref name="offset"></paramref>, <paramref name="Level"></paramref> + <paramref name="offset"></paramref>].
119         ''' (默认是 [1, <paramref name="Level"></paramref>],
120         ''' 当offset的值为0的时候,则为[0, <paramref name="Level"></paramref>-1],
121         ''' 当然这个参数也可以使其他的值)
122         ''' </param>
123         <ExportAPI("Ranks.Mapping")>
124         <Extension> Public Function GenerateMapping(data As IEnumerable(Of Double), Optional Level As Integer = 10, Optional offset As Integer = 1) As Integer()
125             Dim array As Double() = data.ToArray
126
127             If array.Length = 0 Then
128                 Return {}
129             End If
130
131             Dim MinValue As Double = array.Min
132             Dim MaxValue As Double = array.Max
133             Dim d As Double = MaxValue - MinValue
134
135             If d = 0R Then ' 所有的值都是一样的,则都是同等级的
136                 Return 1.Repeats(array.Length)
137             End If
138
139             Dim chunkBuf As Integer() = New Integer(array.Length - 1) {}
140             Dim i As int = 0
141
142             For Each x As Double In array
143                 Dim lv As Integer = Fix(Level * (x - MinValue) / d)
144                 chunkBuf(++i) = lv + offset
145             Next
146
147             Return chunkBuf
148         End Function
149
150         <Extension>
151         Public Function LogLevels(data As IEnumerable(Of Double), base%, Optional level As Integer = 100) As Integer()
152             Dim logvalues = data.Select(Function(x) sys.Log(x, base)).ToArray
153             Return logvalues.GenerateMapping(level)
154         End Function
155
156         <ExportAPI("Ranks.Log2")>
157         <Extension> Public Function Log2Ranks(data As IEnumerable(Of Double), Optional Level As Integer = 100) As Integer()
158             Dim log2Value = data.Select(Function(x) sys.Log(x, 2)).ToArray
159             Return log2Value.GenerateMapping(Level)
160         End Function
161
162         <ExportAPI("Ranks.Log2")>
163         <Extension> Public Function Log2Ranks(data As IEnumerable(Of Integer), Optional Level As Integer = 10) As Integer()
164             Return data.Select(Function(d) CDbl(d)).Log2Ranks
165         End Function
166
167         <ExportAPI("Ranks.Log2")>
168         <Extension> Public Function Log2Ranks(data As IEnumerable(Of Long), Optional Level As Integer = 10) As Integer()
169             Return data.Select(Function(d) CDbl(d)).Log2Ranks
170         End Function
171
172         ''' <summary>
173         ''' 如果每一个数值之间都是相同的大小,则返回原始数据,因为最大值与最小值的差为0,无法进行映射的创建(会出现除0的错误)
174         ''' </summary>
175         ''' <param name="data"></param>
176         ''' <returns></returns>
177         ''' <remarks>为了要保持顺序,不能够使用并行拓展</remarks>
178         ''' 
179         <ExportAPI("Ranks.Mapping")>
180         <Extension> Public Function GenerateMapping(data As IEnumerable(Of Integer), Optional Level As Integer = 10, Optional offset% = 1) As Integer()
181             Return GenerateMapping((From n In data Select CDbl(n)).ToArray, Level, offset)
182         End Function
183
184         <ExportAPI("Ranks.Mapping")>
185         <Extension> Public Function GenerateMapping(data As IEnumerable(Of Long), Optional Level As Integer = 10) As Integer()
186             Return GenerateMapping((From n In data Select CDbl(n)).ToArray, Level)
187         End Function
188
189         ''' <summary>
190         ''' Function centers and/or scales the columns of a numeric matrix.
191         ''' </summary>
192         ''' <param name="data">numeric matrix</param>
193         ''' <param name="center">either a logical value or a numeric vector of length equal to the number of columns of x</param>
194         ''' <param name="isScale">either a logical value or a numeric vector of length equal to the number of columns of x</param>
195         ''' <returns></returns>
196         <ExportAPI("Scale"Info:="function centers and/or scales the columns of a numeric matrix.")>
197         Public Function Scale(<Parameter("x""numeric matrix")> data As IEnumerable(Of Double),
198                               <Parameter("center""either a logical value or a numeric vector of length equal to the number of columns of x")>
199                               Optional center As Boolean = True,
200                               <Parameter("scale""either a logical value or a numeric vector of length equal to the number of columns of x")>
201                               Optional isScale As Boolean = TrueAs Double()
202
203             Dim avg As Double = data.Average
204             Dim rms As Double = VBMath.RMS(data)
205
206             If center Then
207                 data = (From n In data Select n - avg).ToArray
208             End If
209
210             If isScale Then
211                 data = (From n In data Select n / rms).ToArray
212             End If
213
214             Return data.ToArray
215         End Function
216
217         <Extension>
218         Public Function MapHelper(Of T)(data As IEnumerable(Of T)) As Func(Of Integer, T)
219             Dim source As T() = data.ToArray
220
221             Return Function(level%)
222                        If level < 0 Then
223                            level = 0
224                        ElseIf level >= source.Length Then
225                            level = source.Length - 1
226                        End If
227
228                        Return source(level)
229                    End Function
230         End Function
231     End Module
232 End Namespace