-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.py
396 lines (315 loc) · 12.9 KB
/
main.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
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
## Jack Collins, Final Year Project, National University of Ireland Galway, 2017
## written for Python2.7
## This file defines calculates the emission an observer at various angles to the
## rotation axis would see
from classStar import *
from classFieldline import *
import matplotlib.pyplot as plt
from visual import *
from time import time
import numpy as np
from scipy.ndimage.filters import gaussian_filter
#asks user which star to model
def specifyStarParameters():
#load list of already saved pulsars
starInfo = {}
try:
f = open("savedStars.txt", 'r')
print("Saved stars are ")
for line in f.readlines():
info = line.split(",")
starName = info.pop(0)
print(starName)
starInfo[starName] = info
f.close()
except:
print("No saved stars")
#ask user input
starName = raw_input("Type name of saved pulsar or \'new\': ")
if starName == "new":
R = float(raw_input("Radius of star (km): "))
P = float(raw_input("Period of rotation (s): "))
chi = float(raw_input("Inclination of magnetic axis to rotational axis (degrees): "))
name = raw_input("If you would like to save this star enter a name (to skip hit Enter): ")
if name != "":
f = open("savedStars.txt", 'w')
f.write(",".join([name,R,P,chi]))
else:
(R, P, chi) = [float(item) for item in starInfo[starName]]
star = Star(R, P, chi)
return star
#plots graph of emissions
def plotEmissions(emissions, chi=-1, rad=-1):
em = gaussian_filter(np.asarray(emissions), sigma=3)
plt.figure(figsize=(10,5))
plt.pcolor(em, vmin=0, vmax=1.8)
plt.axis([360,0,180,0])
#show color scale
plt.xlabel(r'Phase $\phi$ (degrees)', {'size':'15'})
plt.ylabel("Observer Viewing Angle (degrees)", {'size':'15'})
if chi >= 0:
plt.text(360, 175, r'$\chi=$' + str(chi)+r'$^{\circ}$', size=20, color='white')
if rad >= 0:
plt.text(360, 175, str(rad)+r'$R_{LC}$', size=20, color='white')
plt.colorbar()
plt.show()
return 0
#saves matrix of emissions WITHOUT BLUR to file
def saveEmissions(emissions):
fname = raw_input("Enter a name for the emissions file: ")
if fname == "":
print("Not saved")
return 0
f = open("savedEmissions/"+fname+".txt", 'w')
for line in emissions:
f.write(str(line)[1:-1] + "\n")
f.close()
print("File saved")
return 0
#saves polar cap angles
def savePC(angles, filename):
f = open("savedPolarCapPoints/"+filename+".txt", 'w')
f.write(str(angles)[1:-1])
f.close()
def readPC(filename):
f = open("savedPolarCapPoints/"+filename+".txt", "r")
points = f.read()[1:-1].split("), (")
f.close()
thetas = []
for point in points:
thetas.append(float(point.split(", ")[1]))
return(thetas)
#plots the shape of the polar cap for a given magnetic inclination angle
def plotPCPoints(angle):
file = "fifthBandAngle" + str(angle) + "PolarCapPoints"
thetas = readPC(file)
#create x-y points to plot birds eye view
x = []
y = []
for i in range(360):
phi = deg2rad(i - 90) # rotate plot by 90 so phi = 0 is in negative y direction - easier to see change
x.append(thetas[i]*cos(phi))
y.append(thetas[i]*sin(phi))
plt.figure(figsize=(16,16))
plt.scatter(x,y)
plt.scatter(0,0, marker='x', color='black', s=1000)
plt.arrow(0, 0, 0, -3, head_width=0.5, head_length=1, fc='k', ec='k')
plt.text(1, 0.5, "velocity", size=40)
plt.arrow(0, 0, 3, 0, head_width=0.5, head_length=1, fc='k', ec='k')
plt.text(0, -2.5, r'$\phi = 0^{\circ}$', size=40)
plt.text(-10, 10, r'$\chi = $'+str(angle)+r'$^{\circ}$', size=80)
plt.grid(True)
plt.axis([-12,12,-12,12])
plt.show()
return 0
#finds the staring position of the last open field line for a particular value of phi
#probably should start with a smaller theta, or take a minimum theta guess as a parameter
#probably won't work for crab
def findPC(star, phi, decimalPlaces):
theta = 0.1
line = Fieldline(star, phi, theta)
for i in range(decimalPlaces+1):
stepSize = 10**(-i)
while line.isOpen:
theta += stepSize
line = Fieldline(star, phi, theta)
theta -= stepSize
line = Fieldline(star, phi, theta)
return theta #degrees
#plots theta vs phi for the polar cap
def plotPC():
ns = specifyStarParameters()
#ns.setOtherk()
startTime = time()
PCAngles = []
phi_range = np.arange(0,360,30)
for phi in phi_range:
print("phi: ", phi)
PCAngles.append(findPC(ns, phi, 1))
print("Time elapsed:", time() - startTime)
print(PCAngles)
plt.plot(PCAngles)
plt.show()
return PCAngles
#outputs the emissions view of a particular observer angle
def observerView(emissions, obsAng):
em = gaussian_filter(np.asarray(emissions), sigma=3)
observedEmissions = np.fliplr(em)[obsAng] #flipping because star rotates oposite direction to increasing phi
plt.plot(observedEmissions)
plt.xlabel("phase (degrees)")
plt.ylabel("relative emission")
plt.text(5, 1.55, str(obsAng)+r'$^{\circ}$', size=20)
plt.axis([0,360,0,1.7])
plt.show()
return 0
#plots emissions from a band with specified inner radius to the edge of the polar cap
def innerCircleToPolarCap():
ns = specifyStarParameters()
#ns.setOtherk()
startTime = time()
emissions = [[0.0]*360 for i in range(180)]
for phi in np.arange(0,360,1):
print("phi: ", phi)
theta = 2.0 #inner radius
line = Fieldline(ns, phi, theta, False)
#for theta in np.arange(1,theta_max, 0.1):
while line.isOpen:
(phi_emis, theta_emis) = line.emissionDirections[0]
emissions[int(round(theta_emis))][int(round(phi_emis)) % 360] += 1.0
theta += 0.5
line = Fieldline(ns, phi, theta, False)
print("theta PC (degrees): ", theta)
plotEmissions(emissions)
print("Time elapsed:", time() - startTime)
obsAng = int(raw_input("Enter the observers angle (or 0 to quit): "))
while obsAng > 0:
plt.plot(emissions[obsAng])
plt.xlabel("phi (degrees)")
plt.ylabel("relative emission")
plt.show()
obsAng = int(raw_input("Enter the observers angle (or 0 to quit): "))
return 0
#draws a star with field lines at theta = 5, 10, 15 degrees
def visualise3D():
ns = specifyStarParameters()
#ns.setOtherk()
startTime = time()
#draw star, rotational axis, light cylinder, magnetosphere
ns.draw(3, 5, 10)
ns.animate()
#output instructions for manipulation
print("To zoom in/out, hold down the scroll wheel and move the mouse forward/backward.")
print("To move star, hold down the right mouse button to grab, and move the mouse.")
print("Time elapsed:", time() - startTime)
return 0
#this plots emissions using square angular coordinates to get a more equal distribution
def plotUsingNewCoords():
ns = specifyStarParameters()
#ns.setOtherk()
startTime = time()
theta_max = max(findPC(ns, 0, 2), findPC(ns, 90, 2))
increment_size= 0.2
limit = deg2rad(0.01)
emissions = [[0.0]*360 for i in range(180)]
for A in np.arange(-theta_max,theta_max,increment_size):
print("A ", A)
Adeg = A
A = deg2rad(A)
x = sin(A)
for B in np.arange(-theta_max,theta_max,increment_size):
#print("A, B: ", Adeg, B)
B = deg2rad(B)
y = sin(B)
z = cos(A)*cos(B)
position = vector(x,y,z)
#print("A,B ", A,B)
if abs(A) < limit and abs(B) < limit:
#don't try to create a field line too close to the magnetic pole
print("here!")
break
(x, y, z) = position/mag(position)
theta = rad2deg(acos(z))
phi = rad2deg(atan2(y, x))
#print(position)
#print(ns, phi, theta, False, 100)
#rate(5)
line = Fieldline(ns, phi, theta, False)
if line.isOpen:
print(phi, theta)
(phi_emis, theta_emis) = line.emissionDirections[0]
emissions[int(round(theta_emis))][int(round(phi_emis)) % 360] += 1.0
print("Time elapsed:", time() - startTime)
plotEmissions(emissions)
saveEmissions(emissions)
obsAng = int(raw_input("Enter the observers angle (or 0 to quit): "))
while obsAng > 0:
plt.plot(emissions[obsAng])
plt.xlabel("phi (degrees)")
plt.ylabel("relative emission")
plt.show()
obsAng = int(raw_input("Enter the observers angle (or 0 to quit): "))
return 0
#One function to rule them all, one function to find them, One function to bring them all and in the darkness bind them.
def emissionsFromBand(chi, emissionRadii):
ns = Star(10, 0.03, chi)
#ns.setOtherk()
startTime = time()
emissionBandThickness = 0.2 #degrees
stepSize = 0.02
#find (roughly) biggest incircle of polar cap and come in slightly more than required for calculations
polarCapDistances = []
for angle in [0, 45, 90, 135, 180, 200, 225, 270, 315, 360]:
polarCapDistances.append(findPC(ns, angle, 2))
theta_min = min(polarCapDistances) - emissionBandThickness - 5*stepSize
emissions = [ [[0.0]*360 for i in range(180)] for j in range(len(emissionRadii))]
polarCapPoints = []
for phi in np.arange(0,360,1):
print("phi: ", phi)
theta = theta_min
line = Fieldline(ns, phi, theta, False, emissionRadii)
listOfEmittingFieldlinesFromThisPhi = []
while line.isOpen:
listOfEmittingFieldlinesFromThisPhi.append(line.emissionDirections)
theta += stepSize
line = Fieldline(ns, phi, theta, False, emissionRadii)
print("This should be the same number always: ", len(listOfEmittingFieldlinesFromThisPhi[-int(round(emissionBandThickness/stepSize)):]))
for individualFieldline in listOfEmittingFieldlinesFromThisPhi[-int(round(emissionBandThickness/stepSize)):]: #we only want emissions from within 'emissionBandThickness' of last open field lines
for i in range(len(individualFieldline)):
(phi_emis, theta_emis) = individualFieldline[i]
emissions[i][int(round(theta_emis))][int(round(phi_emis)) % 360] += 1.0
#print("theta PC (degrees): ", theta)
polarCapPoints.append((phi,theta))
#savePC(polarCapPoints, "fifthBandAngle"+str(chi)+"PolarCapPoints")
for i in range(len(emissionRadii)):
fname = "distChangeRadius"+str(emissionRadii[i])+"Angle"+str(chi)
f = open("savedEmissions/"+fname+".txt", 'w')
for line in emissions[i]:
f.write(str(line)[1:-1] + "\n")
f.close()
print("File saved")
print("Time elapsed:", time() - startTime)
return 0
#calculates and saves the emissions from stars with multiple of 10 degree magnetic inclination
#can take long to run
def batchCalculate():
emissionRadius = int(raw_input("Enter emission distance to light cylinder (% LC): "))
startTime = time()
for chi in range(0, 100, 10):
print("chi: ", chi)
try:
emissionsFromBand(chi, [emissionRadius])
except:
print("It failed oh no .. KEEP GOING")
print("TOTAL TIME TAKEN = ", time() - startTime)
#Reads from emissions file and returns array of emissions
def readFromFile(filename):
f = open("savedEmissions/"+filename, 'r')
emissions = []
for line in f:
emissions.append([float(item) for item in line[:-1].split(", ")])
return emissions
'''
#sample code for plotting from saved files
name1 = "fifthBandRadius0.5Angle"
name2 = "distChangeRadius0.5Angle60.txt"
for i in range(1, 10):
emissions = readFromFile("distChangeRadius"+str(i/10.0)+"Angle45.txt")
plotEmissions(emissions, rad=i/10.0)
'''
'''
#sample code for calculating emission from range of distances for specid chi
chi = int(raw_input("Enter chi: "))
emRads = [item/10.0 for item in [1,2,3,4,5,6,7,8,9]]
print(emRads)
emissionsFromBand(chi, emRads)
'''
if __name__ == "__main__":
# your code goes here
print("edit main function to your own specifications")
'''NOTES
SAVE THESE USING 3D ARRAY - done
WHEN SAVING EMISSIONS, SPLIT INTO SEVERAL FILES SO THAT PLOTTING STILL WORKS - done
MAKE FUNCTION THAT RUNS FOR DIFFERENT CHI AND RUN THESE IN PARALLEL - done
PLOT ALL FIELD LINES IN POLAR CAP - avoided? Avoided woo!
CHECK MORE POINTS FOR MIN POLAR CAP THETA - done
'''