-
Notifications
You must be signed in to change notification settings - Fork 0
/
calibratorFScore.py
241 lines (187 loc) · 7.48 KB
/
calibratorFScore.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
"""
Written by: Suren Gourapura
Date Written: 06/01/2019
Goal: Provide a fitness score for the calibratorMain.py code
Comments: There will be a main fitness score function called
FitnessMain. This will serve to choose which fitness
score will be used by the code. There will be a dummy
fitness score for now to emulate the real thing.
"""
import numpy as np
import os.path # For checking if indivHistory file exists
import util
import sys
def FitnessTest(pop, fitType, data, amp, phi0):
"""
This function is called by calibratorMain.py to choose the fitness
score type needed. It takes the population and an integer that
tells which fitness score the user wants. It returns the ranked
scores and ranked population to the calibratorMain.py.
"""
if fitType == 1:
scores = FScoreDummy(pop)
elif fitType == 2:
scores = FScoreReal(pop, data, amp, phi0)
elif fitType == -1: # Used for troubleshooting. Disregard
scores = np.ones((pop.shape[0]))
else:
print("Error: fitType value not 1 or 2")
return
# Integrate these new individuals and scores in the
# indivHistory.csv file
#UpdateIndivHistory(rScores, rPop, fitType)
return scores
#function to get the data and store it in a matrix.
#TODO: make nEvents a command line arg
def getData(channel,pop):
nEvents=50
#the maximum time value.
maxt=40.-.3125;
# the evenly sampled times.
eTimes=np.linspace(0., maxt, 128)
# zero-crossing period (.5 period over frequency), currently unused
zCPeriod=.5/1.2;
#container to hold the scores
scores = np.zeros((pop.shape[0])) # pop.shape[0] = popMax
#container to hold the true sample times (from the gA)
tVec=np.zeros(128);
#fill a matrix of our data events, would be nice to do this outside of the fitness score loop.
data=np.zeros((nEvents, 128))
phi0=np.zeros(nEvents)
amp=np.zeros(nEvents)
for event in range(nEvents):
#this is the data file.
#the first entry is the initial phase
#the second entry is the amplitude
#the rest of the entries are the waveform data
evstr="00"
chstr=str(channel)
#print chstr
if event < 10 :
evstr="00"+str(event)
elif event >= 10 and event < 100:
evstr="0"+str(event)
# print evstr
#infile="/users/PCON0003/osu10643/src/SignalCalibrationGA/data/"+chstr+"withphase"+evstr+".txt"
infile = "data/"+chstr+"withphase"+evstr+".txt"
#the max time of the 126th (indexed from 0) sample
temp=np.genfromtxt(infile, delimiter="\n")
phi0[event]=temp[0]
amp[event]=temp[1]
trace=temp[2:]
# phi0[event]=util.getInstPhase(eTimes,trace, 0)
data[event]=util.normalize(trace)
return data, amp, phi0
def FScoreDummy(pop):
"""
We grab a premade array of 126 random numbers between 0-1. These
values will be our target. To make a new random number array, use
the commented code below. To calculate the score, we simply
calculate the chi squared between our individual and the goal
values (goalVal).
"""
numNodes = pop.shape[1]
goalFile = "data/dummyScore/goalValues.csv"
goalVal = np.genfromtxt(goalFile, delimiter=",")[:numNodes]
# Now we create the fitness scores (scores) by calculating the
# Chi Squared in a loop
scores = np.zeros((pop.shape[0])) # pop.shape[0] = popMax
for i in range(pop.shape[0]):
# Sum of the chi sq of each delta t with the respective value
scores[i] = np.sum(((pop[i] - goalVal)**2)/goalVal)
# To minimize chi squared, we maximize 1/ chi squared
eps = 10**(-6)
return 1./(scores + eps)
def FScoreReal(pop, data, amp, phi0):
#progress indicator
#print (".")
#sys.stdout.flush()
#TODO:
#would be good to have an argument for the channel we're calibrating
#would be nice to make this an argument.
nEvents=data.shape[0]
#the maximum time value.
maxt=40.-.3125;
# the evenly sampled times.
eTimes=np.linspace(0., maxt, 128)
# zero-crossing period (.5 period over frequency), currently unused
zCPeriod=.5/1.2;
#container to hold the scores
scores = np.zeros((pop.shape[0])) # pop.shape[0] = popMax
#container to hold the true sample times (from the gA)
tVec=np.zeros(128);
for i in range(scores.size):
#set the times for entries above 0 to the individual values
tVec[1:]=pop[i]
#the sample times from the GA
rTimes=tVec+eTimes
for event in range(nEvents):
# print phi0[event], amp[event]
cw=util.sampledCW(1.2, amp[event], rTimes, phi0[event])
ipScore=np.dot(util.normalize(cw), data[event])
scores[i]+=ipScore
return scores/nEvents
def UpdateIndivHistory(rScores, rPop, fitType):
# Combine the scores and pop into one matrix. Each row has the
# score first, then it's associated individual. The rows are
# ranked best to worst.
currentData = np.hstack((rScores.reshape((rScores.shape[0],1)), \
rPop))
# Choose the file location based on the fitType
if fitType == 1:
fileName = "data/dummyScore/indivHistory.csv"
elif fitType == 2:
fileName = "data/realScore/indivHistory.csv"
if os.path.isfile(fileName) is False: # If the file does not exist
np.savetxt(fileName, currentData, delimiter=',')
else: # If the file exists
# We need to insert each element in the correct place in file
# Grab the history matrix
indivHist = np.genfromtxt(fileName, delimiter=',')
# Create a new combined dataset
combData = np.zeros((indivHist.shape[0]+currentData.shape[0], \
indivHist.shape[1]))
# We need an index for indivHist and for currentData
hInd, cInd = 0, 0
# For each future entry in combData
for i in range(combData.shape[0]):
# There are many cases to consider
# First, check if cInd is out of bounds for currentData
if cInd + 1 > currentData.shape[0]:
# If so, just copy over indivHist
combData[i] = indivHist[hInd]
hInd += 1
# Next, check if hInd is out of bounds for indivHist
elif hInd + 1 > indivHist.shape[0]:
# If so, just copy over currentData
combData[i] = currentData[cInd]
cInd += 1
# Now if we have values for both currentData and indivHist
# if the current data value is larger
elif currentData[cInd,0] > indivHist[hInd,0]:
# Copy over currentData's value
combData[i] = currentData[cInd]
cInd += 1
# Finally if we have values for currentData and indivHist,
# if the indivHist is larger (or equal to)
else:
# Copy over indivHist's value
combData[i] = indivHist[hInd]
hInd += 1
# Now, we rewrite indivHistory.csv with the new combData
np.savetxt(fileName, combData, delimiter=',')
return
"""
The below code writes a new goal string for the simple fitness score. It
generates 126 random numbers from 0 to 1 and stores it in a file with name
goalStr.
"""
"""
import random
strName = "goalString"
goalStr = np.zeros((126))
for i in range(126):
goalStr[i] = random.random()
print(goalStr)
np.savetxt('data/'+strName+'.csv', goalStr, delimiter=',')
"""