-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmakeDailyMovie.py
executable file
·292 lines (270 loc) · 9.46 KB
/
makeDailyMovie.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
#!/usr/local/python/bin/python
"""
TODO: Add docstring
"""
import os
import sys
import logging
import argparse as ap
import glob as g
from collections import OrderedDict
from datetime import (
datetime,
timedelta
)
import pymysql
import dailymotion as dm
import dailymotion_secrets as dms
from create_movie import (
create_movie,
generate_movie
)
# pylint: disable=logging-format-interpolation
# pylint: disable=invalid-name
# pylint: disable=redefined-outer-name
movie_dir = "/ngts/staging/archive/movie"
logfile = "/ngts/staging/archive/logs/movie/"
logging.basicConfig(filename=logfile,
level=logging.DEBUG,
format='%(levelname)10s - %(message)s')
def argParse():
"""
TODO: Add docstring
"""
p = ap.ArgumentParser()
p.add_argument("--pngs",
help="make the PNG files for a given das",
choices=getDasList())
p.add_argument("--montage",
help="montage all PNG files",
action="store_true")
p.add_argument("--movie",
help="make movie from montaged PNG files",
action="store_true")
p.add_argument("--tidy",
help="tidy up pngs?",
action="store_true")
p.add_argument("--upload",
help="upload movie to YouTube",
action="store_true")
return p.parse_args()
def getDasList():
"""
Generate a list of das machine names
"""
return ["das{:02d}".format(i) for i in range(1, 13)]
def getLastNight():
"""
Get the night int for last night
"""
tnow = datetime.utcnow()
if tnow.hour < 18:
delta = -1
else:
delta = 0
return int((tnow + delta*timedelta(days=1)).strftime('%Y%m%d'))
def getActionsToProcess(night):
"""
Find all last night's actions
"""
actions_to_process = []
with pymysql.connect(host='ds', db='ngts_ops') as cur:
qry = """
SELECT
action_id, action
FROM action_list
WHERE night=%s
AND camera_id != 899
AND action != 'stow'
AND action != 'roofopen'
"""
qry_args = (night,)
cur.execute(qry, qry_args)
results = cur.fetchall()
for row in results:
actions_to_process.append("action{}_{}".format(row[0], row[1]))
return actions_to_process
def make_pngs(movie_dir, actions, das_id):
"""
Take a list of actions and make pngs
for the local items. The output is stored in
/movie_dir/das_id/
"""
logging.info("{} - Making pngs from {}".format(nowstr(), das_id))
# now loop over the night's actions
# only make the pngs for the local images
for action in actions:
if os.path.exists("/local/{}".format(action)):
logging.info("{} - Making pngs from {}".format(nowstr(), action))
imglist = sorted(g.glob("/local/{}/*.fits".format(action)))
if imglist:
das_movie_dir = "{}/{}".format(movie_dir, das_id)
create_movie(imglist,
images_directory=das_movie_dir,
include_increment=False,
clobber_images_directory=False,
resize_factor=4)
def getDatetime(t):
"""
get the date and time from a raw image filename
and create a datetime variable
"""
ychk = int(t[8:12])
mthchk = int(t[12:14])
dchk = int(t[14:16])
hchk = int(t[16:18])
minchk = int(t[18:20])
schk = int(t[20:22])
x = datetime(year=ychk, month=mthchk,
day=dchk, hour=hchk,
minute=minchk, second=schk)
return x
def make_montage(movie_dir, das_list):
"""
sync the pngs according to earliest image that day then
montage all the pngs with imagemagick
"""
logging.info("{} - Making montage".format(nowstr()))
os.chdir(movie_dir)
logging.info("{} - Moving to: {}".format(nowstr(), os.getcwd()))
# just get a list of all the images for all das machines
# we don't care about syncing them in time as its annoying and I
# don't have time to fix this now.
images = OrderedDict()
for das in das_list:
images[das] = sorted(g.glob('{}/*.png'.format(das)))
# get the das machine with the max number of images
max_images = 0
for das in das_list:
if len(images[das]) > max_images:
max_images = len(images[das])
# now loop max_images times
# grab an image from each das machine
# if that list gives an IndexError, fill
# it with a blank image
for i in range(0, max_images):
files = ""
for das in das_list:
try:
files += "{} ".format(images[das][i])
except IndexError:
files += "empty/empty.png "
logging.info("{} - [{}/{}] {}".format(nowstr(), i+1, max_images, files))
# now montage them together
comm = "/usr/local/bin/montage {} -tile 6x2 -geometry " \
"400x300-80+3 tiled_{:05d}.png".format(files, i)
logging.info("{} - {}".format(nowstr(), comm))
os.system(comm)
def make_movie(movie_dir, movie):
"""
Make a movie of the montaged images
"""
tiled_list = sorted(g.glob("{}/tiled*.png".format(movie_dir)))
if tiled_list:
logging.info("{} - Making movie".format(nowstr()))
generate_movie(movie_dir, movie)
else:
logging.info("{} - No tiled images, skipping".format(nowstr()))
sys.exit(1)
def upload2youtube(filename, title):
"""
Upload the movie to YouTube using the OAuth setup for NGTS-OPS user channel
"""
logging.info("{} - Uploading video to YouTube".format(nowstr()))
v_id = os.popen("/usr/local/anaconda3/bin/python " \
"/usr/local/cron/scripts/upload2youtube.py " \
"--file={} --title={} --description='NGTS Daily Movie' " \
"--category='22' " \
"--privacyStatus='unlisted'".format(filename, title)).readlines()
video_id = v_id[1].split()[2].replace("'", "")
logging.info("{} - Video ID: {}".format(nowstr(), video_id))
return video_id
def upload2dailymotion(filename, title):
"""
Upload to dailymotion website using the secrets stored outside github
"""
d = dm.Dailymotion()
d.set_grant_type('password',
api_key=dms.api_key,
api_secret=dms.api_secret,
scope=['manage_videos'],
info={'username': dms.username,
'password': dms.password})
url = d.upload(filename)
res = d.post('/me/videos', {'url': url,
'title': title,
'published': 'true',
'channel': 'news'})
movie_id = res['id']
logging.info("{} - Video ID: {}".format(nowstr(), movie_id))
return movie_id
def logVideoId(video_id, night):
"""
Log the video ID to the database
"""
qry = """
INSERT INTO daily_movies
(night, youtube_id)
VALUES (%s, %s)
"""
qry_args = (night, video_id,)
with pymysql.connect(host='ds', db='ngts_ops') as cur:
cur.execute(qry, qry_args)
logging.info("{} - Logging video ID".format(nowstr()))
logging.info("{} - {}".format(nowstr(), qry))
def nowstr():
"""
TODO: Add docstring
"""
return datetime.utcnow().replace(microsecond=0).isoformat()
if __name__ == "__main__":
# get time of start
t1 = datetime.utcnow()
# parse command line
args = argParse()
# get a list of das machines
das_list = getDasList()
# start id for movie
#start_id = {key: -1 for key in das_list}
# get last night
night = getLastNight()
# check the move dir exists
if not os.path.exists(movie_dir):
os.mkdir(movie_dir)
# make pngs
if args.pngs:
actions = getActionsToProcess(night)
make_pngs(movie_dir, actions, args.pngs)
# montage pngs
if args.montage:
#make_montage(movie_dir, das_list, start_id)
make_montage(movie_dir, das_list)
# set up the movie outpout name
movie_name = "{}/daily_movies/movie_{}.mp4".format(movie_dir, night)
# make movie of montages and tidy up
if args.movie:
make_movie(movie_dir, movie_name)
# check tge movie exists before wiping the pngs
if not os.path.exists(movie_name):
logging.fatal("{} - NO MOVIE FILE! QUITTING".format(nowstr()))
# TODO : send an email here!
sys.exit(1)
# clean up the pngs
if args.tidy and os.path.exists(movie_name):
logging.info("{} - Removing tiled pngs".format(nowstr()))
os.system("/bin/rm {}/tiled*.png".format(movie_dir))
for das in das_list:
logging.info("{} - Removing individual pngs".format(nowstr()))
os.system("/bin/rm %s/%s/IMAGE*.png" % (movie_dir, das))
# upload to youtube
if args.upload and os.path.exists(movie_name):
if os.path.exists(movie_name):
#video_id = upload2youtube(movie_name, night)
video_id = upload2dailymotion(movie_name, night)
logVideoId(video_id, night)
else:
logging.fatal("{} - No such movie file: {}".format(nowstr(), movie_name))
# some final stats
t2 = datetime.utcnow()
dt = (t2-t1).total_seconds()/60.
logging.info("{} - Runtime: {:.2f} mins".format(nowstr(), dt))