![JAR search and dependency download from the Maven repository](/logo.png)
lucuma.core.model.Target.scala Maven / Gradle / Ivy
// Copyright (c) 2016-2023 Association of Universities for Research in Astronomy, Inc. (AURA)
// For license information see LICENSE or https://opensource.org/licenses/BSD-3-Clause
package lucuma.core.model
import cats.*
import cats.implicits.*
import eu.timepit.refined.cats.*
import eu.timepit.refined.types.string.NonEmptyString
import lucuma.core.enums.Band
import lucuma.core.math.*
import lucuma.core.math.BrightnessUnits.*
import lucuma.core.util.*
import lucuma.refined.*
import monocle.Focus
import monocle.Lens
import monocle.Optional
import monocle.Prism
import monocle.Traversal
import monocle.macros.GenPrism
import scala.collection.immutable.SortedMap
/** A target of observation. */
sealed trait Target extends Product with Serializable {
def name: NonEmptyString
def sourceProfile: SourceProfile
}
object Target extends WithGid('t'.refined) with TargetOptics {
case class Sidereal(
name: NonEmptyString,
tracking: SiderealTracking,
sourceProfile: SourceProfile,
catalogInfo: Option[CatalogInfo]
) extends Target
object Sidereal extends SiderealOptics {
given Eq[Sidereal] =
Eq.by(x => (x.name, x.tracking, x.sourceProfile, x.catalogInfo))
/**
* A sidereal target order based on tracking information, which roughly means by base coordinate
* without applying proper motion.
*
* Not implicit.
*/
val TrackOrder: Order[Sidereal] = Order.by(x => (x.tracking, x.name))
/**
* Sidereal targets ordered by name first and then tracking information.
*
* Not implicit.
*/
val NameOrder: Order[Sidereal] = Order.by(x => (x.name, x.tracking))
}
case class Nonsidereal(
name: NonEmptyString,
ephemerisKey: EphemerisKey,
sourceProfile: SourceProfile
) extends Target
object Nonsidereal extends NonsiderealOptics {
given Eq[Nonsidereal] =
Eq.by(x => (x.name, x.ephemerisKey, x.sourceProfile))
/**
* A nonsidereal target order based on ephemeris key.
*
* Not implicit.
*/
val TrackOrder: Order[Nonsidereal] = Order.by(x => (x.ephemerisKey, x.name))
/**
* Nonsidereal targets ordered by name first and then ephemeris key.
*
* Not implicit.
*/
val NameOrder: Order[Nonsidereal] = Order.by(x => (x.name, x.ephemerisKey))
}
given Eq[Target] = Eq.instance {
case (a @ Sidereal(_, _, _, _), b @ Sidereal(_, _, _, _)) => a === b
case (a @ Nonsidereal(_, _, _), b @ Nonsidereal(_, _, _)) => a === b
case _ => false
}
/**
* A target order based on tracking information. For sidereal targets this roughly means by base
* coordinate without applying proper motion. For non-sidereal this means by `EphemerisKey`.
*
* Not implicit.
*/
val TrackOrder: Order[Target] =
Order.from {
case (a @ Sidereal(_, _, _, _), b @ Sidereal(_, _, _, _)) =>
Sidereal.TrackOrder.compare(a, b)
case (a @ Nonsidereal(_, _, _), b @ Nonsidereal(_, _, _)) =>
Nonsidereal.TrackOrder.compare(a, b)
case (Nonsidereal(_, _, _), _) => -1
case _ => 1
}
/**
* Targets ordered by name first and then tracking information.
*
* Not implicit.
*/
val NameOrder: Order[Target] =
Order.from {
case (a @ Sidereal(_, _, _, _), b @ Sidereal(_, _, _, _)) =>
Sidereal.NameOrder.compare(a, b)
case (a @ Nonsidereal(_, _, _), b @ Nonsidereal(_, _, _)) =>
Nonsidereal.NameOrder.compare(a, b)
case (Nonsidereal(_, _, _), _) => -1
case _ => 1
}
trait SiderealOptics { this: Sidereal.type =>
/** @group Optics */
val name: Lens[Sidereal, NonEmptyString] =
Focus[Sidereal](_.name)
/** @group Optics */
val tracking: Lens[Sidereal, SiderealTracking] =
Focus[Sidereal](_.tracking)
/** @group Optics */
val parallax: Lens[Sidereal, Option[Parallax]] =
tracking.andThen(SiderealTracking.parallax)
/** @group Optics */
val radialVelocity: Lens[Sidereal, Option[RadialVelocity]] =
tracking.andThen(SiderealTracking.radialVelocity)
/** @group Optics */
val baseCoordinates: Lens[Sidereal, Coordinates] =
tracking.andThen(SiderealTracking.baseCoordinates)
/** @group Optics */
val baseRA: Lens[Sidereal, RightAscension] =
tracking.andThen(SiderealTracking.baseRa)
/** @group Optics */
val baseDec: Lens[Sidereal, Declination] =
tracking.andThen(SiderealTracking.baseDec)
/** @group Optics */
val epoch: Lens[Sidereal, Epoch] =
tracking.andThen(SiderealTracking.epoch)
/** @group Optics */
val properMotion: Lens[Sidereal, Option[ProperMotion]] =
tracking.andThen(SiderealTracking.properMotion)
/** @group Optics */
val properMotionRA: Optional[Sidereal, ProperMotion.RA] =
properMotion.some.andThen(ProperMotion.ra)
/** @group Optics */
val properMotionDec: Optional[Sidereal, ProperMotion.Dec] =
properMotion.some.andThen(ProperMotion.dec)
/** @group Optics */
val sourceProfile: Lens[Sidereal, SourceProfile] =
Focus[Sidereal](_.sourceProfile)
/** @group Optics */
val integratedSpectralDefinition: Optional[Sidereal, SpectralDefinition[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedSpectralDefinition)
/** @group Optics */
val surfaceSpectralDefinition: Optional[Sidereal, SpectralDefinition[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceSpectralDefinition)
/** @group Optics */
val fwhm: Optional[Sidereal, Angle] =
sourceProfile.andThen(SourceProfile.fwhm)
/** @group Optics */
val integratedBandNormalizedSpectralDefinition
: Optional[Sidereal, SpectralDefinition.BandNormalized[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedBandNormalizedSpectralDefinition)
/** @group Optics */
val surfaceBandNormalizedSpectralDefinition
: Optional[Sidereal, SpectralDefinition.BandNormalized[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceBandNormalizedSpectralDefinition)
/** @group Optics */
val integratedEmissionLinesSpectralDefinition
: Optional[Sidereal, SpectralDefinition.EmissionLines[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedEmissionLinesSpectralDefinition)
/** @group Optics */
val surfaceEmissionLinesSpectralDefinition
: Optional[Sidereal, SpectralDefinition.EmissionLines[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceEmissionLinesSpectralDefinition)
/** @group Optics */
val unnormalizedSED: Optional[Sidereal, Option[UnnormalizedSED]] =
sourceProfile.andThen(SourceProfile.unnormalizedSED)
/** @group Optics */
val integratedBrightnesses: Optional[Sidereal, SortedMap[Band, BrightnessMeasure[Integrated]]] =
sourceProfile.andThen(SourceProfile.integratedBrightnesses)
/** @group Optics */
val surfaceBrightnesses: Optional[Sidereal, SortedMap[Band, BrightnessMeasure[Surface]]] =
sourceProfile.andThen(SourceProfile.surfaceBrightnesses)
/** @group Optics */
val integratedBrightnessesT: Traversal[Sidereal, BrightnessMeasure[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedBrightnessesT)
/** @group Optics */
val surfaceBrightnessesT: Traversal[Sidereal, BrightnessMeasure[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceBrightnessesT)
/** @group Optics */
def integratedBrightnessIn[T](
b: Band
): Traversal[Sidereal, BrightnessMeasure[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedBrightnessIn(b))
/** @group Optics */
def surfaceBrightnessIn[T](b: Band): Traversal[Sidereal, BrightnessMeasure[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceBrightnessIn(b))
/** @group Optics */
val integratedWavelengthLines
: Optional[Sidereal, SortedMap[Wavelength, EmissionLine[Integrated]]] =
sourceProfile.andThen(SourceProfile.integratedWavelengthLines)
/** @group Optics */
val surfaceWavelengthLines: Optional[Sidereal, SortedMap[Wavelength, EmissionLine[Surface]]] =
sourceProfile.andThen(SourceProfile.surfaceWavelengthLines)
/** @group Optics */
val integratedWavelengthLinesT: Traversal[Sidereal, EmissionLine[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedWavelengthLinesT)
/** @group Optics */
val surfaceWavelengthLinesT: Traversal[Sidereal, EmissionLine[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceWavelengthLinesT)
/** @group Optics */
def integratedWavelengthLineIn(
w: Wavelength
): Traversal[Sidereal, EmissionLine[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedWavelengthLineIn(w))
/** @group Optics */
def surfaceWavelengthLineIn[T](w: Wavelength): Traversal[Sidereal, EmissionLine[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceWavelengthLineIn(w))
/** @group Optics */
val integratedFluxDensityContinuum: Optional[Sidereal, FluxDensityContinuumMeasure[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedFluxDensityContinuum)
/** @group Optics */
val surfaceFluxDensityContinuum: Optional[Sidereal, FluxDensityContinuumMeasure[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceFluxDensityContinuum)
/** @group Optics */
val catalogInfo: Lens[Sidereal, Option[CatalogInfo]] =
Focus[Sidereal](_.catalogInfo)
}
trait NonsiderealOptics { this: Nonsidereal.type =>
/** @group Optics */
val name: Lens[Nonsidereal, NonEmptyString] =
Focus[Nonsidereal](_.name)
/** @group Optics */
val ephemerisKey: Lens[Nonsidereal, EphemerisKey] =
Focus[Nonsidereal](_.ephemerisKey)
val sourceProfile: Lens[Nonsidereal, SourceProfile] =
Focus[Nonsidereal](_.sourceProfile)
/** @group Optics */
val integratedSpectralDefinition: Optional[Nonsidereal, SpectralDefinition[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedSpectralDefinition)
/** @group Optics */
val surfaceSpectralDefinition: Optional[Nonsidereal, SpectralDefinition[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceSpectralDefinition)
/** @group Optics */
val fwhm: Optional[Nonsidereal, Angle] =
sourceProfile.andThen(SourceProfile.fwhm)
/** @group Optics */
val integratedBandNormalizedSpectralDefinition
: Optional[Nonsidereal, SpectralDefinition.BandNormalized[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedBandNormalizedSpectralDefinition)
/** @group Optics */
val surfaceBandNormalizedSpectralDefinition
: Optional[Nonsidereal, SpectralDefinition.BandNormalized[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceBandNormalizedSpectralDefinition)
/** @group Optics */
val integratedEmissionLinesSpectralDefinition
: Optional[Nonsidereal, SpectralDefinition.EmissionLines[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedEmissionLinesSpectralDefinition)
/** @group Optics */
val surfaceEmissionLinesSpectralDefinition
: Optional[Nonsidereal, SpectralDefinition.EmissionLines[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceEmissionLinesSpectralDefinition)
/** @group Optics */
val unnormalizedSED: Optional[Nonsidereal, Option[UnnormalizedSED]] =
sourceProfile.andThen(SourceProfile.unnormalizedSED)
/** @group Optics */
val integratedBrightnesses
: Optional[Nonsidereal, SortedMap[Band, BrightnessMeasure[Integrated]]] =
sourceProfile.andThen(SourceProfile.integratedBrightnesses)
/** @group Optics */
val surfaceBrightnesses: Optional[Nonsidereal, SortedMap[Band, BrightnessMeasure[Surface]]] =
sourceProfile.andThen(SourceProfile.surfaceBrightnesses)
/** @group Optics */
val integratedBrightnessesT: Traversal[Nonsidereal, BrightnessMeasure[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedBrightnessesT)
/** @group Optics */
val surfaceBrightnessesT: Traversal[Nonsidereal, BrightnessMeasure[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceBrightnessesT)
/** @group Optics */
def integratedBrightnessIn[T](
b: Band
): Traversal[Nonsidereal, BrightnessMeasure[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedBrightnessIn(b))
/** @group Optics */
def surfaceBrightnessIn[T](b: Band): Traversal[Nonsidereal, BrightnessMeasure[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceBrightnessIn(b))
/** @group Optics */
val integratedWavelengthLines
: Optional[Nonsidereal, SortedMap[Wavelength, EmissionLine[Integrated]]] =
sourceProfile.andThen(SourceProfile.integratedWavelengthLines)
/** @group Optics */
val surfaceWavelengthLines
: Optional[Nonsidereal, SortedMap[Wavelength, EmissionLine[Surface]]] =
sourceProfile.andThen(SourceProfile.surfaceWavelengthLines)
/** @group Optics */
val integratedWavelengthLinesT: Traversal[Nonsidereal, EmissionLine[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedWavelengthLinesT)
/** @group Optics */
val surfaceWavelengthLinesT: Traversal[Nonsidereal, EmissionLine[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceWavelengthLinesT)
/** @group Optics */
def integratedWavelengthLineIn(
w: Wavelength
): Traversal[Nonsidereal, EmissionLine[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedWavelengthLineIn(w))
/** @group Optics */
def surfaceWavelengthLineIn[T](w: Wavelength): Traversal[Nonsidereal, EmissionLine[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceWavelengthLineIn(w))
/** @group Optics */
val integratedFluxDensityContinuum: Optional[Nonsidereal, FluxDensityContinuumMeasure[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedFluxDensityContinuum)
/** @group Optics */
val surfaceFluxDensityContinuum: Optional[Nonsidereal, FluxDensityContinuumMeasure[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceFluxDensityContinuum)
}
}
trait TargetOptics { this: Target.type =>
/** @group Optics */
val sidereal: Prism[Target, Target.Sidereal] = GenPrism[Target, Target.Sidereal]
/** @group Optics */
val nonsidereal: Prism[Target, Target.Nonsidereal] = GenPrism[Target, Target.Nonsidereal]
/** @group Optics */
val name: Lens[Target, NonEmptyString] =
Lens[Target, NonEmptyString](_.name)(v => {
case t @ Target.Sidereal(_, _, _, _) => Target.Sidereal.name.replace(v)(t)
case t @ Target.Nonsidereal(_, _, _) => Target.Nonsidereal.name.replace(v)(t)
})
/** @group Optics */
val ephemerisKey: Optional[Target, EphemerisKey] =
nonsidereal.andThen(Nonsidereal.ephemerisKey)
/** @group Optics */
val siderealTracking: Optional[Target, SiderealTracking] =
sidereal.andThen(Sidereal.tracking)
/** @group Optics */
val sourceProfile: Lens[Target, SourceProfile] =
Lens[Target, SourceProfile](_.sourceProfile)(v => {
case t @ Target.Sidereal(_, _, _, _) => Target.Sidereal.sourceProfile.replace(v)(t)
case t @ Target.Nonsidereal(_, _, _) => Target.Nonsidereal.sourceProfile.replace(v)(t)
})
/** @group Optics */
val integratedSpectralDefinition: Optional[Target, SpectralDefinition[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedSpectralDefinition)
/** @group Optics */
val surfaceSpectralDefinition: Optional[Target, SpectralDefinition[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceSpectralDefinition)
/** @group Optics */
val fwhm: Optional[Target, Angle] =
sourceProfile.andThen(SourceProfile.fwhm)
/** @group Optics */
val integratedBandNormalizedSpectralDefinition
: Optional[Target, SpectralDefinition.BandNormalized[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedBandNormalizedSpectralDefinition)
/** @group Optics */
val surfaceBandNormalizedSpectralDefinition
: Optional[Target, SpectralDefinition.BandNormalized[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceBandNormalizedSpectralDefinition)
/** @group Optics */
val integratedEmissionLinesSpectralDefinition
: Optional[Target, SpectralDefinition.EmissionLines[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedEmissionLinesSpectralDefinition)
/** @group Optics */
val surfaceEmissionLinesSpectralDefinition
: Optional[Target, SpectralDefinition.EmissionLines[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceEmissionLinesSpectralDefinition)
/** @group Optics */
val unnormalizedSED: Optional[Target, Option[UnnormalizedSED]] =
sourceProfile.andThen(SourceProfile.unnormalizedSED)
/** @group Optics */
val integratedBrightnesses: Optional[Target, SortedMap[Band, BrightnessMeasure[Integrated]]] =
sourceProfile.andThen(SourceProfile.integratedBrightnesses)
/** @group Optics */
val surfaceBrightnesses: Optional[Target, SortedMap[Band, BrightnessMeasure[Surface]]] =
sourceProfile.andThen(SourceProfile.surfaceBrightnesses)
/** @group Optics */
val integratedBrightnessesT: Traversal[Target, BrightnessMeasure[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedBrightnessesT)
/** @group Optics */
val surfaceBrightnessesT: Traversal[Target, BrightnessMeasure[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceBrightnessesT)
/** @group Optics */
def integratedBrightnessIn[T](
b: Band
): Traversal[Target, BrightnessMeasure[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedBrightnessIn(b))
/** @group Optics */
def surfaceBrightnessIn[T](b: Band): Traversal[Target, BrightnessMeasure[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceBrightnessIn(b))
/** @group Optics */
val integratedWavelengthLines: Optional[Target, SortedMap[Wavelength, EmissionLine[Integrated]]] =
sourceProfile.andThen(SourceProfile.integratedWavelengthLines)
/** @group Optics */
val surfaceWavelengthLines: Optional[Target, SortedMap[Wavelength, EmissionLine[Surface]]] =
sourceProfile.andThen(SourceProfile.surfaceWavelengthLines)
/** @group Optics */
val integratedWavelengthLinesT: Traversal[Target, EmissionLine[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedWavelengthLinesT)
/** @group Optics */
val surfaceWavelengthLinesT: Traversal[Target, EmissionLine[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceWavelengthLinesT)
/** @group Optics */
def integratedWavelengthLineIn(
w: Wavelength
): Traversal[Target, EmissionLine[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedWavelengthLineIn(w))
/** @group Optics */
def surfaceWavelengthLineIn[T](w: Wavelength): Traversal[Target, EmissionLine[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceWavelengthLineIn(w))
/** @group Optics */
val integratedFluxDensityContinuum: Optional[Target, FluxDensityContinuumMeasure[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedFluxDensityContinuum)
/** @group Optics */
val surfaceFluxDensityContinuum: Optional[Target, FluxDensityContinuumMeasure[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceFluxDensityContinuum)
/** @group Optics */
val parallax: Optional[Target, Option[Parallax]] =
siderealTracking.andThen(SiderealTracking.parallax)
/** @group Optics */
val radialVelocity: Optional[Target, Option[RadialVelocity]] =
siderealTracking.andThen(SiderealTracking.radialVelocity)
/** @group Optics */
val baseCoordinates: Optional[Target, Coordinates] =
siderealTracking.andThen(SiderealTracking.baseCoordinates)
/** @group Optics */
val baseRA: Optional[Target, RightAscension] =
siderealTracking.andThen(SiderealTracking.baseRa)
/** @group Optics */
val baseDec: Optional[Target, Declination] =
siderealTracking.andThen(SiderealTracking.baseDec)
/** @group Optics */
val epoch: Optional[Target, Epoch] =
sidereal.andThen(Sidereal.epoch)
/** @group Optics */
val properMotion: Optional[Target, Option[ProperMotion]] =
sidereal.andThen(Sidereal.properMotion)
/** @group Optics */
val properMotionRA: Optional[Target, ProperMotion.RA] =
sidereal.andThen(Sidereal.properMotionRA)
/** @group Optics */
val properMotionDec: Optional[Target, ProperMotion.Dec] =
sidereal.andThen(Sidereal.properMotionDec)
/** @group Optics */
val catalogInfo: Optional[Target, Option[CatalogInfo]] =
sidereal.andThen(Sidereal.catalogInfo)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy