Skip to content

danielradosa/sweg

Repository files navigation

sweg

Swiss Ephemeris GO wrapper.

A complete Swiss Ephemeris wrapper for Go.

Swiss Ephemeris is the de-facto astronomical engine for astrology and high-precision ephemeris work — planetary positions, houses, eclipses, fixed stars, and more. sweg exposes its full C API to Go through cgo, so you can call it with native Go types.

jd := sweg.Julday(2025, 1, 1, 12.0, sweg.SeGregCal)   // Julian day, 2025-01-01 12:00 UT

xx := make([]float64, 6)    // results: lon, lat, dist, + their speeds
serr := make([]byte, 256)   // error message buffer

sweg.CalcUt(jd, sweg.SeSun, sweg.SeflgSwieph|sweg.SeflgSpeed, xx, serr)
fmt.Printf("Sun longitude: %.4f°\n", xx[0])   // → 281.3234°  (Capricorn)

Requirements

  • Go 1.25+
  • cgo enabled (CGO_ENABLED=1) and a working C compiler (clang/gcc)
  • The bundled libswe.so is a macOS / Apple-Silicon (arm64) library. On other platforms, build libswe yourself from the official Swiss Ephemeris C sources and put it where your linker and loader can find it (see below).

Install

go get github.com/danielradosa/sweg

The build works out of the box — cgo links against the bundled libswe.so. The one thing to know: the binary it produces still has to find libswe.so at run time. The library's install name is @rpath/libswe.so and Go bakes no rpath into your binary, so without help you'll see:

dyld: Library not loaded: @rpath/libswe.so — no LC_RPATH's found

Pick whichever fix suits you (all verified):

A. Point the loader at the library at run time

# macOS — directory that contains libswe.so
DYLD_LIBRARY_PATH=/path/to/sweg ./yourapp
# Linux
LD_LIBRARY_PATH=/path/to/libswe ./yourapp

B. Bake the path into the binary at build time

CGO_LDFLAGS="-Wl,-rpath,/path/to/sweg" go build .
# ...then ./yourapp runs with no extra environment.

C. Install the library system-wide — copy libswe.so to a standard loader path (e.g. /usr/local/lib, then sudo ldconfig on Linux).

Tip: when you depend on sweg as a module, libswe.so lives in the Go module cache ($(go env GOMODCACHE)/github.com/danielradosa/sweg@<version>/). Use that directory as the path above, or copy the file next to your binary.

Quick start

package main

import (
	"fmt"

	"github.com/danielradosa/sweg"
)

func main() {
	defer sweg.Close() // releases Swiss Ephemeris resources

	// Optional: point at high-precision ephemeris data files (.se1).
	// Without them, the library uses its built-in fallback automatically.
	// sweg.SetEphePath([]byte("/path/to/ephe"))

	jd := sweg.Julday(2025, 1, 1, 12.0, sweg.SeGregCal)

	xx := make([]float64, 6)
	serr := make([]byte, 256)

	ret := sweg.CalcUt(jd, sweg.SeSun, sweg.SeflgSwieph|sweg.SeflgSpeed, xx, serr)
	if ret < 0 {
		fmt.Println("error:", string(serr))
		return
	}
	fmt.Printf("Sun: lon=%.6f°  lat=%.6f°  dist=%.6f AU  speed=%.6f°/day\n",
		xx[0], xx[1], xx[2], xx[3])
}

How the API works

sweg mirrors the original C API one-to-one, so two conventions carry over:

C idiom In sweg What you do
Output array (double*) []float64 Pass a pre-sized slice, e.g. make([]float64, 6); results are written into it
Error message (char*) serr []byte Pass make([]byte, 256); read it with string(serr) on error
String input (char*) []byte Pass []byte("Sirius")
Return code (int) int32 Most calc functions return < 0 on error (message is in serr)

So the pattern is always: allocate your output slices, call the function, check the return code, read the slices.

What's included

The full Swiss Ephemeris surface — 100 functions. The most-used groups:

Area Functions
Planet & body positions Calc, CalcUt, CalcPctr, NodAps, NodApsUt, GetOrbitalElements
Fixed stars Fixstar, FixstarUt, FixstarMag, Fixstar2, Fixstar2Ut
Houses & angles Houses, HousesEx, HousesEx2, HousePos, HouseName, GauquelinSector
Eclipses & occultations SolEclipseWhen*, LunEclipseWhen*, LunOccultWhen*, …How, …Where
Rise / set / transit / horizon RiseTrans, RiseTransTrueHor, Azalt, AzaltRev, Refrac
Heliacal phenomena HeliacalUt, HeliacalPhenoUt, VisLimitMag, HeliacalAngle
Dates & time Julday, Revjul, UtcToJd, DateConversion, Deltat, Sidtime, TimeEqu
Sidereal / ayanamsa SetSidMode, GetAyanamsa, GetAyanamsaUt, GetAyanamsaName
Setup & config SetEphePath, SetJplFile, SetTopo, SetTidAcc, Version, GetPlanetName, Close
Coordinate & math utilities Degnorm, SplitDeg, Cotrans, CalcEpsilon, DegMidp

Constants are exported in Go-idiomatic CamelCase, e.g. bodies SeSun, SeMoon, SeTrueNode; flags SeflgSwieph, SeflgSpeed, SeflgSidereal; calendars SeGregCal, SeJulCal. See constants.go for the full list.

Thread safety

Swiss Ephemeris keeps global state and isn't thread-safe. sweg guards every call with an internal mutex, so it's safe to call from multiple goroutines — calls are serialized rather than run in parallel.

Ephemeris data files

For maximum precision and the widest date range, download the Swiss Ephemeris data files (.se1) from Astrodienst and point to them with SetEphePath. Without them, the library falls back to its built-in (Moshier) ephemeris automatically — lower precision, but no setup required.

Credits & license

Swiss Ephemeris is created and copyrighted by Astrodienst AG, Zürich. It is dual-licensed under the AGPL-3.0 or a commercial license — those terms govern the bundled libswe library and any software you distribute that links against it. Review them before shipping a product. This repository is a thin Go binding around that library; the cgo glue was generated with c-for-go.

About

Swiss Ephemeris GO wrapper.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors