Skip to content

Commit

Permalink
Fixed coverage map output
Browse files Browse the repository at this point in the history
  • Loading branch information
GermanHydrogen committed Nov 24, 2024
1 parent 5e3a3ae commit 503ae3b
Show file tree
Hide file tree
Showing 14 changed files with 3,852 additions and 28 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,7 @@ docs/_build/
# Pyenv
.python-version

*.sh
*.sh

**/ipynb_checkpoints
*.ipynb
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified data/mask.npy
Binary file not shown.
8 changes: 4 additions & 4 deletions day_integration_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ modules:
mask_filepath: "data/mask.npy"
sun_apparent_size: 0.54
cloud_map:
threshold: 3.5
threshold: 3.0

comm:
class: pyobs.comm.local.LocalComm
Expand All @@ -71,10 +71,10 @@ modules:
tester:
class: pyobs_cloudcover.testing.TestModule
image_path: "data/test_day_image.fits"
total_fraction: 0.7
total_fraction: 0.3
zenith_fraction: 0.02
zenith_value: False
zenith_average: 2.3
zenith_value: True
zenith_average: 5.8

comm:
class: pyobs.comm.local.LocalComm
Expand Down
1,423 changes: 1,419 additions & 4 deletions poetry.lock

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion pyobs_cloudcover/cloud_coverage_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@


class CloudCoverageInfo(object):
def __init__(self, cloud_cover_query: SkyPixelQuery, change: Optional[float], obs_time: datetime.datetime) -> None:
def __init__(self, cloud_cover_query: SkyPixelQuery, change: Optional[float], cloud_plot: bytes, obs_time: datetime.datetime) -> None:
self.cloud_cover_query = cloud_cover_query
self.change = change
self.cloud_plot = cloud_plot
self.obs_time = obs_time
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import datetime

import numpy as np
from cloudmap_rs import AltAzCoord, SkyPixelQuery
import numpy.typing as npt
from cloudmap_rs import SkyPixelQuery

from pyobs_cloudcover.cloud_coverage_info import CloudCoverageInfo
from pyobs_cloudcover.cloud_info_calculator.coverage_change_calculator import \
CoverageChangeCalculator
from pyobs_cloudcover.measurement_log.field_evaluators.zenith_cloud_coverage_calculator import \
ZenithCloudCoverageCalculator


class CoverageInfoCalculator:
def __init__(self, coverage_change_calculator: CoverageChangeCalculator) -> None:
self._coverage_change_calculator = coverage_change_calculator

def __call__(self, sky_query: SkyPixelQuery, obs_time: datetime.datetime) -> CloudCoverageInfo:
def __call__(self, sky_query: SkyPixelQuery, cloud_plot: bytes, obs_time: datetime.datetime) -> CloudCoverageInfo:
change = self._coverage_change_calculator(sky_query.get_pixels())

return CloudCoverageInfo(sky_query, change, obs_time)
return CloudCoverageInfo(sky_query, change, cloud_plot, obs_time)
Empty file.
32 changes: 32 additions & 0 deletions pyobs_cloudcover/cloud_plot/cloud_plotter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import io
from typing import List

import matplotlib.pyplot as plt
import numpy as np

from cloudmap_rs import AltAzCoord


def plot_clouds(coordinates: List[AltAzCoord], clouds: List[bool]) -> bytes:
'''
z = 90 - np.rad2deg([coord.alt for coord in coordinates])
az = np.rad2deg([coord.az for coord in coordinates])
plt.polar()
plt.scatter(az, z, c=clouds, s=1)
plt.colorbar()
'''

lon, lat = [coord.az for coord in coordinates], [coord.alt for coord in coordinates]
plt.polar()
plt.scatter(lon, 90 - np.rad2deg(lat), c=clouds, s=1)
plt.colorbar()

return render_plot()

def render_plot() -> bytes:
buffer = io.BytesIO()
plt.savefig(buffer, format='png')
buffer.seek(0)
plt.close()

return buffer.read()
30 changes: 23 additions & 7 deletions pyobs_cloudcover/pipeline/day/pipeline.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import datetime
from copy import copy
from itertools import compress
from typing import List, Any, Optional

import matplotlib.pyplot as plt
import numpy as np
from numpy import typing as npt

from cloudmap_rs import SkyPixelQuery

from pyobs_cloudcover.cloud_coverage_info import CloudCoverageInfo
from pyobs_cloudcover.cloud_info_calculator import CoverageInfoCalculator
from pyobs_cloudcover.cloud_plot.cloud_plotter import plot_clouds, render_plot
from pyobs_cloudcover.pipeline.day.color_ratio_calculation import calc_color_ratio
from pyobs_cloudcover.pipeline.day.debayer_image import debayer_image
from pyobs_cloudcover.pipeline.day.sun_masker import SunMasker
from pyobs_cloudcover.pipeline.day.altaz_map_generator import AltAzMapGenerator
from pyobs_cloudcover.pipeline.night.cloud_map_generator.cloud_map_generator import CloudMapGenerator
from pyobs_cloudcover.pipeline.night.preprocessor.image_binner import ImageBinner
from pyobs_cloudcover.pipeline.pipeline import Pipeline


