transitsong 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,9 @@
1
+ Metadata-Version: 2.4
2
+ Name: transitsong
3
+ Version: 0.0.1
4
+ Requires-Dist: numpy
5
+ Requires-Dist: sounddevice
6
+ Requires-Dist: lightkurve
7
+ Requires-Dist: matplotlib
8
+ Requires-Dist: scipy
9
+ Requires-Dist: moviepy
@@ -0,0 +1,2 @@
1
+ # sounds
2
+ sonification of transits
@@ -0,0 +1,21 @@
1
+ [build-system]
2
+ requires = [
3
+ "setuptools",
4
+ "numpy",
5
+ "cython",
6
+ "wheel"
7
+ ]
8
+ build-backend = "setuptools.build_meta"
9
+
10
+ [project]
11
+ name = "transitsong"
12
+ version = "0.0.1"
13
+
14
+ dependencies = [
15
+ "numpy",
16
+ "sounddevice",
17
+ "lightkurve",
18
+ "matplotlib",
19
+ "scipy",
20
+ "moviepy"
21
+ ]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,12 @@
1
+ from transitsong.main import Transit
2
+
3
+ # test that lightcurve downloads ok!
4
+
5
+ def test_lc_download():
6
+ tic = 124029677
7
+ sector = 33
8
+
9
+ transit = Transit(tic, sector)
10
+
11
+ assert len(transit.norm_flux) == len(transit.time), "Time and flux arrays are not the same length"
12
+ assert len(transit.norm_flux) > 0, "norm flux array, time array is of length 0"
File without changes
@@ -0,0 +1,243 @@
1
+ import lightkurve as lk
2
+ import matplotlib.pyplot as plt
3
+ import numpy as np
4
+ from scipy.io.wavfile import write
5
+ import sounddevice as sd
6
+ import matplotlib.animation as animation
7
+ from moviepy import *
8
+ from moviepy.video.fx import MultiplySpeed
9
+ import os
10
+ from pathlib import Path
11
+
12
+ # set matplotlib preferences
13
+ #plt.style.use(path + 'text.mplstyle')
14
+
15
+
16
+ class Transit:
17
+ """A program that makes an animation with audio for an input TESS lightcurve.
18
+
19
+ Attributes:
20
+ tic (int or str): TESS Input Catalog number
21
+ sector (int): TESS sector number
22
+ window (list of length 2): start and end days of sector
23
+ """
24
+
25
+ def __init__(self, tic, sector, window = None):
26
+ self.tic = tic
27
+ self.sector = sector
28
+ self.window = window
29
+
30
+ try:
31
+ search_result = lk.search_lightcurve(
32
+ f"TIC {tic}",
33
+ mission="TESS",
34
+ author="SPOC",
35
+ sector =[sector] )
36
+
37
+ lc = search_result.download()
38
+ self.success = True
39
+
40
+ except Exception as e:
41
+ self.success = False
42
+ raise ValueError("Failed to load lightcurve for TIC {} in sector {}: {}".format(tic, sector, str(e)))
43
+
44
+ print("Successfully loaded lightcurve for TIC {} in sector {}".format(tic, sector))
45
+
46
+ lc_binned = lc.bin(time_bin_size=0.01)
47
+
48
+ lc_binned = lc_binned.normalize()
49
+
50
+ lc_fluxes = lc_binned.flux.value
51
+ lc_times = lc_binned.time.value
52
+
53
+ #med_value = np.nanmedian(lc_fluxes)
54
+
55
+ #lc_normflux = lc_fluxes/med_value
56
+
57
+ self.time = lc_times
58
+ self.norm_flux = lc_fluxes
59
+
60
+
61
+ if window is not None:
62
+ new_times = []
63
+ new_fluxes = []
64
+
65
+ for i in range(len(self.time)):
66
+ if self.time[i] > window[0] and self.time[i] < window[1]:
67
+ new_times.append(self.time[i])
68
+ new_fluxes.append(self.norm_flux[i])
69
+
70
+ self.time = np.array(new_times)
71
+ self.norm_flux = np.array(new_fluxes)
72
+
73
+
74
+ def make_sound_arr(self, max_val=900, min_val=200):
75
+ """Sound array
76
+
77
+ Make sound array as .wav file, higher pitch corresponds to higher flux. Saves to subdirectory "song."
78
+
79
+ Args:
80
+ max_val (int or float): maximum Hz frequency
81
+ min_val (int or float): minimum Hz frequency
82
+
83
+ Returns:
84
+ Nothing.
85
+ """
86
+
87
+ mapped_flux = (self.norm_flux - np.nanmin(self.norm_flux)) / (np.nanmax(self.norm_flux) - np.nanmin(self.norm_flux)) * (max_val - min_val) + min_val
88
+
89
+ self.mapped_flux = mapped_flux
90
+
91
+ audio = []
92
+ len_points = []
93
+
94
+ samplerate = 44100
95
+ duration = 0.05
96
+
97
+ for flux in mapped_flux:
98
+ frequency = flux
99
+ t = np.linspace(0, duration, int(samplerate * duration), endpoint=False)
100
+
101
+ audio_signal = np.sin(2*np.pi*frequency*t)
102
+ audio_signal = audio_signal[~np.isnan(audio_signal)]
103
+ len_points.append(len(audio_signal))
104
+
105
+ audio.extend(audio_signal)
106
+
107
+ audio_arr = np.array(audio)
108
+ self.audio_arr = audio_arr
109
+
110
+ song_path = os.getcwd() + "/song/"
111
+ self.song_path = song_path
112
+ if not os.path.isdir(song_path):
113
+ directory = Path(song_path)
114
+ directory.mkdir(parents=True, exist_ok=True)
115
+
116
+ write(song_path + f"TIC{self.tic}_S{self.sector}_SONG.wav", samplerate, audio_arr)
117
+
118
+ # colors
119
+ cmap = plt.cm.magma
120
+
121
+ sorted_args = np.argsort(self.norm_flux)
122
+
123
+ values = np.linspace(0, 1, len(self.norm_flux))
124
+ colors = np.empty((len(self.norm_flux), 4)) # 4 for RGBA
125
+ colors[sorted_args] = cmap(values)
126
+
127
+ self.colors= colors
128
+
129
+ #sd.play(audio_arr, samplerate)
130
+ #sd.wait()
131
+
132
+
133
+ def make_video(self):
134
+ """Video file
135
+
136
+ Makes animated plot of lightcurve, lighter color corresponds to higher flux. Saves as .mp4 in subdirectory "dance".
137
+
138
+ Args:
139
+ None.
140
+
141
+ Returns:
142
+ Nothing.
143
+ """
144
+ # Original time
145
+ x_raw = self.time
146
+ y_raw = self.norm_flux
147
+
148
+ # Removing nans
149
+ y = y_raw[~np.isnan(y_raw)]
150
+ x = x_raw[~np.isnan(y_raw)]
151
+
152
+
153
+ fig, ax = plt.subplots()
154
+ line, = ax.plot([], [], marker='o', linestyle='', color='b')
155
+ ax.set_xlabel('Time (days)')
156
+ ax.set_ylabel('Normalized Flux')
157
+ ax.set_xlim(self.time[0], self.time[-1])
158
+ ax.set_ylim(np.nanmin(self.norm_flux)-0.005, np.nanmax(self.norm_flux)+0.005)
159
+ ax.set_title(f"TIC {self.tic} - Sector {self.sector}")
160
+
161
+
162
+ def update(i):
163
+
164
+ # line.set_data(x[:frame], y[:frame])
165
+ # line.set_color(self.colors[frame])
166
+
167
+ plt.scatter(x[:i], y[:i], color=self.colors[i], edgecolor="k", linewidth=0.5)
168
+
169
+ # return line,
170
+
171
+
172
+ ani = animation.FuncAnimation(
173
+ fig, update, frames=len(x), interval=50, repeat=True
174
+ )
175
+
176
+ dance_path = os.getcwd() + "/dance/"
177
+ self.dance_path = dance_path
178
+ if not os.path.isdir(dance_path):
179
+ directory = Path(dance_path)
180
+ directory.mkdir(parents=True, exist_ok=True)
181
+
182
+ ani.save(dance_path + f"TIC{self.tic}_S{self.sector}_DANCE.mp4", writer='ffmpeg', fps=30)
183
+ #plt.show()
184
+
185
+ def combine(self):
186
+ video_clip = VideoFileClip(self.dance_path + f"TIC{self.tic}_S{self.sector}_DANCE.mp4", audio=False)
187
+ audio_clip = AudioFileClip(self.song_path + f"TIC{self.tic}_S{self.sector}_SONG.wav")
188
+
189
+ video_factor = video_clip.duration / audio_clip.duration
190
+
191
+
192
+ video_clip = video_clip.with_effects([MultiplySpeed(video_factor)])
193
+
194
+
195
+ final_clip = video_clip.with_audio(audio_clip)
196
+
197
+ song_and_dance_path = os.getcwd() + "/song_and_dance/"
198
+ if not os.path.isdir(song_and_dance_path):
199
+ directory = Path(song_and_dance_path)
200
+ directory.mkdir(parents=True, exist_ok=True)
201
+
202
+ final_clip.write_videofile(
203
+ song_and_dance_path + f"TIC{self.tic}_S{self.sector}_FINAL.mp4",
204
+ codec="libx264",
205
+ audio_codec="aac",
206
+ temp_audiofile="temp-audio.m4a",
207
+ remove_temp=True,
208
+ )
209
+
210
+
211
+ video_clip.close()
212
+ audio_clip.close()
213
+ final_clip.close()
214
+
215
+ #def play_song(Transit):
216
+ # here is where we do the simultaneous thing?
217
+ #tic = 124029677
218
+ #sector = 33
219
+ #window = [2217, 2220]
220
+
221
+
222
+
223
+ # tic = 55652896
224
+ # sector = 63 #originally did 38
225
+ # window = [2340, 2341]
226
+
227
+ # tic = 149601126
228
+ # sector = 32 #96
229
+ # window = [2196, 2198.5]
230
+
231
+ # tic = 263930790
232
+ # sector = 73
233
+ # window = [3293, 3299]
234
+
235
+ # planet = Transit(tic, sector, window=window)
236
+ # planet.make_sound_arr()
237
+ # planet.make_video()
238
+ # planet.combine()
239
+
240
+
241
+ #55652896, 38, 63
242
+
243
+
@@ -0,0 +1,9 @@
1
+ Metadata-Version: 2.4
2
+ Name: transitsong
3
+ Version: 0.0.1
4
+ Requires-Dist: numpy
5
+ Requires-Dist: sounddevice
6
+ Requires-Dist: lightkurve
7
+ Requires-Dist: matplotlib
8
+ Requires-Dist: scipy
9
+ Requires-Dist: moviepy
@@ -0,0 +1,10 @@
1
+ README.md
2
+ pyproject.toml
3
+ tests/tests.py
4
+ transitsong/__init__.py
5
+ transitsong/main.py
6
+ transitsong.egg-info/PKG-INFO
7
+ transitsong.egg-info/SOURCES.txt
8
+ transitsong.egg-info/dependency_links.txt
9
+ transitsong.egg-info/requires.txt
10
+ transitsong.egg-info/top_level.txt
@@ -0,0 +1,6 @@
1
+ numpy
2
+ sounddevice
3
+ lightkurve
4
+ matplotlib
5
+ scipy
6
+ moviepy
@@ -0,0 +1 @@
1
+ transitsong