Skip to content

Commit

Permalink
refactor python api to be consistent with docs (#26)
Browse files Browse the repository at this point in the history
* introduce lib date-tz by cmake/HHinnatDate.cmake
* for using the library date-tz, change cflags to c++17 and use runner windows-2022
* manually download tzdata for Windows 
* separate header files

* Rename: Analyzer -> Algorithm, SPA_Analyzer -> SPACalculator
* reimplemented fseg._analyzer.py and backend Algorithm & SPACalculator

* update docstring
* use cross-reference in docs/**/*.md

* use toml recording case data
* add foo algorithm for testing




Co-authored-by: mikesongming <mikesongming@users.noreply.github.com>
Co-authored-by: Mike Song <mikesongming@gmail.com>
  • Loading branch information
3 people authored Jul 7, 2022
1 parent a470f23 commit 5d86e3b
Show file tree
Hide file tree
Showing 38 changed files with 941 additions and 537 deletions.
1 change: 1 addition & 0 deletions .changelog/news/24.api
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
simplify python frontend api by refactoring c++ backend with pybind11-empowered virtual function overriding and methods overloading
1 change: 1 addition & 0 deletions .changelog/news/24.doc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
update flow graph in dev-guid.md and docstring in _analyzer.py
2 changes: 2 additions & 0 deletions .changelog/news/PR26.maint
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Introduce cmake module to fetch library pybind11 and date-tz; Modify setup.py to support c++17 on MacOSX >= 10.12;
and Build windows version on Windows-2022 with manually downloaded tzdata
3 changes: 2 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ jobs:
- [ubuntu-20.04, manylinux_x86_64]
- [macos-11, macosx_x86_64]
# - [macos-12, macosx_x86_64]
- [windows-2019, win_amd64]
# - [windows-2019, win_amd64]
- [windows-2022, win_amd64]
python:
- 'cp310'
steps:
Expand Down
21 changes: 11 additions & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16.0)

project(FSEG)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

cmake_policy(SET CMP0095 NEW)
# cmake_policy(SET CMP0068 NEW)
Expand All @@ -21,7 +21,12 @@ if (MSVC)
# (according to https://cmake.org/cmake/help/latest/variable/MSVC_VERSION.html#variable:MSVC_VERSION)
if (MSVC_VERSION GREATER_EQUAL 1925)
cmake_print_variables(MSVC_VERSION)
add_compile_options(/Zc:preprocessor)
cmake_print_variables(CMAKE_VERSION)
cmake_print_variables(CMAKE_SYSTEM_VERSION)

# add_compile_options(/Zc:preprocessor)

# add_compile_options(/wd5105) ## which failed on Github Actions Runner windows-2019
else()
message(FATAL_ERROR "MSVC compiler before VS2019 Update5 are not supported")
endif()
Expand All @@ -31,23 +36,19 @@ else()
LINK_LIBRARIES(m)
endif()


find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
message(STATUS "Set up ccache ...")
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) # Less useful to do it for linking, see edit2
endif(CCACHE_FOUND)

# fetch pybind11 when building
# Fetch third-party libraries
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
set(FETCHCONTENT_UPDATES_DISCONNECTED ON CACHE BOOL "Disable updating fetched content")
include(HHinnatDate)
include(GitPybind11)

include(FetchContent)
FetchContent_Declare(pybind11
GIT_REPOSITORY https://github.com/pybind/pybind11.git
GIT_TAG v2.9.2
)
FetchContent_MakeAvailable(pybind11)

add_subdirectory(src)

Expand Down
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
include CMakeLists.txt
recursive-include src *
recursive-include cmake *
recursive-exclude src/python */__pycache__/*
11 changes: 1 addition & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Please visit [Homepage](https://mikesongming.github.io/SE-Geometry/index.html) f

FSEG can be installed via PyPi by:
```sh
pip install FSEG
pip install fseg
```

To build by source, call a [PEP517](https://peps.python.org/pep-0517) compliant build-system by:
Expand All @@ -58,12 +58,3 @@ To aggregate expertise and efforts from both uncommercial and commercial entitie
本项目版权采用[LGPLv2.1](LICENSE)开源协议,意味着基于本项目的库文件可以进行任意开源或者闭源软件的开发,但是对本项目的**任意修改**需要采用同样的协议开源。

如有疑问,请联系 gnosoir@hotmail.com

<!-- Sun-Earth-Analyzer (SEA) is a Soloar Position algorithm runtime package with Python.
It provides:
- SPA
Tested Platforms:
- MacOSX-10.9-x86_64 -->
6 changes: 6 additions & 0 deletions cmake/GitPybind11.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
include(FetchContent)
FetchContent_Declare(pybind11
GIT_REPOSITORY https://github.com/pybind/pybind11.git
GIT_TAG v2.9.2
)
FetchContent_MakeAvailable(pybind11)
13 changes: 13 additions & 0 deletions cmake/HHinnatDate.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
set(USE_SYSTEM_TZ_DB ON CACHE INTERNAL "")
set(BUILD_SHARED_LIBS ON CACHE INTERNAL "")
set(BUILD_TZ_LIB ON CACHE INTERNAL "")

# switch off C++17 uncaught_exceptions
# add_compile_definitions(HAS_UNCAUGHT_EXCEPTIONS=FALSE)

include(FetchContent)
FetchContent_Declare(howard_hinnant_date
GIT_REPOSITORY https://github.com/HowardHinnant/date.git
GIT_TAG v3.0.1
)
FetchContent_MakeAvailable(howard_hinnant_date)
144 changes: 88 additions & 56 deletions docs/dev-guide/dev-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

1. Install [Anaconda](https://www.anaconda.com/) on System
2. Install [CMake](https://cmake.org) on System
3. Install C++/C Compiler on System, w.r.t. [supported platforms](https://mikesongming.github.io/SE-Geometry/#supported-platforms)
3. Install C++/C Compiler on System, w.r.t. [supported platforms](../index.md#supported-platforms)
4. Checkout issue related branch from [Github](https://github.com/mikesongming/SE-Geometry)
5. Prepare Python environment, either by
```
Expand All @@ -14,8 +14,12 @@ or
```
pip install tox && tox -e dev
```
6. Browse and edit source code as your wish, [VSCode](https://code.visualstudio.com/) recommened as the IDE
7. Broadcast your work using [towncrier](https://towncrier.readthedocs.io/en/latest/) by:
6. Add `pre-commit` git hooks
```
python -m pre_commit install
```
7. Browse and edit source code as your wish, [VSCode](https://code.visualstudio.com/) recommened as the IDE
8. Broadcast your work using [towncrier](https://towncrier.readthedocs.io/en/latest/) by:
```
towncrier create {source}.{type} --edit
```
Expand All @@ -25,7 +29,7 @@ where {type} is one of:
> - bug: for bug fixes
> - maint: for maintenance and ci related
> - dev: for breakthrough changes/milestone
> - docs: for documentation changes
> - doc: for documentation changes
> - author: for contributor names
and where the {source} part of the filename is:
Expand All @@ -44,24 +48,34 @@ empowered by [Mermaid-Js](https://mermaid-js.github.io/mermaid/)
``` mermaid
flowchart LR
i1((Observatory))
i2((OBS_TIME_T))
a1[SunEarthAnalyzer]
a2[interface of<br>SPA_Analyzer]
b1[SPA_Analyzer]
b2[(C implementation of<br>SPA algorithm)]
i1---a1
i2---a1
Python<===>|pybind11|CPP
subgraph Python
a1-->|set_observatory|a2
a1-->|sun_position_at|a2
i2((Local Datatime))
c1[SunEarthAnalyzer]
a1[py::Algorithm]
a2[py::SPACalculator]
b1[Algorithm]
b2[SPACalculator]
d1[(C implementation of<br>SPA algorithm)]
i1---c1
i2---c1
Py<===>|pybind11|Cpp
subgraph Frontend
c1--->Py
subgraph Py
direction TB
a1-->a2
end
end
subgraph CPP
direction TB
b1-->|calculate_sun_position_at|b2
subgraph Backend
Cpp--->d1
subgraph Cpp
direction TB
b1-->b2
end
end
```

Expand All @@ -70,58 +84,67 @@ flowchart LR
``` mermaid
sequenceDiagram
participant SunEarthAnalyzer
participant SPA_Analyzer
participant SPACalculator
participant SPA
SunEarthAnalyzer ->>+ SPA_Analyzer: load algorithm
SPA_Analyzer -->>- SunEarthAnalyzer: calculator
SunEarthAnalyzer ->>+ SPACalculator: load algorithm
SPACalculator -->>- SunEarthAnalyzer: calculator
SunEarthAnalyzer ->> SPA_Analyzer: set observatory
SunEarthAnalyzer ->> SPACalculator: set observatory
SunEarthAnalyzer ->> SPACalculator: set local datetime
SunEarthAnalyzer ->>+ SPA_Analyzer: sun position at ?
SunEarthAnalyzer ->>+ SPACalculator: sun position ?
% break when observatory not set
% SPA_Analyzer -->> SunEarthAnalyzer: RuntimeError
% SPACalculator -->> SunEarthAnalyzer: RuntimeError
% end
SPA_Analyzer -->>+ SPA: calculate sun position at ?
SPACalculator -->>+ SPA: calculate sun position at ?
% break when validate_inputs fails
% SPA-->SPA_Analyzer: error code
% SPA-->SPACalculator: error code
% end
SPA -->> SPA: spa calcluate
SPA -->>- SPA_Analyzer: spa_data
SPA_Analyzer -->>- SunEarthAnalyzer: TopoCentricSunPositionResult
SPA -->>- SPACalculator: spa_data
SPACalculator -->>- SunEarthAnalyzer: TopoCentricSunPositionResult
```

### 3. Class Diagram

``` mermaid
classDiagram
SunEarthAnalyzer "1" --> "0..1" Analyzer: load algorithm
SunEarthAnalyzer "1" --> "0..1" Algorithm: load algorithm
SunEarthAnalyzer "1" --> "0..1" Observatory: set observatory
SunEarthAnalyzer --> TopoCentricSunPositionResult: sun position at
Analyzer <|-- SPA_Analyzer
Analyzer <|-- SG2_Analyzer
TopoCentricSunPositionResult --> OBS_TIME_T
Algorithm <|-- SPACalculator
Algorithm <|-- SG2_Calculator
Algorithm <|-- Other_Algorithm
class SunEarthAnalyzer {
+String algorithm
+Observatory observatory
-Analyzer _impl
+algorithm: string
+observatory: Observatory
+registered: dict
-_impl: Algorithm
+has_set_observatory()
+sun_position_at(obs_time: OBS_TIME_T)
+sun_position_at(local_datetime)
-_load_algorithm()
}
class Analyzer {
class Algorithm {
-_observatory_set: bool = false
+virtual: get_observatory()
+virtual: set_observatory(kwargs)
+virtual: calc_sun_position_at(year,month,day,hour,minute,second)
-_local_datetime_set: bool = false
-_observatory: map<string, double>
-_local_datetime: array<int>
+ static OBS_FIELDS: vector<string>
+has_set_observatory()
+get_observatory()
+set_observatory(...)
+has_set_local_datetime()
+get_local_datetime()
+set_local_datetime(...)
+virtual: name()
+virtual: calc_sun_position()
}
<<interface>> Analyzer
class SPA_Analyzer {
-_observatory: map[string, double]
<<interface>> Algorithm
class SPACalculator {
-_spa: spa_data
}
class SG2_Analyzer {
class SG2_Calculator {
TODO
}
class Observatory {
Expand All @@ -135,23 +158,32 @@ classDiagram
+temperature: float = 0
+atmos_refract: float = 0
}
class OBS_TIME_T {
+year: int
+month: int
+day: int
+hour: int
+minute: int
+second: int
}
class TopoCentricSunPositionResult {
+zenith: float
+azimuth: float
+julian_day: float = None
+obs_time: OBS_TIME_T = None
}
```

## How to add algorithm

1. Add an sub-class of `Algorithm`, implementing two methods: `name` and `calc_sun_position`

2. Add a [pybind11 trampoline class](https://pybind11.readthedocs.io/en/stable/advanced/classes.html#overriding-virtual-functions-in-python) for the new algorithm class for automatic downcasting

3. Bind the algorithm to python in `src/cpp/main.cpp`
```cpp
py::class_<SPACalculator, Algorithm, PySPACaculator>(m, "SPACalculator")
.def(py::init<>())
.def_property_readonly("name", &SPACalculator::name)
.def("calc_sun_position", &SPACalculator::calc_sun_position);
```
4. Register the algorithm in `src/python/fseg/impl/__init__.py`
```py
registered_algorithms = {
"SPA": SPACalculator,
}
```
## Tests by Pytest

Currently, only Python code is tested by pytest. You are welcome to incorporate C++ tests.
Expand Down
4 changes: 2 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
A library on sun position and sunlight analysis from the observer's viewpoint,
which comsists of a simplistic _python_ frontend and an extensible _C++_ backend.

[Get Started](https://mikesongming.github.io/SE-Geometry/user-guide/install/){ .md-button .md-button--primary }
[Get Started](./user-guide/install.md){ .md-button .md-button--primary }


## Features & Algorithms
Expand All @@ -19,6 +19,6 @@ which comsists of a simplistic _python_ frontend and an extensible _C++_ backend

## Supported Platforms

- MacOSX-10.9-x86_64
- MacOSX-10.12-x86_64
- Ubuntu-20.04-manylinux_x86_64
- Windows-2019-win_amd64
3 changes: 0 additions & 3 deletions docs/reference/data.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,3 @@
::: fseg._data.Observatory

::: fseg._data.TopoCentricSunPositionResult

<!-- ## safely_from_dict
::: fseg._data.safely_from_dict -->
2 changes: 1 addition & 1 deletion docs/user-guide/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ either from PYPI or from source. Later, installation with Anaconda is more reco
## with PIP

```sh
pip install FSEG
pip install fseg
```

## with GIT
Expand Down
Loading

0 comments on commit 5d86e3b

Please sign in to comment.