Skip to content

Commit d9af2e9

Browse files
Merge pull request #8 from pyobs/performance
Performance enhancement and day pipeline
2 parents 245d096 + de2a31d commit d9af2e9

File tree

84 files changed

+1544
-571
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+1544
-571
lines changed

Readme.md

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,39 @@ This pipeline estimates the limiting magnitude of each pixel based on the visibi
1212

1313
## Web Service
1414

15-
Route: `/query?ra={Right ascension in degree}&dec={Declination in degree}`
15+
### Point Query
16+
Returns the cloudiness value of the analyzed sky position closest to the requested position. <br>
17+
**Routes**: <br>
18+
`/query/point?ra={Right ascension in degree}&dec={Declination in degree}` or <br>
19+
`/query/point?alt={Altitude in degree}&az={Azimuth in degree}`
1620

17-
### Result
18-
| Field | Type | Description |
19-
|----------|-------|-------------------------------------------------|
21+
**Example:** <br>
22+
`/query/point?alt=90.0&az=0.0`
23+
24+
25+
**Result:**
26+
27+
| Field | Type | Description |
28+
|----------|-------|--------------------------------------------------|
29+
| obs_time | float | Observation Unix time of the last analyzed image |
30+
| value | bool | If it is cloudy at the requested point |
31+
32+
### Area Query
33+
Returns the cloud fraction within the requested great circle.
34+
35+
**Routes**: <br>
36+
`/query/area?ra={Right ascension in degree}&dec={Declination in degree}&radius={Radius in degree}` or <br>
37+
`/query/area?alt={Altitude in degree}&az={Azimuth in degree}&radius={Radius in degree}`
38+
39+
**Example:** <br>
40+
`/query/area?alt=90.0&az=0.0&radius=10.0`
41+
42+
**Result:**
43+
44+
| Field | Type | Description |
45+
|----------|-------|--------------------------------------------------|
2046
| obs_time | float | Observation Unix time of the last analyzed image |
21-
| value | float | Limiting magnitude in mag |
47+
| value | float | Cloud fraction in the requested area in percent |
2248

2349

2450
## Configuration

data/mask.npy

6.14 MB
Binary file not shown.

data/test_day_image.fits

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:3fd9a8cbda94f9a57d23e64da3446978d96a17075829d6ee28c84149ed80c4b3
3+
size 12888000

day_integration_test.yaml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
class: pyobs.modules.MultiModule
2+
3+
shared:
4+
world:
5+
class: pyobs.utils.simulation.SimWorld
6+
time: "2020-10-21 12:00:00"
7+
8+
9+
modules:
10+
cloudcover:
11+
class: pyobs_cloudcover.application.Application
12+
13+
image_sender: "tester"
14+
15+
server:
16+
url: "localhost"
17+
port: 8080
18+
19+
# This is overridden by the test module
20+
measurement_log:
21+
url: ""
22+
bucket: ""
23+
org: ""
24+
token: ""
25+
26+
pipelines:
27+
day:
28+
alt_interval:
29+
start: 18
30+
end:
31+
32+
options:
33+
world_model:
34+
class: pyobs_cloudcover.world_model.SimpleModel
35+
a0: 4.81426598e-03
36+
F: 2.00000000e+00
37+
R: 1.06352627e+03
38+
c_x: 7.57115607e+02
39+
c_y: 5.11194838e+02
40+
41+
mask_filepath: "data/mask.npy"
42+
43+
cloud_map:
44+
threshold: 3.5
45+
46+
coverage_info:
47+
zenith_altitude: 80
48+
49+
comm:
50+
class: pyobs.comm.local.LocalComm
51+
name: "cloudcover"
52+
53+
tester:
54+
class: pyobs_cloudcover.testing.TestModule
55+
image_path: "data/test_day_image.fits"
56+
total_fraction: 0.7
57+
zenith_fraction: 0.02
58+
zenith_value: False
59+
zenith_average: 2.3
60+
61+
comm:
62+
class: pyobs.comm.local.LocalComm
63+
name: "tester"
64+
65+
vfs:
66+
class: pyobs.vfs.VirtualFileSystem
67+
roots:
68+
cache:
69+
class: pyobs.vfs.MemoryFile
70+
#root: .
71+
72+
comm:
73+
class: pyobs.comm.local.LocalComm
74+
name: multi
75+
76+
timezone: Europe/Berlin
77+
location:
78+
longitude: 9.944333
79+
latitude: 51.560583
80+
elevation: 201.0000000008158

example.yaml

Lines changed: 64 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,6 @@ class: pyobs_cloudcover.application.Application
33
# Camera which images are used for cloud detection
44
image_sender: "allskycam"
55

6-
# Astronomical solution
7-
# Possible models:
8-
# Simple Model
9-
# class: pyobs_cloudcover.world_model.SimpleModel
10-
# parameters: (a0, F, R, c_x, c_y) see https://ui.adsabs.harvard.edu/abs/2019A&A...626A.105B
11-
# WCS Model
12-
# class: pyobs_cloudcover.world_model.WCSModel
13-
# parameters:
14-
# file_path: Path to FITS file containing WCS
15-
model:
16-
class: pyobs_cloudcover.world_model.SimpleModel
17-
a0: 4.81426598e-03
18-
F: 2.00000000e+00
19-
R: 1.06352627e+03
20-
c_x: 7.57115607e+02
21-
c_y: 5.11194838e+02
22-
236
# Web Service
247
server:
258
# Host Name
@@ -37,13 +20,63 @@ measurement_log:
3720
# Different image analysis pipelines can be used for different solar altitude intervals
3821
# Currently only the "night" pipeline is available, which works best after the astronomical dawn
3922
pipelines:
23+
day:
24+
alt_interval:
25+
start: 18
26+
end:
27+
28+
options:
29+
# Astronomical solution
30+
# Possible models:
31+
# Simple Model
32+
# class: pyobs_cloudcover.world_model.SimpleModel
33+
# parameters: (a0, F, R, c_x, c_y) see https://ui.adsabs.harvard.edu/abs/2019A&A...626A.105B
34+
# WCS Model
35+
# class: pyobs_cloudcover.world_model.WCSModel
36+
# parameters:
37+
# file_path: Path to FITS file containing WCS
38+
world_model:
39+
class: pyobs_cloudcover.world_model.SimpleModel
40+
a0: 4.81426598e-03
41+
F: 2.00000000e+00
42+
R: 1.06352627e+03
43+
c_x: 7.57115607e+02
44+
c_y: 5.11194838e+02
45+
46+
# Filepath to the image mask
47+
mask_filepath: "data/mask.npy"
48+
49+
cloud_map:
50+
# Under which color ratio a pixel is considered cloudy (blue/red + blue/green)
51+
threshold: 3.5
52+
53+
coverage_info:
54+
# Altitude which is considered to be the lower boundary of the zenith to average for the zenith cloud fraction measurement (in degree)
55+
zenith_altitude: 80
4056
night:
4157
# Solar altitude interval (in degree), in which this pipeline should be used
4258
alt_interval:
4359
start:
4460
end: -18
4561

4662
options:
63+
# Astronomical solution
64+
# Possible models:
65+
# Simple Model
66+
# class: pyobs_cloudcover.world_model.SimpleModel
67+
# parameters: (a0, F, R, c_x, c_y) see https://ui.adsabs.harvard.edu/abs/2019A&A...626A.105B
68+
# WCS Model
69+
# class: pyobs_cloudcover.world_model.WCSModel
70+
# parameters:
71+
# file_path: Path to FITS file containing WCS
72+
world_model:
73+
class: pyobs_cloudcover.world_model.SimpleModel
74+
a0: 4.81426598e-03
75+
F: 2.00000000e+00
76+
R: 1.06352627e+03
77+
c_x: 7.57115607e+02
78+
c_y: 5.11194838e+02
79+
4780
preprocessor:
4881
# Filepath to the image mask
4982
mask_filepath: "tests/integration/mask.npy"
@@ -72,14 +105,23 @@ pipelines:
72105
# Rectangle around the calculated star position with 2 * window_size + 1 length, in which the star searched for (in px)
73106
window_size: 6.0
74107

75-
cloud_map:
108+
# Determines at which celestial positions the limiting magnitude is evaluated
109+
altaz_grid:
110+
# Number of equidistant points on the hole celestial sphere
111+
point_number: 100000
112+
# Lower boundary for altitude
113+
limiting_altitude: 30
114+
115+
lim_mag_map:
76116
# Radius in which to use stars for estimating the limiting magnitude (in degree)
77117
radius: 7.0
78118
# Number of consecutive images in which a star has to be visible to be considered visible for the limiting magnitude estimation
79119
integration_length: 1
80120

81-
coverage_info:
121+
cloud_map:
82122
# Under which limiting magnitude a pixel is considered cloudy (in mag)
83-
cloud_threshold: 5.5
84-
# Radius around the zenith to average for the zenith cloud fraction measurement (in degree)
85-
zenith_radius: 20
123+
threshold: 5.5
124+
125+
coverage_info:
126+
# Altitude which is considered to be the lower boundary of the zenith to average for the zenith cloud fraction measurement (in degree)
127+
zenith_altitude: 80
Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,6 @@ modules:
1212

1313
image_sender: "tester"
1414

15-
model:
16-
class: pyobs_cloudcover.world_model.WCSModel
17-
file_path: "data/test_wcs.fits"
18-
1915
server:
2016
url: "localhost"
2117
port: 8080
@@ -34,6 +30,10 @@ modules:
3430
end: -18
3531

3632
options:
33+
world_model:
34+
class: pyobs_cloudcover.world_model.WCSModel
35+
file_path: "data/test_wcs.fits"
36+
3737
preprocessor:
3838
mask_filepath: ""
3939
bin_size: 2
@@ -48,22 +48,29 @@ modules:
4848
reverse_matcher:
4949
sigma_threshold: 4.0
5050
window_size: 10.0
51-
52-
cloud_map:
51+
altaz_grid:
52+
point_number: 100000
53+
limiting_altitude: 30
54+
lim_mag_map:
5355
radius: 7.0
5456
integration_length: 1
57+
cloud_map:
58+
threshold: 5.5
5559

5660
coverage_info:
57-
cloud_threshold: 5.5
58-
zenith_radius: 20
61+
zenith_altitude: 80
5962

6063
comm:
6164
class: pyobs.comm.local.LocalComm
6265
name: "cloudcover"
6366

6467
tester:
6568
class: pyobs_cloudcover.testing.TestModule
66-
image_path: "data/test_image.fits"
69+
image_path: "data/test_night_image.fits"
70+
total_fraction: 0.1
71+
zenith_fraction: 0.0
72+
zenith_value: False
73+
zenith_average: 0.0
6774

6875
comm:
6976
class: pyobs.comm.local.LocalComm

pyobs_cloudcover/application.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,13 @@
88
from pyobs_cloudcover.measurement_log.influx import Influx
99
from pyobs_cloudcover.pipeline.pipeline_controller_factory import PipelineControllerFactory
1010
from pyobs_cloudcover.web_api.server_factory import ServerFactory
11-
from pyobs_cloudcover.world_model import WorldModel
12-
from pyobs_cloudcover.world_model.world_model_factory import WorldModelFactory
1311

1412
log = logging.getLogger(__name__)
1513

1614

1715
class Application(Module):
1816
def __init__(self,
1917
image_sender: str,
20-
model: Dict[str, Any],
2118
server: Dict[str, Any],
2219
measurement_log: Dict[str, Any],
2320
pipelines: Dict[str, Dict[str, Any]], *args: Any, **kwargs: Any) -> None:
@@ -26,15 +23,12 @@ def __init__(self,
2623

2724
self._image_sender = image_sender
2825

29-
world_model_factory = WorldModelFactory(self.observer)
30-
world_model: WorldModel = world_model_factory(model)
31-
32-
server_factory = ServerFactory(self.observer, world_model)
26+
server_factory = ServerFactory(self.observer)
3327
self._server = server_factory(server)
3428

3529
self._measurement_log = Influx(**measurement_log)
3630

37-
pipeline_controller_factory = PipelineControllerFactory(self.observer, world_model)
31+
pipeline_controller_factory = PipelineControllerFactory(self.observer)
3832
self._pipeline_controller = pipeline_controller_factory(pipelines)
3933

4034
async def open(self) -> None:
@@ -58,8 +52,10 @@ async def process_new_image(self, event: Event, sender: str) -> None:
5852

5953
measurement = self._pipeline_controller(image.data, obs_time)
6054

61-
log.info("Finished measurement!")
62-
6355
if measurement is not None:
56+
log.debug(f"{measurement.total_cover}, {measurement.zenith_cover}, {measurement.change}")
57+
6458
self._server.set_measurement(measurement)
6559
self._measurement_log(measurement)
60+
61+
log.info("Finished measurement!")
Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,14 @@
11
import datetime
22
from typing import Optional
33

4-
import numpy as np
5-
import numpy.typing as npt
4+
from cloudmap_rs import SkyPixelQuery
65

76

87
class CloudCoverageInfo(object):
9-
def __init__(self, cloud_cover_map: npt.NDArray[np.float_],
10-
total_cover: float, average: float, std: float, zenith_cover: float, zenith_average: float, zenith_std: float, change: Optional[float], obs_time: datetime.datetime) -> None:
11-
self.cloud_cover_map = cloud_cover_map
8+
def __init__(self, cloud_cover_query: SkyPixelQuery,
9+
total_cover: float, zenith_cover: Optional[float], change: Optional[float], obs_time: datetime.datetime) -> None:
10+
self.cloud_cover_query = cloud_cover_query
1211
self.total_cover = total_cover
13-
self.average = average
14-
self.std = std
1512
self.zenith_cover = zenith_cover
16-
self.zenith_average = zenith_average
17-
self.zenith_std = zenith_std
1813
self.change = change
1914
self.obs_time = obs_time
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from pyobs_cloudcover.cloud_info_calculator.coverage_info_calculator import CoverageInfoCalculator
2+
from pyobs_cloudcover.cloud_info_calculator.zenith_cloud_coverage_calculator import ZenithCloudCoverageCalculator
3+
from pyobs_cloudcover.cloud_info_calculator.cloud_info_calculator_factory import CloudInfoCalculatorFactory
4+
from pyobs_cloudcover.cloud_info_calculator.cloud_info_calculator_options import CloudInfoCalculatorOptions
5+
6+
__all__ = ["CoverageInfoCalculator", "ZenithCloudCoverageCalculator", "CloudInfoCalculatorFactory", "CloudInfoCalculatorOptions"]

0 commit comments

Comments
 (0)