Commit 9fea0933 authored by BO ZHANG's avatar BO ZHANG 🏀
Browse files

major updates

parent 99a15c89
Pipeline #1423 failed with stage
in 0 seconds
...@@ -2,5 +2,4 @@ ...@@ -2,5 +2,4 @@
omit = omit =
tests/* tests/*
setup.py setup.py
csst_proto/api.py
test_codestyle.py test_codestyle.py
install:
pip install .
rm -rf build csst_proto.egg-info
uninstall:
pip uninstall csst_proto -y
...@@ -40,7 +40,7 @@ from astropy.io import fits ...@@ -40,7 +40,7 @@ from astropy.io import fits
# read an L0 image # read an L0 image
img = fits.getdata("CSST_MS_SCI_06_L0_img.fits") img = fits.getdata("CSST_MS_SCI_06_L0_img.fits")
# flip the image # flip the image
img_flipped = flip_image(img=img) img_flipped = flip_image(image=img)
``` ```
## algorithm description ## algorithm description
......
import os from .flip_image import flip_image, read_default_image
from .demo import demo_function, DemoClass
__version__ = "0.0.1" __version__ = "0.0.1"
PACKAGE_PATH = os.path.dirname(__file__) __all__ = [
"flip_image",
"read_default_image",
"demo_function",
"DemoClass",
]
"""
Identifier: csst_proto/demo.py
Name: demo.py
Description: 这个文件包括了一个演示函数和演示类
Author: Bo Zhang
Created: 2023-10-26
Modified-History:
2023-10-26, Bo Zhang, add module header
2023-10-28,
"""
import toml
import os
import pathlib
from typing import Optional
# 如何找到当前.py文件所在的文件夹绝对路径?
# 方法1: 使用 pathlib
# HERE: pathlib.Path = pathlib.Path(__file__).parent.resolve()
# 方法2: 使用 os
HERE: str = os.path.dirname(__file__)
# 这个函数演示了如何利用随包数据
# 当config_path被指定时,会读取指定的config_path
# 当config_path=None时,读取随包数据中的config/default_config.toml
def read_config(config_path: Optional[str] = None):
"""Get config info from a toml file.
Read a `toml` format config file.
If `config_path` is specified, read that config.
Otherwise, read the default config in `config/default_config.toml`.
Parameters
----------
config_path : Optional[str]
The config file path.
Returns
-------
dict
The configuration dictionary.
"""
# if config_path is specified, use it, otherwise use the default
if config_path is None:
config_path: str = os.path.join(HERE, "config", "default_config.toml")
# read the config file
config: dict = toml.load(config_path)
return config
A=1
B=2
\ No newline at end of file
def a_demo_function(*args): """
Identifier: csst_proto/demo.py
Name: demo.py
Description: 这个文件包括了一个演示函数和演示类
Author: Bo Zhang
Created: 2023-10-26
Modified-History:
2023-10-28, Bo Zhang, add module header
"""
from typing import Any
def demo_function(*args: Any):
""" """
A demo function. A demo function.
This function is a demo. This function count the input positional arguments and returns the counts.
Parameters Parameters
---------- ----------
*args : any *args : Any
The argument list. The input positional arguments.
Returns Returns
------- -------
int int
The number of input arguments. The count of input positional arguments.
Examples Examples
-------- --------
>>> a_demo_function(None) >>> demo_function(None)
""" """
return len(args) return len(args)
class ADemoClass: class DemoClass:
""" """
A demo class. A demo class.
...@@ -49,9 +62,10 @@ class ADemoClass: ...@@ -49,9 +62,10 @@ class ADemoClass:
Examples Examples
-------- --------
>>> a = ADemoClass("Jane", "Doe") >>> a = DemoClass("Jane", "Doe")
>>> a.say_hello() >>> a.say_hello()
""" """
def __init__(self, first_name, last_name): def __init__(self, first_name, last_name):
self.first_name = first_name self.first_name = first_name
self.last_name = last_name self.last_name = last_name
......
import numpy as np """
import joblib Identifier: csst_proto/flip_image.py
Name: flip_image.py
Description: 这个模块包括了一个图像翻转函数和一个读取随包默认图像的函数
Author: Bo Zhang
Created: 2023-10-26
Modified-History:
2023-10-26, Bo Zhang, add module header
2023-10-28, Bo Zhang, add comments
"""
import multiprocessing import multiprocessing
from . import PACKAGE_PATH import os
import joblib
import numpy as np
import pathlib
# find the absolute path of this file
# use pathlib
# HERE: pathlib.Path = pathlib.Path(__file__).parent.resolve()
# or use os
HERE: str = os.path.dirname(__file__)
# the main algorithm # 此函数翻转了输入图像
def flip_image(img: np.ndarray) -> np.ndarray: # 当use_numpy=True时用numpy函数进行翻转
# 当use_numpy=False时用用指标进行翻转
def flip_image(image: np.ndarray, use_numpy: bool = False) -> np.ndarray:
""" """
Flip an input image. Flip an input image.
...@@ -13,8 +32,10 @@ def flip_image(img: np.ndarray) -> np.ndarray: ...@@ -13,8 +32,10 @@ def flip_image(img: np.ndarray) -> np.ndarray:
Parameters Parameters
---------- ----------
img : np.ndarray image : np.ndarray
The input image. The input image.
use_numpy : bool
Use numpy.flipud and numpy.fliplr if True, otherwise use indices.
Returns Returns
------- -------
...@@ -23,22 +44,27 @@ def flip_image(img: np.ndarray) -> np.ndarray: ...@@ -23,22 +44,27 @@ def flip_image(img: np.ndarray) -> np.ndarray:
Examples Examples
-------- --------
>>> flip_image(np.array([1, 2], [3, 4])) >>> flip_image(np.array([[1, 2], [3, 4]]), use_numpy=False)
array([[4, 3],
[2, 1]])
""" """
try: try:
assert img.ndim == 2 assert image.ndim == 2
img_flipped = img[::-1, ::-1]
return img_flipped if use_numpy:
image_flipped = np.fliplr(np.flipud(image))
else:
image_flipped = image[::-1, ::-1]
return image_flipped
except AssertionError: except AssertionError:
raise AssertionError("The input image is {}D not 2D!".format(img.ndim)) raise AssertionError("The input image is {}D not 2D!".format(image.ndim))
# a demo on how to read test image # 此函数读取了随包数据中的test_image.txt
def read_test_image(): def read_default_image():
""" """Read default image.
Read test image.
This function reads the test image associated with this package. This function reads the default image associated with this package.
Returns Returns
------- -------
...@@ -47,22 +73,8 @@ def read_test_image(): ...@@ -47,22 +73,8 @@ def read_test_image():
Examples Examples
-------- --------
>>> test_image = read_test_image() >>> test_image = read_default_image()
""" """
fp_img = PACKAGE_PATH + "/data/test_image.txt" fp_img = os.path.join(HERE, "/data/test_image.txt")
print("reading file {} ...".format(fp_img)) print("reading file {} ...".format(fp_img))
return np.loadtxt(fp_img, dtype=int) return np.loadtxt(fp_img, dtype=int)
def flip_multiple_images_mp(imgs: list, n_jobs: int) -> list:
""" parallel with multiprocessing """
with multiprocessing.Pool(n_jobs) as p:
results = p.map(flip_image, imgs)
return results
def flip_multiple_images_jl(imgs: list, n_jobs: int) -> list:
""" parallel with joblib """
return joblib.Parallel(n_jobs=n_jobs, backend="multiprocessing")(
joblib.delayed(flip_image)(img) for img in imgs
)
"""
Identifier: csst_proto/flip_image_in_parallel.py
Name: flip_image_in_parallel.py
Description: 这个模块包括了基于joblib和multiprocessing的两种并行翻转图像的函数
Author: Bo Zhang
Created: 2023-10-26
Modified-History:
2023-10-26, Bo Zhang, add module header
2023-10-28, Bo Zhang, add comments, separated from flip_image.py
"""
import multiprocessing
import joblib
import numpy as np
from .flip_image import flip_image
def flip_multiple_images_mp(images: list[np.ndarray], n_jobs: int) -> list[np.ndarray]:
"""Flip input images in parallel.
Flip images in parallel with `multiprocessing`.
Parameters
----------
images : list[np.ndarray]
The input image list.
n_jobs : int
The number of processes.
Returns
-------
The flipped image list.
"""
with multiprocessing.Pool(n_jobs) as p:
results = p.map(flip_image, images)
return results
def flip_multiple_images_jl(images: list[np.ndarray], n_jobs: int) -> list[np.ndarray]:
"""Flip input images in parallel.
Flip images in parallel with `joblib`.
Parameters
----------
images : list[np.ndarray]
The input image list.
n_jobs : int
The number of processes.
Returns
-------
The flipped image list.
"""
return joblib.Parallel(n_jobs=n_jobs, backend="multiprocessing")(
joblib.delayed(flip_image)(image) for image in images
)
numpy==1.23.3 numpy==1.23.3
scipy==1.9.2 scipy==1.9.2
joblib==1.2.0 joblib==1.2.0
setuptools==65.5.1
astropy==5.1 astropy==5.1
pycodestyle==2.9.1
pytest==7.2.1 pytest==7.2.1
pytest-cov==4.0.0 coverage==7.2.1
coverage==7.2.1 toml==0.10.2
\ No newline at end of file \ No newline at end of file
import setuptools import setuptools
import csst_proto
# 读取README.md作为长描述
with open("README.md", "r") as fh: with open("README.md", "r") as fh:
long_description = fh.read() long_description = fh.read()
setuptools.setup( setuptools.setup(
name='csst_proto', name="csst_proto", # 包名
version=csst_proto.__version__, version="0.0.1", # 版本号
author='Bo Zhang', author="Bo Zhang", # 作者
author_email='bozhang@nao.cas.cn', author_email="bozhang@nao.cas.cn", # 邮箱
description='The CSST L1 pipeline - prototype', # short description description="The CSST L1 pipeline - prototype", # 短描述
long_description=long_description, long_description=long_description, # 长描述
long_description_content_type="text/markdown", long_description_content_type="text/markdown", # 长描述类型
url='https://csst-tb.bao.ac.cn/code/csst-l1/csst_proto', url="https://csst-tb.bao.ac.cn/code/csst-l1/csst_proto", # 主页
project_urls={ packages=setuptools.find_packages(), # 用setuptools工具自动发现带有__init__.py的包
'Source': 'https://csst-tb.bao.ac.cn/code/csst-l1/csst_proto', license="MIT", # 证书类型
}, classifiers=[ # 程序分类, 参考 https://pypi.org/classifiers/
packages=setuptools.find_packages(), # How mature is this project?
license='MIT', # 3 - Alpha
classifiers=["Development Status :: 5 - Production/Stable", # 4 - Beta
"Intended Audience :: Science/Research", # 5 - Production/Stable
"License :: OSI Approved :: MIT License", "Development Status :: 3 - Alpha",
"Operating System :: OS Independent", "Intended Audience :: Science/Research",
"Programming Language :: Python :: 3.9", "License :: OSI Approved :: MIT License",
"Topic :: Scientific/Engineering :: Physics", "Operating System :: OS Independent",
"Topic :: Scientific/Engineering :: Astronomy"], "Programming Language :: Python :: 3.11",
package_dir={'csst_proto': 'csst_proto'}, "Topic :: Scientific/Engineering :: Physics",
# include_package_data=True, "Topic :: Scientific/Engineering :: Astronomy",
package_data={"": ["LICENSE", "README.md"], ],
"csst_proto": ["data/test_image.txt", include_package_data=True, # 包含所有随包数据
"data/table_data.csv" # 请注意检查,防止临时文件或其他不必要的文件被提交到仓库,否则会一同安装
]}, python_requires=">=3.11", # Python版本要求
# install_requires=['numpy>1.20.3', ext_modules=[ # 如果有随包的C代码,需要在这里定义扩展
# 'scipy',
# 'matplotlib',
# 'astropy',
# ],
python_requires='>=3.9',
ext_modules=[
setuptools.Extension( setuptools.Extension(
name="csst_proto.cext.helloworld", sources=["cextern/helloworld.c"] name="csst_proto.cext.helloworld",
sources=["cextern/helloworld.c"],
) )
] ],
) )
\ No newline at end of file
"""
Identifier: csst_proto/test_demo_function.py
Name: test_demo_function.py
Description: Test demo function.
Author: Bo Zhang
Created: 2023-10-26
Modified-History:
2023-10-26, Bo Zhang, created
2023-10-26, Bo Zhang, add module header
"""
import unittest
from csst_proto.api import a_demo_function
class TestDemoFunction(unittest.TestCase):
def test_demo_function_1(self):
"""
Aim
---
Test demo function.
Criteria
--------
Pass if the demo function returns `1`.
Details
-------
The demo function returns the length of the input argument list.
This case aims to test whether the demo function returns `1` if input is `None`.
"""
# demo function test
self.assertTrue(
a_demo_function(None) == 1,
"Single-argument case failed.",
)
def test_demo_function_2(self):
"""
Aim
---
Test demo function.
Criteria
--------
Pass if the demo function returns `2`.
Details
-------
The demo function returns the length of the input argument list.
This case aims to test whether the demo function returns `2` if input is `None, None`.
"""
# demo function test
self.assertEqual(
a_demo_function(None, None),
2,
"Double-argument case failed.",
)
def test_demo_function_bad_case(self):
"""
Aim
---
Test demo function.
Criteria
--------
Pass if the demo function result is not equal to `2`.
Details
-------
The demo function returns the length of the input argument list.
This case aims to test whether the demo function result is not equal to `2`
if input is `None, None, None`.
"""
# demo function test
self.assertNotEquals(
a_demo_function(None, None, None),
2,
"Triple-argument case failed.",
)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment