Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
5da23c7
add swig
Luochenghuang Nov 4, 2024
694d915
Add python wrapper for swig generated python API
Luochenghuang Nov 7, 2024
3a98fae
fix bug where when query the material in tree the second time causes …
Luochenghuang Nov 7, 2024
34edeb5
Add Prism and SlatedPrism
Luochenghuang Nov 7, 2024
4b83858
extend the bounding of the group object from float("-inf") to float("…
Luochenghuang Nov 7, 2024
01ecc24
When material_type is NULL, constitutes a None in python.
Luochenghuang Nov 7, 2024
51065c6
clean up the code a little bit
Luochenghuang Nov 7, 2024
84715d7
add jupyter notebook to showcase the interface
Luochenghuang Nov 7, 2024
072f95d
add 1000 sphere case
Luochenghuang Nov 7, 2024
8b1d2dd
Add benchmark
Luochenghuang Nov 7, 2024
c9c3134
Modify the build script to include relative directories for header fi…
Luochenghuang Nov 14, 2024
41be3cd
Add new macros for when compiling for swig; get rid of manual include…
Luochenghuang Nov 14, 2024
9076e6a
Add readme, minor edits
Luochenghuang Nov 14, 2024
7919184
Change dir name to python
Luochenghuang Nov 14, 2024
ce3b93e
Update the bulid script to add autogen.sh
Luochenghuang Nov 14, 2024
742cf41
Get rid of Guile dependency for when building python extension
Luochenghuang Nov 14, 2024
896274e
update gitignore to exclude python extension generated files
Luochenghuang Nov 14, 2024
9ed3791
Make bounding_box return actual coordinates; Get rid of Material obje…
Luochenghuang Nov 14, 2024
2d5008d
Improve docs, make things more pythonic.
Luochenghuang Nov 15, 2024
b3a4743
Add vector3 arrays and enable creation of Prisms and SlantedPrisms
Luochenghuang Nov 15, 2024
3a7cdce
Clean up .i file
Luochenghuang Nov 15, 2024
1c4a78e
Add tests to the ctlgeom module
Luochenghuang Nov 15, 2024
4b35188
Add tests for ObjectGroup
Luochenghuang Nov 15, 2024
db2df0a
Add readme for python extension
Luochenghuang Nov 15, 2024
bfe89e2
Add loop in c in material_of_numpy_points_in_tree for x10 speed up
Luochenghuang Nov 15, 2024
1ad3961
update notebook
Luochenghuang Nov 15, 2024
1c80504
Add python wrappers for vecterized queries of materials in group.
Luochenghuang Nov 15, 2024
cc12467
update readme
Luochenghuang Nov 15, 2024
82c54e8
rename test.ipynb to demo.ipynb
Luochenghuang Nov 15, 2024
6385568
automake-ified python build
stevengj Nov 15, 2024
73b3cbe
Update README.md
Luochenghuang Nov 15, 2024
fc85a8a
Merge branch 'python' of https://github.com/NanoComp/libctl
Luochenghuang Nov 18, 2024
2a6395e
Fix imports, delete setup.py
Luochenghuang Nov 19, 2024
c51e3fc
Add . into the SUBDIRS varialbes so utils/* gets built when building …
Luochenghuang Nov 19, 2024
8c017f8
Make tweaks to make python installation proper.
Luochenghuang Nov 20, 2024
04fac59
Automatically grab python 3
Luochenghuang Nov 21, 2024
020c2a3
Keep namespace cleaner
Luochenghuang Nov 22, 2024
65b919b
Make python install instruction canonical
Luochenghuang Nov 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ missing
py-compile
compile
test-driver
.DS_Store

# other generated files
example.scm
Expand All @@ -53,4 +54,11 @@ geom-ctl-io.c
geomtst
nlopt-constants.scm
utils/test-prism
*.dat
*.dat

utils/python/__pycache__
utils/python/build
utils/python/libctlgeom.egg-info
utils/python/_libctlgeom.cpython*
utils/python/libctlgeom_wrap.c
utils/python/libctlgeom.py
56 changes: 56 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,57 @@ fi
AC_PROG_EGREP
AC_CHECK_HEADERS(nlopt.h)


##############################################################################
# checks for python
##############################################################################

AC_ARG_WITH(python,
[AS_HELP_STRING([--without-python],[compile without Python interface])],
with_python=$withval,with_python=yes)

AC_CHECK_PROG(SWIG, swig, swig, echo)
if test "$USE_MAINTAINER_MODE" = yes && (test "x$with_python" = "xyes" || test "x$with_scheme" = "xyes") && test "x$SWIG" = xecho; then
AC_MSG_ERROR([SWIG not found; configure --without-python --without-scheme or use a release tarball])
fi

if test "x$with_python" = xno; then
have_python=no
else
if test "$enable_shared" = no; then
AC_MSG_WARN([Python interface requires --enable-shared; disabling])
have_python=no
else
AM_PATH_PYTHON([3],[have_python=yes],[have_python=no])
if test $have_python = yes; then
AC_MSG_CHECKING([for Python include directory])
pinc=`echo "from sysconfig import get_paths; print(get_paths()[['include']])" | $PYTHON - 2>/dev/null`
AC_MSG_RESULT([${pinc:-unknown}])
test -n "$pinc" && PYTHON_INCLUDES="-I$pinc"
save_CPPFLAGS=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $PYTHON_INCLUDES"
AC_CHECK_HEADER([Python.h], [], [AC_MSG_WARN([disabling Python wrappers])
have_python=no])

if test $have_python = yes; then
AC_MSG_CHECKING([for Numpy include directory])
pinc=`echo "import numpy; print (numpy.get_include())" | $PYTHON - 2>/dev/null`
AC_MSG_RESULT([${pinc:-unknown}])
test -n "$pinc" && PYTHON_INCLUDES="$PYTHON_INCLUDES -I$pinc"
CPPFLAGS="$save_CPPFLAGS $PYTHON_INCLUDES"
AC_CHECK_HEADER([numpy/arrayobject.h],[],[
AC_MSG_WARN([disabling Python wrappers])
have_python=no],[#include <Python.h>])
fi

CPPFLAGS=$save_CPPFLAGS
fi # have_python
fi # enabled_shared
fi # with_python

AC_SUBST(PYTHON_INCLUDES)
AM_CONDITIONAL(WITH_PYTHON, test x"$have_python" = "xyes")

###########################################################################

libctl_dir=$srcdir
Expand All @@ -259,4 +310,9 @@ AC_CHECK_LIB(gen, basename)

AC_CONFIG_FILES([Makefile src/Makefile utils/Makefile examples/Makefile examples/example.scm])
AC_CONFIG_FILES([utils/gen-ctl-io], [chmod u+x utils/gen-ctl-io])

if test "x$with_python" = xyes; then
AC_CONFIG_FILES([utils/python/Makefile])
fi

AC_OUTPUT
5 changes: 5 additions & 0 deletions doc/docs/Installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ If you are installing on your personal Linux or BSD machine, then precompiled bi

**Do not compile something from source if an official binary package is available.** For one thing, you're just creating pain for yourself. Worse, the binary package may already be installed, in which case installing a different version from source will just cause trouble.

Python Extension for libctlgeom
------

Please follow the [instructions here](../../utils/python/README.md) to install the python extension.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this needs to be an http to github … I don't think readthedocs will let you link outside the docs directory?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's merge this and then you can do a PR to make a proper link once it is merged and appears on github.


Guile
-----

Expand Down
6 changes: 6 additions & 0 deletions utils/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
if WITH_PYTHON
SUBDIRS = . python
else
SUBDIRS = .
endif

bin_SCRIPTS = gen-ctl-io
include_HEADERS = ctlgeom.h
nodist_include_HEADERS = ctlgeom-types.h
Expand Down
36 changes: 36 additions & 0 deletions utils/python/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
AM_CPPFLAGS = -I$(top_srcdir)/src \
-I$(top_srcdir)/utils \
-I$(top_builddir) # for config.h

BUILT_SOURCES = libctlgeom_wrap.c libctlgeom.py
EXTRA_DIST = $(BUILT_SOURCES) libctlgeom.i numpy.i
MAINTAINERCLEANFILES = $(BUILT_SOURCES)

_libctlgeom_la_SOURCES = libctlgeom_wrap.c
_libctlgeom_la_LIBADD = $(top_builddir)/utils/libctlgeom.la $(PYTHON_LIBS)
_libctlgeom_la_LDFLAGS = -module -version-info @SHARED_VERSION_INFO@
_libctlgeom_la_CPPFLAGS = $(PYTHON_INCLUDES) $(AM_CPPFLAGS)

pyctlgeomdir = $(pythondir)/ctlgeom
pyctlgeom_PYTHON = __init__.py ctlgeom.py libctlgeom.py
pyctlgeom_LTLIBRARIES = _libctlgeom.la

#################################################
# generated code via swig and guile
#################################################

if MAINTAINER_MODE

LIBCTL_SWIG_SRC = libctlgeom.i numpy.i

HPPFILES= \
$(top_srcdir)/utils/ctlgeom.h \
$(top_srcdir)/src/ctl.h \
$(top_srcdir)/utils/ctlgeom-types.h

libctlgeom_wrap.c: $(LIBCTL_SWIG_SRC) $(HPPFILES)
$(SWIG) -Wextra $(SWIG_MEEP_FLAGS) $(AM_CPPFLAGS) -outdir $(builddir) -python -o $@ $(srcdir)/libctlgeom.i

libctlgeom.py: libctlgeom_wrap.c

endif # MAINTAINER_MODE
194 changes: 194 additions & 0 deletions utils/python/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
# Python Extension for libctl

This directory contains SWIG bindings to create a Python extension for libctl.

## Prerequisites
- SWIG
- Python 3.x
- A C compiler (gcc, clang, etc.)

## Installation (build from source)

In the top source directory, run the following
```bash
./configure --enable-maintainer-mode --enable-shared
make
make install
```
Note that you'll need to have `guile` installed to build from source.

## Installation (from a release)

If you are building from an official `.tar.gz` package on the [releases page](https://github.com/NanoComp/libctl/releases), then you can run the following commands:
```bash
tar xvzf libctl-x.x.x.tar.gz
cd libctl-x.x.x
./configure --enable-shared --without-guile
make
make install
```

If you *don't* want to install the python extension, you can configure with `--without-python`.


## Usage Examples

### Basic Shapes

```python
from ctlgeom import Sphere, Cylinder, Block, Cone, Wedge, Ellipsoid, Prism, SlantedPrism

# Create a sphere
sphere = Sphere(
material="metal",
center=(0, 0, 0),
radius=1.0
)

# Create a cylinder
cylinder = Cylinder(
material=1 + 1j,
center=(0, 0, 0),
radius=1.0,
height=2.0,
axis=(0, 0, 1)
)

# Create a block (rectangular prism)
block = Block(
material={"foo" : 42},
center=(0, 0, 0),
e1=(1, 0, 0), # x-axis
e2=(0, 1, 0), # y-axis
e3=(0, 0, 1), # z-axis
size=(2.0, 3.0, 4.0)
)

# Create a cone
cone = Cone(
material="glass",
center=(0, 0, 0),
radius=1.0, # base radius
height=2.0,
axis=(0, 0, 1),
radius2=0.5 # top radius (0 for perfect cone)
)

# Create a wedge (partial cylinder)
wedge = Wedge(
material="plastic",
center=(0, 0, 0),
radius=1.0,
height=2.0,
axis=(0, 0, 1),
wedge_angle=1.57, # 90 degrees in radians
wedge_start=(1, 0, 0)
)

# Create an ellipsoid
ellipsoid = Ellipsoid(
material="glass",
center=(0, 0, 0),
e1=(1, 0, 0),
e2=(0, 1, 0),
e3=(0, 0, 1),
size=(2.0, 3.0, 4.0) # semi-axes lengths
)

# Create a prism from vertices
vertices = [
(1.0, 0.0, 0.0),
(0.0, 1.0, 0.0),
(-1.0, 0.0, 0.0)
]
prism = Prism(
material="metal",
vertices=vertices,
height=2.0,
axis=(0, 0, 1),
center=(0, 0, 0) # optional
)

# Create a slanted prism
slanted_prism = SlantedPrism(
material="metal",
vertices=vertices,
height=2.0,
axis=(0, 0, 1),
sidewall_angle=0.523, # 30 degrees in radians
center=(0, 0, 0) # optional
)
```

### Working with Shapes

```python
from ctlgeom import point_is_in_object, ObjectGroup

# Check if a point is inside an object
point = (0.5, 0.5, 0.5)
is_inside = point_is_in_object(point, sphere)

# Get object volume
volume = sphere.volume()

# Get object bounding box
low, high = sphere.bounding_box()

# Group multiple objects
group = ObjectGroup([sphere, cylinder, block])

# Query material at a point
material = group.material_at_point(point)

# Query the material at a numpy array of points. (Must faster than python loops!)
material = group.material_at_numpy_points(point)

# Query the material at a cartesian grid
material = group.material_on_grid(xx, yy, zz)

# Display debug information
sphere.debug_info()
```

### Vectorized Operations

```python
import numpy as np
import matplotlib.pyplot as plt
import time

sphere1 = Sphere(material=1+3j, center=(0, -0.5, 0), radius=0.5)
sphere2 = Sphere(material=2+2j, center=(0, 0.5, 0), radius=1)
block = Block(material=3+1j, center=(0.5, 0.5, 0), e1=(1, 1, 0), e2=(1, -1, 0), e3=(0, 0, 1), size=(1, 1, 1))
group = ObjectGroup([sphere2, sphere1, block])

# Create a grid of points
x = np.linspace(-1, 1, 500)
y = np.linspace(-1, 1, 500)
xx, yy = np.meshgrid(x, y)
zz = np.zeros_like(xx)

start_time = time.time()
material_map = group.material_on_grid(xx, yy, zz)
end_time = time.time()
print(f"Time taken: {end_time - start_time} seconds")

plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
plt.imshow(material_map.real, cmap='viridis', extent=[-5, 5, -5, 5])
plt.colorbar(label='Material')
plt.title('Real')
plt.subplot(1, 2, 2)
plt.imshow(material_map.imag, cmap='viridis', extent=[-5, 5, -5, 5])
plt.colorbar(label='Material')
plt.title('Imaginary')
plt.show()
```

### Running tests
First, make sure pytest is installed. You can install it by `pip install pytest`.
```bash
cd tests/
pytest * -v
```
2 changes: 2 additions & 0 deletions utils/python/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import libctlgeom
from .ctlgeom import *
Loading