Skip to content

Commit d1b872a

Browse files
akash5100nabobalis
andauthored
Adds createMovie function to generate movie (#73)
Co-authored-by: Nabil Freij <[email protected]>
1 parent ccc80c3 commit d1b872a

File tree

7 files changed

+227
-24
lines changed

7 files changed

+227
-24
lines changed

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ repos:
55
- id: docformatter
66
args: [--in-place, --pre-summary-newline, --make-summary-multi]
77
- repo: https://github.com/myint/autoflake
8-
rev: v1.5.1
8+
rev: v1.5.3
99
hooks:
1010
- id: autoflake
1111
args: ['--in-place', '--remove-all-unused-imports', '--remove-unused-variable']
1212
exclude: ".*(.fits|.fts|.fit|.txt|tca.*|extern.*|.rst|.md|__init__.py)$"
1313
- repo: https://github.com/psf/black
14-
rev: 22.6.0
14+
rev: 22.8.0
1515
hooks:
1616
- id: black
1717
exclude: ".*(.fits|.fts|.fit|.txt|.csv)$"

MANIFEST.in

Lines changed: 0 additions & 19 deletions
This file was deleted.

hvpy/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
from .datasource import *
33
from .event import *
44
from .facade import *
5-
from .utils import create_layers, create_events
5+
from .helpers import createMovie
6+
from .utils import create_events, create_layers, save_file
67
from .version import __version__

hvpy/helpers.py

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import time
2+
from typing import Union, Optional
3+
from pathlib import Path
4+
from datetime import datetime
5+
6+
from hvpy.api_groups.movies.queue_movie import queueMovieInputParameters
7+
from hvpy.facade import downloadMovie, getMovieStatus, queueMovie
8+
from hvpy.utils import _add_shared_docstring, save_file
9+
10+
__all__ = [
11+
"createMovie",
12+
]
13+
14+
15+
@_add_shared_docstring(queueMovieInputParameters)
16+
def createMovie(
17+
startTime: datetime,
18+
endTime: datetime,
19+
layers: str,
20+
events: str,
21+
eventsLabels: bool,
22+
imageScale: float,
23+
format: Optional[str] = "mp4",
24+
frameRate: Optional[str] = "15",
25+
maxFrames: Optional[str] = None,
26+
scale: Optional[bool] = None,
27+
scaleType: Optional[str] = None,
28+
scaleX: Optional[float] = None,
29+
scaleY: Optional[float] = None,
30+
movieLength: Optional[float] = None,
31+
watermark: Optional[bool] = True,
32+
width: Optional[str] = None,
33+
height: Optional[str] = None,
34+
x0: Optional[str] = None,
35+
y0: Optional[str] = None,
36+
x1: Optional[str] = None,
37+
y1: Optional[str] = None,
38+
x2: Optional[str] = None,
39+
y2: Optional[str] = None,
40+
size: Optional[int] = None,
41+
movieIcons: Optional[int] = None,
42+
followViewport: Optional[int] = None,
43+
reqObservationDate: Optional[datetime] = None,
44+
overwrite: bool = False,
45+
filename: Union[str, Path] = None,
46+
hq: bool = False,
47+
timeout: float = 5,
48+
) -> Path:
49+
"""
50+
Automatically creates a movie using `queueMovie`, `getMovieStatus` and
51+
`downloadMovie` functions.
52+
53+
Parameters
54+
----------
55+
{Insert}
56+
overwrite
57+
Whether to overwrite the file if it already exists.
58+
Default is `False`.
59+
filename
60+
The path to save the file to.
61+
Optional, will default to ``f"{starttime}_{endtime}.{format}"``.
62+
hq
63+
Download a higher-quality movie file (valid for "mp4" movies only, ignored otherwise).
64+
Default is `False`, optional.
65+
timeout
66+
The timeout in minutes to wait for the movie to be created.
67+
Default is 5 minutes.
68+
69+
Examples
70+
--------
71+
>>> from hvpy import createMovie, DataSource, create_events, create_layers
72+
>>> from datetime import datetime, timedelta
73+
>>> movie_location = createMovie(
74+
... startTime=datetime.today() - timedelta(days=15, minutes=5),
75+
... endTime=datetime.today() - timedelta(days=15),
76+
... layers=create_layers([(DataSource.AIA_171, 100)]),
77+
... events=create_events(["AR"]),
78+
... eventsLabels=True,
79+
... imageScale=1,
80+
... filename="my_movie",
81+
... )
82+
>>> # This is to cleanup the file created from the example
83+
>>> # you don't need to do this
84+
>>> from pathlib import Path
85+
>>> Path('my_movie.mp4').unlink()
86+
"""
87+
input_params = locals()
88+
# These are used later on but we want to avoid passing
89+
# them into queueMovie.
90+
input_params.pop("overwrite")
91+
input_params.pop("filename")
92+
input_params.pop("hq")
93+
input_params.pop("timeout")
94+
res = queueMovie(**input_params)
95+
if res.get("error"):
96+
raise RuntimeError(res["error"])
97+
timeout_counter = time.time() + 60 * timeout # Default 5 minutes
98+
while True:
99+
status = getMovieStatus(
100+
id=res["id"],
101+
format=format,
102+
token=res["token"],
103+
)
104+
if status["status"] in [0, 1]:
105+
time.sleep(3)
106+
if status["status"] == 2:
107+
break
108+
if time.time() > timeout_counter:
109+
raise RuntimeError(f"Exceeded timeout of {timeout} minutes.")
110+
if status["status"] == 3:
111+
raise RuntimeError(status["error"])
112+
binary_data = downloadMovie(
113+
id=res["id"],
114+
format=format,
115+
hq=hq,
116+
)
117+
if filename is None:
118+
filename = f"{res['id']}_{startTime.date()}_{endTime.date()}.{format}"
119+
else:
120+
filename = f"{filename}.{format}"
121+
save_file(
122+
data=binary_data,
123+
filename=filename,
124+
overwrite=overwrite,
125+
)
126+
return Path(filename)

hvpy/tests/test_helper.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
from pathlib import Path
2+
from datetime import datetime
3+
4+
import pytest
5+
6+
from hvpy.datasource import DataSource
7+
from hvpy.helpers import createMovie
8+
from hvpy.utils import create_events, create_layers
9+
10+
11+
def test_createMovie(start_time, end_time, tmp_path):
12+
f1 = tmp_path / "movie"
13+
result = createMovie(
14+
startTime=start_time,
15+
endTime=end_time,
16+
layers=create_layers([(DataSource.AIA_171, 100)]),
17+
events=create_events(["AR"]),
18+
eventsLabels=True,
19+
imageScale=1,
20+
filename=f1,
21+
)
22+
assert isinstance(result, Path)
23+
assert result.exists()
24+
assert result == tmp_path / "movie.mp4"
25+
26+
result = createMovie(
27+
startTime=start_time,
28+
endTime=end_time,
29+
layers=create_layers([(DataSource.AIA_171, 100)]),
30+
events=create_events(["AR"]),
31+
eventsLabels=True,
32+
imageScale=1,
33+
filename=f1,
34+
overwrite=True,
35+
)
36+
assert isinstance(result, Path)
37+
assert result.exists()
38+
assert result == tmp_path / "movie.mp4"
39+
40+
41+
def test_createMovie_with_none_filename(start_time, end_time):
42+
result = createMovie(
43+
startTime=start_time,
44+
endTime=end_time,
45+
layers=create_layers([(DataSource.AIA_171, 100)]),
46+
events=create_events(["AR"]),
47+
eventsLabels=True,
48+
imageScale=1,
49+
)
50+
assert isinstance(result, Path)
51+
assert result.exists()
52+
result.unlink() # clean up
53+
54+
55+
def test_createMovie_timeout(start_time, end_time, tmp_path):
56+
f1 = tmp_path / "movie"
57+
with pytest.raises(RuntimeError):
58+
createMovie(
59+
startTime=start_time,
60+
endTime=end_time,
61+
layers=create_layers([(DataSource.AIA_171, 100)]),
62+
events=create_events(["AR"]),
63+
eventsLabels=True,
64+
imageScale=1,
65+
filename=f1,
66+
timeout=0.5,
67+
)
68+
69+
70+
def test_error_handling2(tmp_path):
71+
f1 = tmp_path / "movie"
72+
with pytest.raises(RuntimeError):
73+
createMovie(
74+
startTime=datetime(2010, 1, 1),
75+
endTime=datetime(2010, 1, 2),
76+
layers=create_layers([(DataSource.AIA_171, 100)]),
77+
events=create_events(["AR"]),
78+
eventsLabels=True,
79+
imageScale=1,
80+
filename=f1,
81+
)
82+
83+
84+
def test_error_handling(tmp_path):
85+
f1 = tmp_path / "movie"
86+
with pytest.raises(RuntimeError):
87+
createMovie(
88+
startTime=datetime(2010, 1, 1),
89+
endTime=datetime(2010, 1, 2),
90+
layers=create_layers([(DataSource.AIA_171, 100)]),
91+
events=create_events(["AR"]),
92+
eventsLabels=True,
93+
imageScale=1,
94+
filename=f1,
95+
)

hvpy/tests/test_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ def test_save_file(tmp_path):
8484
)
8585
save_file(res, f1, overwrite=False)
8686
assert f1.exists()
87-
with pytest.raises(ValueError, match="already exists"):
87+
with pytest.raises(FileExistsError, match="already exists"):
8888
save_file(res, f1, overwrite=False)
8989
save_file(res, f1, overwrite=True)
9090
assert f1.exists()

hvpy/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,5 +148,5 @@ def save_file(data: bytearray, filename: Union[Path, str], overwrite: bool = Fal
148148
if isinstance(filename, str):
149149
filename = Path(filename)
150150
if filename.exists() and not overwrite:
151-
raise ValueError(f"{filename} already exists. Use overwrite=True to overwrite.")
151+
raise FileExistsError(f"{filename} already exists. Use overwrite=True to overwrite.")
152152
filename.write_bytes(data)

0 commit comments

Comments
 (0)