Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
tiagohm committed Apr 1, 2024
2 parents 64201aa + 24ea32d commit 17e5b39
Show file tree
Hide file tree
Showing 273 changed files with 8,327 additions and 6,767 deletions.
3 changes: 2 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@
*.jar binary
*.fit binary
*.fits binary
*.xisf binary
*.ttf binary
*.xcf binary
*.png binary
*.db binary
*.gz binary
*.dll binary
*.so binary
*.zip binary
*.zip binary
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,3 @@ libobjectbox*.dylib
.kotlin

# End of https://www.toptal.com/developers/gitignore/api/intellij,kotlin,java,gradle

**/saved/*.png
**/saved/*.jpg
2 changes: 1 addition & 1 deletion GitHub CI.run.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<option name="externalSystemIdString"
value="GRADLE"/>
<option name="scriptParameters"
value="-Dgithub=true"/>
value="-Dgithub=true --continue"/>
<option name="taskDescriptions">
<list/>
</option>
Expand Down
7 changes: 4 additions & 3 deletions api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import org.springframework.boot.gradle.tasks.bundling.BootJar

plugins {
kotlin("jvm")
id("org.springframework.boot") version "3.2.3"
id("org.springframework.boot") version "3.2.4"
id("io.spring.dependency-management") version "1.1.4"
kotlin("plugin.spring")
kotlin("kapt")
Expand All @@ -19,7 +19,7 @@ dependencies {
implementation(project(":nebulosa-guiding-phd2"))
implementation(project(":nebulosa-hips2fits"))
implementation(project(":nebulosa-horizons"))
implementation(project(":nebulosa-imaging"))
implementation(project(":nebulosa-image"))
implementation(project(":nebulosa-indi-client"))
implementation(project(":nebulosa-log"))
implementation(project(":nebulosa-lx200-protocol"))
Expand All @@ -29,6 +29,7 @@ dependencies {
implementation(project(":nebulosa-stellarium-protocol"))
implementation(project(":nebulosa-watney"))
implementation(project(":nebulosa-wcs"))
implementation(project(":nebulosa-xisf"))
implementation(libs.apache.codec)
implementation(libs.csv)
implementation(libs.eventbus)
Expand All @@ -45,7 +46,7 @@ dependencies {
implementation("org.springframework.boot:spring-boot-starter-undertow")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
kapt("org.springframework:spring-context-indexer:6.1.4")
kapt("org.springframework:spring-context-indexer:6.1.5")
testImplementation(project(":nebulosa-astrobin-api"))
testImplementation(project(":nebulosa-skycatalog-stellarium"))
testImplementation(project(":nebulosa-test"))
Expand Down
2 changes: 1 addition & 1 deletion api/src/main/kotlin/nebulosa/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ URL: `localhost:{PORT}/ws`
"offset": 0,
"offsetMin": 0,
"offsetMax": 0,
"hasGuiderHead": false,
"hasGuideHead": false,
"pixelSizeX": 0,
"pixelSizeY": 0,
"capturesPath": "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ import nebulosa.batch.processing.ExecutionContext.Companion.getDouble
import nebulosa.batch.processing.ExecutionContext.Companion.getDuration
import nebulosa.batch.processing.delay.DelayStep
import nebulosa.batch.processing.delay.DelayStepListener
import nebulosa.image.format.ImageRepresentation
import nebulosa.indi.device.camera.Camera
import nebulosa.indi.device.camera.FrameType
import nebulosa.indi.device.guide.GuideOutput
import java.nio.file.Files
import java.nio.file.Path
import java.time.Duration

data class DARVJob(
Expand Down Expand Up @@ -65,8 +67,8 @@ data class DARVJob(
onNext(DARVEvent.Finished(id))
}

override fun onExposureFinished(step: CameraExposureStep, stepExecution: StepExecution) {
onNext(CameraExposureFinished(stepExecution.jobExecution, step.camera, 1, 1, Duration.ZERO, 1.0, Duration.ZERO, step.savedPath!!))
override fun onExposureFinished(step: CameraExposureStep, stepExecution: StepExecution, image: ImageRepresentation?, savedPath: Path) {
onNext(CameraExposureFinished(stepExecution.jobExecution, step.camera, 1, 1, Duration.ZERO, 1.0, Duration.ZERO, savedPath))
}

override fun onGuidePulseElapsed(step: GuidePulseStep, stepExecution: StepExecution) {
Expand Down
21 changes: 13 additions & 8 deletions api/src/main/kotlin/nebulosa/api/alignment/polar/tppa/TPPAStep.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ import nebulosa.batch.processing.StepExecution
import nebulosa.batch.processing.StepResult
import nebulosa.common.concurrency.latch.Pauseable
import nebulosa.common.time.Stopwatch
import nebulosa.fits.fits
import nebulosa.imaging.Image
import nebulosa.image.format.ImageRepresentation
import nebulosa.indi.device.camera.Camera
import nebulosa.indi.device.mount.Mount
import nebulosa.log.debug
import nebulosa.log.loggerFor
import nebulosa.math.Angle
import nebulosa.math.deg
import nebulosa.plate.solving.PlateSolver
import java.nio.file.Path

data class TPPAStep(
@JvmField val camera: Camera,
Expand All @@ -30,18 +30,18 @@ data class TPPAStep(
private val longitude: Angle = mount!!.longitude,
private val latitude: Angle = mount!!.latitude,
private val cameraRequest: CameraStartCaptureRequest = request.capture,
) : Step, Pauseable {
) : Step, Pauseable, CameraCaptureListener {

private val cameraExposureStep = CameraExposureStep(camera, cameraRequest)
private val alignment = ThreePointPolarAlignment(solver, longitude, latitude)
private val listeners = LinkedHashSet<TPPAListener>()
private val stopwatch = Stopwatch()
private val stepDistances = DoubleArray(2) { if (request.eastDirection) request.stepDistance else -request.stepDistance }

@Volatile private var image: Image? = null
@Volatile private var mountSlewStep: MountSlewStep? = null
@Volatile private var noSolutionAttempts = 0
@Volatile private var stepExecution: StepExecution? = null
@Volatile private var savedImage: Pair<ImageRepresentation?, Path>? = null

val stepCount
get() = alignment.state
Expand All @@ -65,20 +65,26 @@ data class TPPAStep(
return listeners.remove(listener)
}

override fun onExposureFinished(step: CameraExposureStep, stepExecution: StepExecution, image: ImageRepresentation?, savedPath: Path) {
savedImage = image to savedPath
}

override fun beforeJob(jobExecution: JobExecution) {
cameraExposureStep.registerCameraCaptureListener(this)
cameraExposureStep.beforeJob(jobExecution)
mount?.tracking(true)
}

override fun afterJob(jobExecution: JobExecution) {
cameraExposureStep.afterJob(jobExecution)
cameraExposureStep.unregisterCameraCaptureListener(this)

if (mount != null && request.stopTrackingWhenDone) {
mount.tracking(false)
}

savedImage = null
stopwatch.stop()

listeners.forEach { it.polarAlignmentFinished(this, jobExecution.cancellationToken.isCancelled) }
}

Expand Down Expand Up @@ -119,14 +125,13 @@ data class TPPAStep(
cameraExposureStep.execute(stepExecution)

if (!cancellationToken.isCancelled) {
val savedPath = cameraExposureStep.savedPath ?: return StepResult.FINISHED
image = savedPath.fits().use { image?.load(it, false) ?: Image.open(it, false) }
val saved = savedImage ?: return StepResult.FINISHED

val radius = if (mount == null) 0.0 else ThreePointPolarAlignment.DEFAULT_RADIUS

// Polar alignment step.
val result = alignment.align(
savedPath, image!!, mount?.rightAscension ?: 0.0, mount?.declination ?: 0.0, radius,
saved.second, mount?.rightAscension ?: 0.0, mount?.declination ?: 0.0, radius,
request.compensateRefraction, cancellationToken
)

Expand Down
10 changes: 6 additions & 4 deletions api/src/main/kotlin/nebulosa/api/atlas/SkyAtlasUpdateTask.kt
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,12 @@ class SkyAtlasUpdateTask(

httpClient.newCall(request).execute().use {
if (it.isSuccessful) {
val reader = SimbadDatabaseReader(it.body!!.byteStream().source())

for (entity in reader) {
simbadEntityRepository.save(entity)
it.body!!.byteStream().source().use { source ->
SimbadDatabaseReader(source).use { reader ->
for (entity in reader) {
simbadEntityRepository.save(entity)
}
}
}
} else if (it.code == 404) {
finished = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import nebulosa.guiding.Guider
import nebulosa.guiding.phd2.PHD2Guider
import nebulosa.hips2fits.Hips2FitsService
import nebulosa.horizons.HorizonsService
import nebulosa.imaging.Image
import nebulosa.image.Image
import nebulosa.log.loggerFor
import nebulosa.phd2.client.PHD2Client
import nebulosa.sbd.SmallBodyDatabaseService
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package nebulosa.api.calibration

import nebulosa.fits.*
import nebulosa.imaging.Image
import nebulosa.imaging.algorithms.transformation.correction.BiasSubtraction
import nebulosa.imaging.algorithms.transformation.correction.DarkSubtraction
import nebulosa.imaging.algorithms.transformation.correction.FlatCorrection
import nebulosa.image.Image
import nebulosa.image.algorithms.transformation.correction.BiasSubtraction
import nebulosa.image.algorithms.transformation.correction.DarkSubtraction
import nebulosa.image.algorithms.transformation.correction.FlatCorrection
import nebulosa.image.format.Header
import nebulosa.image.format.ImageHdu
import nebulosa.image.format.ReadableHeader
import nebulosa.indi.device.camera.FrameType
import nebulosa.log.loggerFor
import org.springframework.stereotype.Service
Expand All @@ -31,7 +34,7 @@ class CalibrationFrameService(

return if (darkFrame != null || biasFrame != null || flatFrame != null) {
var transformedImage = if (createNew) image.clone() else image
var calibrationImage = Image(transformedImage.width, transformedImage.height, Header.EMPTY, transformedImage.mono)
var calibrationImage = Image(transformedImage.width, transformedImage.height, Header.Empty, transformedImage.mono)

if (biasFrame != null) {
calibrationImage = biasFrame.path!!.fits().use(calibrationImage::load)!!
Expand Down Expand Up @@ -98,7 +101,8 @@ class CalibrationFrameService(

try {
file.fits().use { fits ->
val (header) = fits.filterIsInstance<ImageHdu>().firstOrNull() ?: return@use
val hdu = fits.filterIsInstance<ImageHdu>().firstOrNull() ?: return@use
val header = hdu.header
val frameType = header.frameType?.takeIf { it != FrameType.LIGHT } ?: return@use

val exposureTime = if (frameType == FrameType.DARK) header.exposureTimeInMicroseconds else 0L
Expand Down Expand Up @@ -174,7 +178,7 @@ class CalibrationFrameService(

@JvmStatic private val LOG = loggerFor<CalibrationFrameService>()

@JvmStatic val Header.frameType
@JvmStatic val ReadableHeader.frameType
get() = frame?.uppercase()?.let {
if ("LIGHT" in it) FrameType.LIGHT
else if ("DARK" in it) FrameType.DARK
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import nebulosa.batch.processing.JobExecution
import nebulosa.batch.processing.JobStatus
import nebulosa.batch.processing.StepExecution
import nebulosa.batch.processing.delay.DelayStep
import nebulosa.image.format.ImageRepresentation
import java.nio.file.Path

data class CameraCaptureEventHandler(private val observer: Observer<MessageEvent>) : CameraCaptureListener {

Expand All @@ -31,8 +33,8 @@ data class CameraCaptureEventHandler(private val observer: Observer<MessageEvent
sendCameraExposureEvent(step, stepExecution, state)
}

override fun onExposureFinished(step: CameraExposureStep, stepExecution: StepExecution) {
sendCameraExposureEvent(step, stepExecution, CameraCaptureState.EXPOSURE_FINISHED)
override fun onExposureFinished(step: CameraExposureStep, stepExecution: StepExecution, image: ImageRepresentation?, savedPath: Path) {
sendCameraExposureEvent(step, stepExecution, CameraCaptureState.EXPOSURE_FINISHED, savedPath)
}

override fun onCaptureFinished(step: CameraExposureStep, jobExecution: JobExecution) {
Expand All @@ -41,7 +43,7 @@ data class CameraCaptureEventHandler(private val observer: Observer<MessageEvent
observer.onNext(CameraCaptureFinished(jobExecution, step.camera, step.exposureAmount, captureElapsedTime, aborted))
}

fun sendCameraExposureEvent(step: CameraExposureStep, stepExecution: StepExecution, state: CameraCaptureState) {
fun sendCameraExposureEvent(step: CameraExposureStep, stepExecution: StepExecution, state: CameraCaptureState, savedPath: Path? = null) {
val exposureCount = stepExecution.context.getInt(CameraExposureStep.EXPOSURE_COUNT)
val captureElapsedTime = stepExecution.context.getDuration(CameraExposureStep.CAPTURE_ELAPSED_TIME)
val captureProgress = stepExecution.context.getDouble(CameraExposureStep.CAPTURE_PROGRESS)
Expand Down Expand Up @@ -83,7 +85,7 @@ data class CameraCaptureEventHandler(private val observer: Observer<MessageEvent
stepExecution.jobExecution, step.camera,
step.exposureAmount, exposureCount,
captureElapsedTime, captureProgress, captureRemainingTime,
step.savedPath!!
savedPath!!,
)
}
else -> return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package nebulosa.api.cameras

import nebulosa.batch.processing.JobExecution
import nebulosa.batch.processing.StepExecution
import nebulosa.image.format.ImageRepresentation
import java.nio.file.Path

interface CameraCaptureListener {

Expand All @@ -11,7 +13,7 @@ interface CameraCaptureListener {

fun onExposureElapsed(step: CameraExposureStep, stepExecution: StepExecution) = Unit

fun onExposureFinished(step: CameraExposureStep, stepExecution: StepExecution) = Unit
fun onExposureFinished(step: CameraExposureStep, stepExecution: StepExecution, image: ImageRepresentation?, savedPath: Path) = Unit

fun onCaptureFinished(step: CameraExposureStep, jobExecution: JobExecution) = Unit
}
32 changes: 15 additions & 17 deletions api/src/main/kotlin/nebulosa/api/cameras/CameraExposureStep.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import nebulosa.batch.processing.StepResult
import nebulosa.batch.processing.delay.DelayStep
import nebulosa.batch.processing.delay.DelayStepListener
import nebulosa.common.concurrency.latch.CountUpDownLatch
import nebulosa.fits.Fits
import nebulosa.indi.device.camera.*
import nebulosa.io.transferAndClose
import nebulosa.log.debug
Expand All @@ -20,7 +19,6 @@ import okio.sink
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.io.InputStream
import java.nio.file.Path
import java.time.Duration
import java.time.LocalDateTime
Expand Down Expand Up @@ -50,9 +48,6 @@ data class CameraExposureStep(

@Volatile private var stepExecution: StepExecution? = null

@Volatile override var savedPath: Path? = null
private set

override fun registerCameraCaptureListener(listener: CameraCaptureListener): Boolean {
return listeners.add(listener)
}
Expand All @@ -66,7 +61,7 @@ data class CameraExposureStep(
if (event.device === camera) {
when (event) {
is CameraFrameCaptured -> {
save(event.stream, event.fits)
save(event)
}
is CameraExposureAborted,
is CameraExposureFailed,
Expand Down Expand Up @@ -168,25 +163,26 @@ data class CameraExposureStep(
}
}

private fun save(stream: InputStream?, fits: Fits?) {
private fun save(event: CameraFrameCaptured) {
try {
savedPath = request.makeSavePath(camera)
val savedPath = request.makeSavePath(camera)

LOG.info("saving FITS. path={}", savedPath)
LOG.info("saving FITS image at {}", savedPath)

savedPath!!.createParentDirectories()
savedPath.createParentDirectories()

if (stream != null) {
stream.transferAndClose(savedPath!!.outputStream())
} else if (fits != null) {
savedPath!!.outputStream().use { fits.writeTo(it.sink()) }
if (event.stream != null) {
event.stream!!.transferAndClose(savedPath.outputStream())
} else if (event.image != null) {
savedPath.sink().use(event.image!!::write)
} else {
LOG.warn("invalid event. camera={}", event.device)
return
}

listeners.forEach { it.onExposureFinished(this, stepExecution!!) }
listeners.forEach { it.onExposureFinished(this, stepExecution!!, event.image, savedPath) }
} catch (e: Throwable) {
LOG.error("failed to save FITS", e)
LOG.error("failed to save FITS image", e)
aborted = true
} finally {
latch.countDown()
Expand Down Expand Up @@ -230,7 +226,9 @@ data class CameraExposureStep(
@JvmStatic private val DATE_TIME_FORMAT = DateTimeFormatter.ofPattern("yyyyMMdd.HHmmssSSS")

@JvmStatic
fun CameraStartCaptureRequest.makeSavePath(camera: Camera, autoSave: Boolean = this.autoSave): Path {
internal fun CameraStartCaptureRequest.makeSavePath(
camera: Camera, autoSave: Boolean = this.autoSave,
): Path {
return if (autoSave) {
val now = LocalDateTime.now()
val savePath = autoSubFolderMode.pathFor(savePath!!, now)
Expand Down
Loading

0 comments on commit 17e5b39

Please sign in to comment.