Expand All @@ -28,22 +32,34 @@ def __init__(self, mask: npt.NDArray[np.bool_], alt_az_generator: AltAzMapGenera
self._sky_query: Optional[SkyPixelQuery] = None
self._alt_az_mask: Optional[npt.NDArray[np.bool_]] = None

self._image_binner = ImageBinner(2)

def __call__(self, image: npt.NDArray[np.float_], obs_time: datetime.datetime) -> CloudCoverageInfo:
debayered_image = debayer_image(image)
color_ratio_image = calc_color_ratio(debayered_image).flatten()
cloud_map = self._cloud_map_generator(color_ratio_image)
color_ratio_image = calc_color_ratio(debayered_image)#.flatten()
cloud_map = self._image_binner(self._cloud_map_generator(color_ratio_image))

if self._sky_query is None or self._alt_az_mask is None:
alt_az_points = self.flatten(self._alt_az_generator(*image.shape))
self._alt_az_mask = self._mask.flatten() & np.array([x is not None for x in alt_az_points])

self._sky_query = SkyPixelQuery(self.filter(alt_az_points, self._alt_az_mask), cloud_map[self._alt_az_mask]) # type: ignore
if self._sky_query is None or self._alt_az_mask is None:
alt_az_points = self.flatten(self._alt_az_generator(*cloud_map.shape))
self._alt_az_mask = self._mask.flatten().astype(np.bool_) & np.array([x is not None for x in alt_az_points]).astype(np.bool_)
flat_cloud_map = self._to_python_type(cloud_map)
self._sky_query = SkyPixelQuery(self.filter(alt_az_points, self._alt_az_mask), self.filter(flat_cloud_map, self._alt_az_mask)) # type: ignore
else:
self._sky_query.set_pixels(cloud_map[self._alt_az_mask])

sky_query = self._sun_masker(self._sky_query, obs_time)

return self._coverage_info_calculator(sky_query, obs_time)
cloud_plot = cloud_map.astype(np.float_).flatten()
cloud_plot[~self._alt_az_mask] = np.nan
plt.imshow(cloud_plot.reshape(cloud_map.shape))

return self._coverage_info_calculator(sky_query, render_plot(),obs_time)


def _to_python_type(self, cloud_map: npt.NDArray[np.float_]) -> List[bool]:
flat_map = self.flatten(list(cloud_map > 0.5))
return list(map(bool, flat_map))

@staticmethod
def flatten(map_2d: List[List[Any]]) -> List[Any]:
Expand Down
5 changes: 4 additions & 1 deletion pyobs_cloudcover/pipeline/night/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from cloudmap_rs import SkyPixelQuery

from pyobs_cloudcover.cloud_coverage_info import CloudCoverageInfo
from pyobs_cloudcover.cloud_plot.cloud_plotter import plot_clouds
from pyobs_cloudcover.pipeline.night.altaz_grid_generator.spherical_alt_az_generator import SphericalAltAzGenerator
from pyobs_cloudcover.pipeline.night.catalog.catalog_constructor import CatalogConstructor
from pyobs_cloudcover.cloud_info_calculator import CoverageInfoCalculator
Expand Down Expand Up @@ -51,4 +52,6 @@ def __call__(self, image: npt.NDArray[np.float_], obs_time: datetime.datetime) -
sky_query = SkyPixelQuery(alt_az_list, cloud_map)
sky_query = self._moon_masker(sky_query, obs_time)

return self._coverage_info_calculator(sky_query, obs_time)
cloud_plot = plot_clouds(alt_az_list, sky_query.get_pixels())

return self._coverage_info_calculator(sky_query, cloud_plot, obs_time)
15 changes: 14 additions & 1 deletion pyobs_cloudcover/web_api/server.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Optional

from aiohttp import web

from pyobs_cloudcover.cloud_coverage_info import CloudCoverageInfo
Expand All @@ -14,9 +16,14 @@ def __init__(self, query_executor: CoverageQueryExecutor, url: str = "localhost"
self._app = web.Application()
self._app.add_routes([web.get("/query/point", self._point_query)])
self._app.add_routes([web.get("/query/area", self._area_query)])
self._app.add_routes([web.get("/cloud_map.png", self._image)])
self._app.add_routes([web.get("/cloud_map.html", self._image_site)])

self._cloud_plot: Optional[bytes] = None

def set_measurement(self, measurement: CloudCoverageInfo) -> None:
self._query_executor.set_measurement(measurement)
self._cloud_plot = measurement.cloud_plot

async def start(self) -> None:
runner = web.AppRunner(self._app)
Expand Down Expand Up @@ -63,4 +70,10 @@ async def _area_query(self, request: web.Request) -> web.Response:

obs_time = self._query_executor.get_obs_time()

return web.json_response({'value': cover, 'obs_time': obs_time})
return web.json_response({'value': cover, 'obs_time': obs_time})

async def _image(self, _: web.Request) -> web.Response:
return web.Response(body=self._cloud_plot, content_type="image/png")

async def _image_site(self, _: web.Request) -> web.Response:
return web.Response(body=b'<html><img src="cloud_map.png"></html>', content_type="text/html")
7 changes: 4 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ readme = "Readme.md"
packages = [{include = "pyobs_cloudcover"}]

[tool.poetry.dependencies]
python = ">=3.11,<3.12"
python = ">=3.11,<3.13"
matplotlib = "^3.9.2"

[tool.poetry.group.dev.dependencies]
pytest = "^7.4.0"
Expand Down Expand Up @@ -39,7 +40,8 @@ dynamic = ["version"]
dependencies = [
"pyobs-core[full]>=1.13.4",
"influxdb-client>=1.42.0",
"opencv-python>= 4.8.0.76"
"opencv-python>= 4.8.0.76",
"matplotlib"
]

[project.optional-dependencies]
Expand All @@ -51,7 +53,6 @@ test = [
"pytest-aiohttp>=1.0.5",
"mypy>=1.9.0",
"testcontainers[influxdb]>=4.7.1",
"matplotlib"
]

[tool.maturin]
Expand Down
Loading

0 comments on commit 503ae3b

Please sign in to comment.