JPlateSolve is a pure Java library for automated astrometric plate solving. It provides a unified, asynchronous API to determine the exact celestial coordinates (Right Ascension and Declination) of astronomical images.
It serves as the plate-solving engine behind SpacePixels and is designed to be easily embedded into any Java-based astrophotography tool, observatory control software, or batch processing pipeline.
JPlateSolve supports two completely different backend engines, allowing you to choose between offline speed and online convenience:
- Local Plate Solving (ASTAP): Interfaces directly with a local installation of the blazing-fast ASTAP (Astrometric STAcking Program) executable. Perfect for rapid, offline solving.
- Cloud Plate Solving (Astrometry.net): A fully featured Java wrapper for the nova.astrometry.net REST API. Supports both blind solving and custom solving with parameters.
- Smart FITS Parsing: Automatically reads
nom.tam.fitsheaders (likeOBJCTRAandOBJCTDEC) to extract focal length and coordinate hints, dramatically speeding up the solving process. - Fully Asynchronous: All solving methods return Java
Future<PlateSolveResult>objects, ensuring your application's UI thread is never blocked while waiting for a heavy solve to complete.
- Java 21 or higher:
- For Local Solving: You must have ASTAP and its star databases (e.g., H18 or V17) installed on the host machine.
- For Cloud Solving: nova.astrometry.net will be used
If you are using Gradle, include JPlateSolve in your dependencies:
dependencies {
implementation 'io.github.ppissias.jplatesolve:jplatesolve:1.0.0'
}ASTAP solving is lightning fast but requires the executable to be present on the local machine.
import io.github.ppissias.jplatesolve.PlateSolveResult;
import io.github.ppissias.jplatesolve.astap.ASTAPInterface;
import java.io.File;
import java.util.concurrent.Future;
public class PlateSolverApp {
public void solveLocally() throws Exception {
File astapExe = new File("C:/Program Files/astap/astap.exe"); // Or /usr/bin/astap on Linux
String targetImage = "C:/AstroData/light_frame.fits";
System.out.println("Starting local solve...");
// This starts ASTAP in the background and returns an already-running Future
Future<PlateSolveResult> futureResult = ASTAPInterface.solveImage(astapExe, targetImage);
// .get() will block until ASTAP finishes parsing the image
PlateSolveResult result = futureResult.get();
if (result.isSuccess()) {
System.out.println("Solve Successful!");
System.out.println("RA: " + result.getSolveInformation().get("ra"));
System.out.println("DEC: " + result.getSolveInformation().get("dec"));
} else {
System.out.println("Solve failed: " + result.getFailureReason());
}
}
}If the user doesn't have ASTAP, you can securely upload the image to the Astrometry.net cloud for blind solving.
import io.github.ppissias.jplatesolve.PlateSolveResult;
import io.github.ppissias.jplatesolve.astrometrydotnet.AstrometryDotNet;
import java.io.File;
import java.util.concurrent.Future;
public class CloudSolverApp {
public void solveInCloud() throws Exception {
File targetImage = new File("C:/AstroData/light_frame.fits");
try (AstrometryDotNet cloudSolver = new AstrometryDotNet()) {
// Uses the built-in guest API key by default.
// Pass your own key to new AstrometryDotNet("your-api-key") to override it.
cloudSolver.login();
System.out.println("Uploading image and awaiting blind solve...");
// This fires off the upload and polling threads in the background
Future<PlateSolveResult> futureResult = cloudSolver.blindSolve(targetImage);
// .get() blocks until the remote job finishes (can take a few minutes)
PlateSolveResult result = futureResult.get();
if (result.isSuccess()) {
System.out.println("Cloud Solve Successful!");
System.out.println("Annotated Image URL: " + result.getSolveInformation().get("annotated_image_link"));
System.out.println("Orientation: " + result.getSolveInformation().get("orientation"));
} else {
System.out.println("Cloud solve failed: " + result.getFailureReason());
}
}
}
}JPlateSolve uses Gradle as its build system. To build the standalone .jar library yourself:
-
Clone the repository:
git clone [https://github.com/ppissias/jplatesolve.git](https://github.com/ppissias/jplatesolve.git) cd jplatesolve -
Build the project using the Gradle Wrapper:
# On Linux/macOS ./gradlew build # On Windows gradlew.bat build
-
The compiled
.jarfile will be located in thebuild/libs/directory. -
Live Astrometry.net checks are separated from the default test task:
./gradlew integrationTest
JPlateSolve is configured to generate a Maven Central-compatible publication with:
javadoc.jarsources.jar- POM metadata
- PGP signatures
- checksum files
Because the Central Portal does not currently provide an official Gradle publishing plugin, this build produces a signed upload bundle you can submit to the Portal manually.
-
Create
gradle.propertiesin the project root or%USERPROFILE%\.gradle\gradle.properties, then fill in your local values. -
Configure signing credentials. The simplest option is in-memory Gradle properties:
export ORG_GRADLE_PROJECT_signingKey="..." export ORG_GRADLE_PROJECT_signingPassword="..."
-
Build the signed Central bundle:
./gradlew clean mavenCentralBundle
-
Upload the generated file from:
build/distributions/jplatesolve-<version>-central-bundle.zip
Before uploading, make sure your io.github.ppissias namespace is verified in the Central Portal.
The full standardized release workflow is documented in PUBLISHING.md.
BSD 2-Clause License