Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ lazy val testkit = crossProject(JVMPlatform, JSPlatform)
"org.typelevel" %%% "spire-laws" % spireVersion,
"eu.timepit" %%% "refined-scalacheck" % refinedVersion,
"io.circe" %%% "circe-testing" % circeVersion,
"org.typelevel" %%% "cats-time-testkit" % catsTimeVersion,
"io.chrisdavenport" %%% "cats-scalacheck" % catsScalacheckVersion
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ package core
package math

import cats.data.NonEmptyList
import lucuma.core.math.dimensional._
import lucuma.core.math.units._
import cats.data.NonEmptyMap
import lucuma.core.math.dimensional.*
import lucuma.core.math.units.*
import lucuma.core.util.Enumerated

import java.time.Instant

object BrightnessUnits {
type Integrated
type Surface
Expand All @@ -19,6 +22,7 @@ object BrightnessUnits {
trait FluxDensityContinuum[+T]

type BrightnessMeasure[T] = Measure[BigDecimal] Of Brightness[T]
type BrightnessMeasureOverTime[T] = NonEmptyMap[Instant, Measure[BigDecimal] Of Brightness[T]]
Copy link
Contributor

Choose a reason for hiding this comment

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

I suppose we could use the BrightnessMeasure alias here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sounds like a good idea, to reduce confusion a bit


// Brightness Integrated
implicit object VegaMagnitudeIsIntegratedBrightnessUnit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,24 @@
package lucuma.core.model

import cats.Eq
import cats.implicits._
import cats.data.NonEmptyMap
import cats.implicits.*
import coulomb.*
import coulomb.ops.algebra.cats.all.given
import coulomb.syntax.*
import eu.timepit.refined.cats._
import eu.timepit.refined.cats.*
import eu.timepit.refined.types.numeric.PosBigDecimal
import lucuma.core.math.BrightnessUnits._
import lucuma.core.math.dimensional._
import lucuma.core.math.units._
import lucuma.core.math.BrightnessUnits.*
import lucuma.core.math.dimensional.*
import lucuma.core.math.units.*
import monocle.Focus
import monocle.Lens

import java.time.Instant

final case class EmissionLine[T](
lineWidth: Quantity[PosBigDecimal, KilometersPerSecond],
lineFlux: Measure[PosBigDecimal] Of LineFlux[T]
lineFlux: EmissionLine.LineFluxOverTime[T]
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't know anything about this unfortunately. It makes sense that the "line flux" would vary but are we sure that it does?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'll verify, my input from science is that emission lines can also vary over time

) {

/**
Expand All @@ -28,18 +31,20 @@ final case class EmissionLine[T](
* `Integrated` or `Surface`
*/
def to[T0](implicit conv: TagConverter[LineFlux[T], LineFlux[T0]]): EmissionLine[T0] =
EmissionLine[T0](lineWidth, lineFlux.toTag[LineFlux[T0]])
EmissionLine[T0](lineWidth, lineFlux.map(_.toTag[LineFlux[T0]]))
}

object EmissionLine {
implicit def eqEmissionLine[T]: Eq[EmissionLine[T]] =
type LineFluxOverTime[T] = NonEmptyMap[Instant, Measure[PosBigDecimal] Of LineFlux[T]]
Copy link
Contributor

Choose a reason for hiding this comment

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

I wondered why we don't add a LineFluxMeasure to parallel the BrightnessMeasure.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

Sounds like I just missed it when implementing emission lines. Let's add it.


given eqEmissionLine[T]: Eq[EmissionLine[T]] =
Eq.by(x => (x.lineWidth, x.lineFlux))

/** @group Optics */
def lineWidth[T]: Lens[EmissionLine[T], Quantity[PosBigDecimal, KilometersPerSecond]] =
Focus[EmissionLine[T]](_.lineWidth)

/** @group Optics */
def lineFlux[T]: Lens[EmissionLine[T], Measure[PosBigDecimal] Of LineFlux[T]] =
def lineFlux[T]: Lens[EmissionLine[T], NonEmptyMap[Instant, Measure[PosBigDecimal] Of LineFlux[T]]] =
Focus[EmissionLine[T]](_.lineFlux)
}
Original file line number Diff line number Diff line change
Expand Up @@ -209,27 +209,27 @@ object SourceProfile {

/** @group Optics */
val integratedBrightnesses
: Optional[SourceProfile, SortedMap[Band, BrightnessMeasure[Integrated]]] =
: Optional[SourceProfile, SortedMap[Band, BrightnessMeasureOverTime[Integrated]]] =
integratedSpectralDefinition.andThen(SpectralDefinition.brightnesses[Integrated])

/** @group Optics */
val surfaceBrightnesses: Optional[SourceProfile, SortedMap[Band, BrightnessMeasure[Surface]]] =
val surfaceBrightnesses: Optional[SourceProfile, SortedMap[Band, BrightnessMeasureOverTime[Surface]]] =
surfaceSpectralDefinition.andThen(SpectralDefinition.brightnesses[Surface])

/** @group Optics */
val integratedBrightnessesT: Traversal[SourceProfile, BrightnessMeasure[Integrated]] =
val integratedBrightnessesT: Traversal[SourceProfile, BrightnessMeasureOverTime[Integrated]] =
integratedSpectralDefinition.andThen(SpectralDefinition.brightnessesT[Integrated])

/** @group Optics */
val surfaceBrightnessesT: Traversal[SourceProfile, BrightnessMeasure[Surface]] =
val surfaceBrightnessesT: Traversal[SourceProfile, BrightnessMeasureOverTime[Surface]] =
surfaceSpectralDefinition.andThen(SpectralDefinition.brightnessesT[Surface])

/** @group Optics */
def integratedBrightnessIn[T](b: Band): Traversal[SourceProfile, BrightnessMeasure[Integrated]] =
def integratedBrightnessIn[T](b: Band): Traversal[SourceProfile, BrightnessMeasureOverTime[Integrated]] =
integratedSpectralDefinition.andThen(SpectralDefinition.brightnessIn[Integrated](b))

/** @group Optics */
def surfaceBrightnessIn[T](b: Band): Traversal[SourceProfile, BrightnessMeasure[Surface]] =
def surfaceBrightnessIn[T](b: Band): Traversal[SourceProfile, BrightnessMeasureOverTime[Surface]] =
surfaceSpectralDefinition.andThen(SpectralDefinition.brightnessIn[Surface](b))

/** @group Optics */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
package lucuma.core.model

import cats.Eq
import cats.Order._
import cats.syntax.all._
import eu.timepit.refined.cats._
import cats.Order.*
import cats.syntax.all.*
import eu.timepit.refined.cats.*
import eu.timepit.refined.types.numeric.PosBigDecimal
import lucuma.core.enums.Band
import lucuma.core.math.BrightnessUnits._
import lucuma.core.math.BrightnessUnits.*
import lucuma.core.math.Wavelength
import lucuma.core.math.dimensional._
import lucuma.core.math.dimensional.*
import monocle.Focus
import monocle.Lens
import monocle.Optional
Expand Down Expand Up @@ -44,7 +44,7 @@ object SpectralDefinition {

final case class BandNormalized[T](
sed: UnnormalizedSED,
brightnesses: SortedMap[Band, BrightnessMeasure[T]]
brightnesses: SortedMap[Band, BrightnessMeasureOverTime[T]]
) extends SpectralDefinition[T] {
lazy val bands: List[Band] = brightnesses.keys.toList

Expand All @@ -59,7 +59,7 @@ object SpectralDefinition {
): BandNormalized[T0] =
BandNormalized(
sed,
brightnesses.map { case (band, brightness) => band -> brightness.toTag[Brightness[T0]] }
brightnesses.map { case (band, brightnesses) => band -> brightnesses.map(_.toTag[Brightness[T0]]) }
)
}

Expand All @@ -74,15 +74,15 @@ object SpectralDefinition {
Focus[BandNormalized[T]](_.sed)

/** @group Optics */
def brightnesses[T]: Lens[BandNormalized[T], SortedMap[Band, BrightnessMeasure[T]]] =
def brightnesses[T]: Lens[BandNormalized[T], SortedMap[Band, BrightnessMeasureOverTime[T]]] =
Focus[BandNormalized[T]](_.brightnesses)

/** @group Optics */
def brightnessesT[T]: Traversal[BandNormalized[T], BrightnessMeasure[T]] =
def brightnessesT[T]: Traversal[BandNormalized[T], BrightnessMeasureOverTime[T]] =
brightnesses.each

/** @group Optics */
def brightnessIn[T](b: Band): Traversal[BandNormalized[T], BrightnessMeasure[T]] =
def brightnessIn[T](b: Band): Traversal[BandNormalized[T], BrightnessMeasureOverTime[T]] =
brightnesses.filterIndex((a: Band) => a === b)
}

Expand Down Expand Up @@ -152,15 +152,15 @@ object SpectralDefinition {
bandNormalized.andThen(BandNormalized.sed[T])

/** @group Optics */
def brightnesses[T]: Optional[SpectralDefinition[T], SortedMap[Band, BrightnessMeasure[T]]] =
def brightnesses[T]: Optional[SpectralDefinition[T], SortedMap[Band, BrightnessMeasureOverTime[T]]] =
bandNormalized.andThen(BandNormalized.brightnesses[T])

/** @group Optics */
def brightnessesT[T]: Traversal[SpectralDefinition[T], BrightnessMeasure[T]] =
def brightnessesT[T]: Traversal[SpectralDefinition[T], BrightnessMeasureOverTime[T]] =
bandNormalized.andThen(BandNormalized.brightnessesT[T])

/** @group Optics */
def brightnessIn[T](b: Band): Traversal[SpectralDefinition[T], BrightnessMeasure[T]] =
def brightnessIn[T](b: Band): Traversal[SpectralDefinition[T], BrightnessMeasureOverTime[T]] =
bandNormalized.andThen(BandNormalized.brightnessIn[T](b))

/** @group Optics */
Expand Down
36 changes: 18 additions & 18 deletions modules/core/shared/src/main/scala/lucuma/core/model/Target.scala
Original file line number Diff line number Diff line change
Expand Up @@ -208,29 +208,29 @@ object Target extends WithGid('t'.refined) with TargetOptics {
sourceProfile.andThen(SourceProfile.unnormalizedSED)

/** @group Optics */
val integratedBrightnesses: Optional[Sidereal, SortedMap[Band, BrightnessMeasure[Integrated]]] =
val integratedBrightnesses: Optional[Sidereal, SortedMap[Band, BrightnessMeasureOverTime[Integrated]]] =
sourceProfile.andThen(SourceProfile.integratedBrightnesses)

/** @group Optics */
val surfaceBrightnesses: Optional[Sidereal, SortedMap[Band, BrightnessMeasure[Surface]]] =
val surfaceBrightnesses: Optional[Sidereal, SortedMap[Band, BrightnessMeasureOverTime[Surface]]] =
sourceProfile.andThen(SourceProfile.surfaceBrightnesses)

/** @group Optics */
val integratedBrightnessesT: Traversal[Sidereal, BrightnessMeasure[Integrated]] =
val integratedBrightnessesT: Traversal[Sidereal, BrightnessMeasureOverTime[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedBrightnessesT)

/** @group Optics */
val surfaceBrightnessesT: Traversal[Sidereal, BrightnessMeasure[Surface]] =
val surfaceBrightnessesT: Traversal[Sidereal, BrightnessMeasureOverTime[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceBrightnessesT)

/** @group Optics */
def integratedBrightnessIn[T](
b: Band
): Traversal[Sidereal, BrightnessMeasure[Integrated]] =
): Traversal[Sidereal, BrightnessMeasureOverTime[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedBrightnessIn(b))

/** @group Optics */
def surfaceBrightnessIn[T](b: Band): Traversal[Sidereal, BrightnessMeasure[Surface]] =
def surfaceBrightnessIn[T](b: Band): Traversal[Sidereal, BrightnessMeasureOverTime[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceBrightnessIn(b))

/** @group Optics */
Expand Down Expand Up @@ -328,29 +328,29 @@ object Target extends WithGid('t'.refined) with TargetOptics {

/** @group Optics */
val integratedBrightnesses
: Optional[Nonsidereal, SortedMap[Band, BrightnessMeasure[Integrated]]] =
: Optional[Nonsidereal, SortedMap[Band, BrightnessMeasureOverTime[Integrated]]] =
sourceProfile.andThen(SourceProfile.integratedBrightnesses)

/** @group Optics */
val surfaceBrightnesses: Optional[Nonsidereal, SortedMap[Band, BrightnessMeasure[Surface]]] =
val surfaceBrightnesses: Optional[Nonsidereal, SortedMap[Band, BrightnessMeasureOverTime[Surface]]] =
sourceProfile.andThen(SourceProfile.surfaceBrightnesses)

/** @group Optics */
val integratedBrightnessesT: Traversal[Nonsidereal, BrightnessMeasure[Integrated]] =
val integratedBrightnessesT: Traversal[Nonsidereal, BrightnessMeasureOverTime[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedBrightnessesT)

/** @group Optics */
val surfaceBrightnessesT: Traversal[Nonsidereal, BrightnessMeasure[Surface]] =
val surfaceBrightnessesT: Traversal[Nonsidereal, BrightnessMeasureOverTime[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceBrightnessesT)

/** @group Optics */
def integratedBrightnessIn[T](
b: Band
): Traversal[Nonsidereal, BrightnessMeasure[Integrated]] =
): Traversal[Nonsidereal, BrightnessMeasureOverTime[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedBrightnessIn(b))

/** @group Optics */
def surfaceBrightnessIn[T](b: Band): Traversal[Nonsidereal, BrightnessMeasure[Surface]] =
def surfaceBrightnessIn[T](b: Band): Traversal[Nonsidereal, BrightnessMeasureOverTime[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceBrightnessIn(b))

/** @group Optics */
Expand Down Expand Up @@ -462,29 +462,29 @@ trait TargetOptics { this: Target.type =>
sourceProfile.andThen(SourceProfile.unnormalizedSED)

/** @group Optics */
val integratedBrightnesses: Optional[Target, SortedMap[Band, BrightnessMeasure[Integrated]]] =
val integratedBrightnesses: Optional[Target, SortedMap[Band, BrightnessMeasureOverTime[Integrated]]] =
sourceProfile.andThen(SourceProfile.integratedBrightnesses)

/** @group Optics */
val surfaceBrightnesses: Optional[Target, SortedMap[Band, BrightnessMeasure[Surface]]] =
val surfaceBrightnesses: Optional[Target, SortedMap[Band, BrightnessMeasureOverTime[Surface]]] =
sourceProfile.andThen(SourceProfile.surfaceBrightnesses)

/** @group Optics */
val integratedBrightnessesT: Traversal[Target, BrightnessMeasure[Integrated]] =
val integratedBrightnessesT: Traversal[Target, BrightnessMeasureOverTime[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedBrightnessesT)

/** @group Optics */
val surfaceBrightnessesT: Traversal[Target, BrightnessMeasure[Surface]] =
val surfaceBrightnessesT: Traversal[Target, BrightnessMeasureOverTime[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceBrightnessesT)

/** @group Optics */
def integratedBrightnessIn[T](
b: Band
): Traversal[Target, BrightnessMeasure[Integrated]] =
): Traversal[Target, BrightnessMeasureOverTime[Integrated]] =
sourceProfile.andThen(SourceProfile.integratedBrightnessIn(b))

/** @group Optics */
def surfaceBrightnessIn[T](b: Band): Traversal[Target, BrightnessMeasure[Surface]] =
def surfaceBrightnessIn[T](b: Band): Traversal[Target, BrightnessMeasureOverTime[Surface]] =
sourceProfile.andThen(SourceProfile.surfaceBrightnessIn(b))

/** @group Optics */
Expand Down
Loading