From 05985ad64448c7b4012d9e437c9796bcffe8253e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Piaggio?= Date: Tue, 29 Oct 2024 21:49:28 -0300 Subject: [PATCH] renames and rearrangements --- .../scala/explore/model/reusability.scala | 6 +- .../explore/cache/CacheModifierUpdaters.scala | 2 +- .../config/AdvancedConfigurationPanel.scala | 7 +- .../config/BasicConfigurationPanel.scala | 6 +- .../explore/config/ConfigurationPanel.scala | 42 ++-- .../config/SpectroscopyModesTable.scala | 77 +++----- .../src/main/scala/explore/itc/ItcProps.scala | 69 ++++--- .../scala/explore/itc/ItcResultsCache.scala | 2 +- .../explore/tabs/ConfigurationTile.scala | 38 ++-- .../main/scala/explore/tabs/ObsTabTiles.scala | 17 +- .../scala/explore/events/ItcMessage.scala | 4 +- .../explore/{cats => givens}/package.scala | 2 +- ...ala => InstrumentConfigAndItcResult.scala} | 29 ++- .../scala/explore/model/Observation.scala | 29 +-- .../explore/model/boopickle/ItcPickler.scala | 32 +-- .../main/scala/explore/model/display.scala | 21 +- .../explore/model/itc/ItcRequestParams.scala | 6 +- .../explore/modes/InstrumentConfig.scala | 126 ++++++++++++ .../explore/modes/InstrumentOverrides.scala | 16 ++ .../modes/SpectroscopyModesMatrix.scala | 187 ++++-------------- .../scala/queries/schemas/itc/syntax.scala | 12 +- .../scala/workers/itc/ITCGraphRequests.scala | 12 +- .../main/scala/workers/itc/ITCRequests.scala | 8 +- 23 files changed, 367 insertions(+), 383 deletions(-) rename model/shared/src/main/scala/explore/{cats => givens}/package.scala (92%) rename model/shared/src/main/scala/explore/model/{BasicConfigAndItc.scala => InstrumentConfigAndItcResult.scala} (51%) create mode 100644 model/shared/src/main/scala/explore/modes/InstrumentConfig.scala create mode 100644 model/shared/src/main/scala/explore/modes/InstrumentOverrides.scala diff --git a/common/src/main/scala/explore/model/reusability.scala b/common/src/main/scala/explore/model/reusability.scala index 9b187dad7a..955665a6f2 100644 --- a/common/src/main/scala/explore/model/reusability.scala +++ b/common/src/main/scala/explore/model/reusability.scala @@ -13,8 +13,8 @@ import explore.model.enums.AgsState import explore.model.enums.SelectedPanel import explore.model.itc.ItcExposureTime import explore.model.itc.ItcTarget +import explore.modes.InstrumentConfig import explore.modes.InstrumentOverrides -import explore.modes.InstrumentRow import explore.undo.UndoStacks import explore.utils.OdbRestClient import japgolly.scalajs.react.ReactCats.* @@ -101,7 +101,7 @@ object reusability: given Reusability[AngularSize] = Reusability.byEq given Reusability[CatalogTargetResult] = Reusability.byEq given Reusability[BasicConfiguration] = Reusability.byEq - given Reusability[BasicConfigAndItc] = Reusability.byEq + given Reusability[InstrumentConfigAndItcResult] = Reusability.byEq given Reusability[GuideStarCandidate] = Reusability.by(_.name.value) given Reusability[AgsPosition] = Reusability.byEq given Reusability[AgsParams] = Reusability.byEq @@ -110,7 +110,7 @@ object reusability: given Reusability[ObsConfiguration] = Reusability.byEq given Reusability[Existence] = Reusability.byEq given Reusability[ItcExposureTime] = Reusability.byEq - given Reusability[InstrumentRow] = Reusability.byEq + given Reusability[InstrumentConfig] = Reusability.byEq given Reusability[CentralWavelength] = Reusability.byEq given Reusability[ObjectTracking] = Reusability.byEq given Reusability[Asterism] = Reusability.byEq[Asterism] diff --git a/explore/src/main/scala/explore/cache/CacheModifierUpdaters.scala b/explore/src/main/scala/explore/cache/CacheModifierUpdaters.scala index dea66a1da0..331bf70f0f 100644 --- a/explore/src/main/scala/explore/cache/CacheModifierUpdaters.scala +++ b/explore/src/main/scala/explore/cache/CacheModifierUpdaters.scala @@ -8,7 +8,7 @@ import cats.Order.given import cats.syntax.all.* import crystal.Pot import eu.timepit.refined.auto.autoUnwrap -import explore.cats.given +import explore.givens.given import explore.model.GroupTree import explore.model.GroupUpdate import explore.model.Observation diff --git a/explore/src/main/scala/explore/config/AdvancedConfigurationPanel.scala b/explore/src/main/scala/explore/config/AdvancedConfigurationPanel.scala index 84bab0e1a7..a553177d3c 100644 --- a/explore/src/main/scala/explore/config/AdvancedConfigurationPanel.scala +++ b/explore/src/main/scala/explore/config/AdvancedConfigurationPanel.scala @@ -27,8 +27,7 @@ import explore.model.ScienceRequirements import explore.model.display.* import explore.model.display.given import explore.model.enums.WavelengthUnits -import explore.modes.GmosNorthSpectroscopyRow -import explore.modes.GmosSouthSpectroscopyRow +import explore.modes.InstrumentConfig import explore.modes.ModeCommonWavelengths import explore.modes.ModeSlitSize import explore.modes.ModeWavelength @@ -230,11 +229,11 @@ sealed abstract class AdvancedConfigurationPanelBuilder[ reqsWavelength.flatMap(cw => (mode, row.instrument) match case (m: ObservingMode.GmosNorthLongSlit, - GmosNorthSpectroscopyRow(rGrating, rFpu, rFilter, _) + InstrumentConfig.GmosNorthSpectroscopy(rGrating, rFpu, rFilter, _) ) if m.grating === rGrating && m.filter === rFilter && m.fpu === rFpu => ModeData.build(row, reqsWavelength) case (m: ObservingMode.GmosSouthLongSlit, - GmosSouthSpectroscopyRow(rGrating, rFpu, rFilter, _) + InstrumentConfig.GmosSouthSpectroscopy(rGrating, rFpu, rFilter, _) ) if m.grating === rGrating && m.filter === rFilter && m.fpu === rFpu => ModeData.build(row, reqsWavelength) case _ => none diff --git a/explore/src/main/scala/explore/config/BasicConfigurationPanel.scala b/explore/src/main/scala/explore/config/BasicConfigurationPanel.scala index 2a737b4c9d..9a681b23c9 100644 --- a/explore/src/main/scala/explore/config/BasicConfigurationPanel.scala +++ b/explore/src/main/scala/explore/config/BasicConfigurationPanel.scala @@ -10,8 +10,8 @@ import crystal.react.hooks.* import explore.Icons import explore.components.ui.ExploreStyles import explore.model.AppContext -import explore.model.BasicConfigAndItc import explore.model.ImagingConfigurationOptions +import explore.model.InstrumentConfigAndItcResult import explore.model.Observation import explore.model.ScienceRequirements import explore.model.ScienceRequirements.Spectroscopy @@ -38,7 +38,7 @@ case class BasicConfigurationPanel( userId: Option[User.Id], obsId: Observation.Id, spectroscopyView: ViewOpt[Spectroscopy], - selectedConfig: View[Option[BasicConfigAndItc]], + selectedConfig: View[Option[InstrumentConfigAndItcResult]], constraints: ConstraintSet, itcTargets: List[ItcTarget], baseCoordinates: Option[CoordinatesAtVizTime], @@ -73,7 +73,7 @@ private object BasicConfigurationPanel: .map(_.wavelength) .fold("Wavelength is required for creating a configuration.".some)(_ => props.selectedConfig.get match { - case Some(BasicConfigAndItc(_, itc)) => + case Some(InstrumentConfigAndItcResult(_, itc)) => itc match { case Some(Right(r)) if r.isPending => "Waiting for ITC result...".some case Some(Right(r)) if r.isSuccess => none diff --git a/explore/src/main/scala/explore/config/ConfigurationPanel.scala b/explore/src/main/scala/explore/config/ConfigurationPanel.scala index d650edb2b7..abbf23dbcc 100644 --- a/explore/src/main/scala/explore/config/ConfigurationPanel.scala +++ b/explore/src/main/scala/explore/config/ConfigurationPanel.scala @@ -18,14 +18,14 @@ import explore.common.ScienceQueries.ScienceRequirementsUndoView import explore.common.ScienceQueries.UpdateScienceRequirements import explore.components.ui.ExploreStyles import explore.model.AppContext -import explore.model.BasicConfigAndItc +import explore.model.InstrumentConfigAndItcResult import explore.model.ObsConfiguration import explore.model.Observation import explore.model.ScienceRequirements import explore.model.ScienceRequirements.Spectroscopy import explore.model.enums.WavelengthUnits import explore.model.itc.ItcTarget -import explore.modes.InstrumentRow +import explore.modes.InstrumentConfig import explore.modes.SpectroscopyModesMatrix import explore.undo.* import japgolly.scalajs.react.* @@ -45,21 +45,21 @@ import monocle.Iso import queries.common.ObsQueriesGQL case class ConfigurationPanel( - userId: Option[User.Id], - programId: Program.Id, - obsId: Observation.Id, - requirements: UndoSetter[ScienceRequirements], - mode: UndoSetter[Option[ObservingMode]], - posAngle: View[PosAngleConstraint], - obsConf: ObsConfiguration, - itcTargets: List[ItcTarget], - baseCoordinates: Option[CoordinatesAtVizTime], - selectedConfig: View[Option[BasicConfigAndItc]], - instrumentRow: Option[InstrumentRow], // configuration selected if reverted - modes: SpectroscopyModesMatrix, - sequenceChanged: Callback, - readonly: Boolean, - units: WavelengthUnits + userId: Option[User.Id], + programId: Program.Id, + obsId: Observation.Id, + requirements: UndoSetter[ScienceRequirements], + mode: UndoSetter[Option[ObservingMode]], + posAngle: View[PosAngleConstraint], + obsConf: ObsConfiguration, + itcTargets: List[ItcTarget], + baseCoordinates: Option[CoordinatesAtVizTime], + selectedConfig: View[Option[InstrumentConfigAndItcResult]], + revertedInstrumentConfig: Option[InstrumentConfig], + modes: SpectroscopyModesMatrix, + sequenceChanged: Callback, + readonly: Boolean, + units: WavelengthUnits ) extends ReactFnProps[ConfigurationPanel](ConfigurationPanel.component) object ConfigurationPanel: @@ -154,11 +154,11 @@ object ConfigurationPanel: modeAligner.view(_.map(_.toInput).orUnassign) val deleteConfiguration: Callback = - optModeView.set(none) >> // Select the reverted config - props.instrumentRow - .map: row => + optModeView.set(none) >> + props.revertedInstrumentConfig + .map: row => // Select the reverted config props.selectedConfig.mod(c => - BasicConfigAndItc( + InstrumentConfigAndItcResult( row, c.flatMap(_.itcResult.flatMap(_.toOption.map(_.asRight))) ).some diff --git a/explore/src/main/scala/explore/config/SpectroscopyModesTable.scala b/explore/src/main/scala/explore/config/SpectroscopyModesTable.scala index 2423fdd53a..31cb010190 100644 --- a/explore/src/main/scala/explore/config/SpectroscopyModesTable.scala +++ b/explore/src/main/scala/explore/config/SpectroscopyModesTable.scala @@ -21,7 +21,7 @@ import explore.components.HelpIcon import explore.components.ui.ExploreStyles import explore.events.* import explore.model.AppContext -import explore.model.BasicConfigAndItc +import explore.model.InstrumentConfigAndItcResult import explore.model.Progress import explore.model.ScienceRequirements import explore.model.WorkerClients.* @@ -74,7 +74,7 @@ import scalajs.js.JSConverters.* case class SpectroscopyModesTable( userId: Option[User.Id], - selectedConfig: View[Option[BasicConfigAndItc]], + selectedConfig: View[Option[InstrumentConfigAndItcResult]], spectroscopyRequirements: ScienceRequirements.Spectroscopy, constraints: ConstraintSet, targets: Option[List[ItcTarget]], @@ -151,7 +151,7 @@ private object SpectroscopyModesTable: private val formatSlitLength: ModeSlitSize => String = ss => f"${ModeSlitSize.milliarcseconds.get(ss.value).setScale(0, BigDecimal.RoundingMode.DOWN)}%1.0f" - private def formatGrating(grating: InstrumentRow#Grating): String = grating match + private def formatGrating(grating: InstrumentConfig#Grating): String = grating match case f: GmosSouthGrating => f.shortName case f: GmosNorthGrating => f.shortName case f: F2Disperser => f.shortName @@ -159,7 +159,7 @@ private object SpectroscopyModesTable: case f: GnirsDisperser => f.shortName case r => r.toString - private def formatFilter(filter: InstrumentRow#Filter): String = filter match + private def formatFilter(filter: InstrumentConfig#Filter): String = filter match case Some(f: GmosSouthFilter) => f.shortName case Some(f: GmosNorthFilter) => f.shortName case f: F2Filter => f.shortName @@ -169,9 +169,9 @@ private object SpectroscopyModesTable: // I think these are valid Orderings because they should be consistent with == // They could probably be Orders, as well, but only Ordering is actually needed here. - private given Ordering[InstrumentRow#Grating] = Ordering.by(_.toString) - private given Ordering[InstrumentRow#Filter] = Ordering.by(_.toString) - private given Ordering[TimeSpan | Unit] = Ordering.by(_.toOption) + private given Ordering[InstrumentConfig#Grating] = Ordering.by(_.toString) + private given Ordering[InstrumentConfig#Filter] = Ordering.by(_.toString) + private given Ordering[TimeSpan | Unit] = Ordering.by(_.toOption) private def formatInstrument(r: (Instrument, NonEmptyString)): String = r match case (i @ Instrument.Gnirs, m) => s"${i.longName} $m" @@ -293,40 +293,6 @@ private object SpectroscopyModesTable: .sortable ) - // extension (row: SpectroscopyModeRow) - // private def rowToConf(cw: Option[Wavelength]): Option[BasicConfiguration] = - // cw.flatMap(row.intervalCenter) - // .flatMap: cc => - // row.instrument match - // case GmosNorthSpectroscopyRow(grating, fpu, filter, modeOverrides) - // if row.focalPlane === FocalPlane.SingleSlit => - // BasicConfiguration - // .GmosNorthLongSlit( - // grating = grating, - // filter = filter, - // fpu = fpu, - // centralWavelength = cc - // ) - // .some - // case GmosSouthSpectroscopyRow(grating, fpu, filter, _) - // if row.focalPlane === FocalPlane.SingleSlit => - // BasicConfiguration - // .GmosSouthLongSlit( - // grating = grating, - // filter = filter, - // fpu = fpu, - // centralWavelength = cc - // ) - // .some - // case _ => none - - // extension (row: SpectroscopyModeRowWithResult) - // private def rowToConfAndItc(cw: Option[Wavelength]): Option[BasicConfigAndItc] = - // row.entry.rowToConf(cw).map(c => BasicConfigAndItc(c, row.result.some)) - - // private def equalsConf(conf: BasicConfiguration, cw: Option[Wavelength]): Boolean = - // row.entry.rowToConf(cw).contains_(conf) - extension (row: SpectroscopyModeRow) private def enabledRow: Boolean = List(Instrument.GmosNorth, Instrument.GmosSouth).contains_(row.instrument.instrument) && @@ -458,7 +424,7 @@ private object SpectroscopyModesTable: props.selectedConfig.get .flatMap: c => rows.value.find: row => - c.configuration === row.entry.instrument + c.instrumentConfig === row.entry.instrument .map(_.entry) // selectedIndex // The selected index needs to be the index into the sorted data, because that is what @@ -475,9 +441,9 @@ private object SpectroscopyModesTable: _ => val optRow: Option[SpectroscopyModeRowWithResult] = selectedIndex.value.flatMap(idx => sortedRows.lift(idx)) - val conf: Option[BasicConfigAndItc] = + val conf: Option[InstrumentConfigAndItcResult] = optRow.map: row => - BasicConfigAndItc(row.entry.instrument, row.result.some) + InstrumentConfigAndItcResult(row.entry.instrument, row.result.some) if (props.selectedConfig.get =!= conf) props.selectedConfig.set(conf) else Callback.empty @@ -531,12 +497,13 @@ private object SpectroscopyModesTable: row.entry.instrument.instrument match case Instrument.GmosNorth | Instrument.GmosSouth => cache.contains: - ItcRequestParams(w, - sn, - snAt, - constraints, - asterism, - row.entry.instrument + ItcRequestParams( + w, + sn, + snAt, + constraints, + asterism, + row.entry.instrument ) case _ => true @@ -612,9 +579,11 @@ private object SpectroscopyModesTable: def toggleRow( row: SpectroscopyModeRowWithResult - ): Option[BasicConfigAndItc] = - Option.when(props.selectedConfig.get.forall(_.configuration =!= row.entry.instrument)): - BasicConfigAndItc(row.entry.instrument, row.result.some) + ): Option[InstrumentConfigAndItcResult] = + Option.when( + props.selectedConfig.get.forall(_.instrumentConfig =!= row.entry.instrument) + ): + InstrumentConfigAndItcResult(row.entry.instrument, row.result.some) def scrollButton(content: VdomNode, style: Css, indexCondition: Int => Boolean): TagMod = selectedIndex.value.whenDefined(idx => @@ -688,7 +657,7 @@ private object SpectroscopyModesTable: ExploreStyles.TableRowSelected .when: props.selectedConfig.get - .exists(_.configuration === row.original.entry.instrument) + .exists(_.instrumentConfig === row.original.entry.instrument) , ( ^.onClick --> ( diff --git a/explore/src/main/scala/explore/itc/ItcProps.scala b/explore/src/main/scala/explore/itc/ItcProps.scala index 6e9c48e6b2..44dcb5fdea 100644 --- a/explore/src/main/scala/explore/itc/ItcProps.scala +++ b/explore/src/main/scala/explore/itc/ItcProps.scala @@ -10,7 +10,7 @@ import cats.derived.* import cats.effect.IO import cats.syntax.all.* import explore.events.ItcMessage -import explore.model.BasicConfigAndItc +import explore.model.InstrumentConfigAndItcResult import explore.model.Observation import explore.model.ScienceRequirements import explore.model.TargetList @@ -18,10 +18,8 @@ import explore.model.WorkerClients.ItcClient import explore.model.boopickle.ItcPicklers.given import explore.model.itc.* import explore.model.reusability.given -import explore.modes.GmosNorthSpectroscopyRow -import explore.modes.GmosSouthSpectroscopyRow -import explore.modes.GmosSpectroscopyOverrides -import explore.modes.InstrumentRow +import explore.modes.InstrumentConfig +import explore.modes.InstrumentOverrides import japgolly.scalajs.react.Reusability import lucuma.core.enums.Band import lucuma.core.math.BrightnessValue @@ -39,7 +37,7 @@ import scala.collection.immutable.SortedMap case class ItcProps( observation: Observation, - selectedConfig: Option[BasicConfigAndItc], // selected row in spectroscopy modes table + selectedConfig: Option[InstrumentConfigAndItcResult], // selected row in spectroscopy modes table at: TargetList ) derives Eq: private val spectroscopyRequirements: Option[ScienceRequirements.Spectroscopy] = @@ -55,15 +53,15 @@ case class ItcProps( // The remote configuration is read in a different query than the itc results // This will work even in the case the user has overriden some parameters // When we use the remote configuration we don't need the exposure time. - private val remoteConfig: Option[BasicConfigAndItc] = + private val remoteConfig: Option[InstrumentConfigAndItcResult] = observation - .toInstrumentRow(at) + .toInstrumentConfig(at) .map: row => - BasicConfigAndItc(row, none) + InstrumentConfigAndItcResult(row, none) // The user may select a configuration on the modes tables, we'd prefer than but if not // we can try with the remote confiiguration provided by the database - val finalConfig: Option[BasicConfigAndItc] = + val finalConfig: Option[InstrumentConfigAndItcResult] = selectedConfig.orElse(remoteConfig) val signalToNoise: Option[SignalToNoise] = @@ -74,14 +72,26 @@ case class ItcProps( private val wavelength: Option[CentralWavelength] = finalConfig - .map(_.configuration) + .map(_.instrumentConfig) .flatMap: - case GmosNorthSpectroscopyRow(_, _, _, Some(GmosSpectroscopyOverrides(cw, _, _))) => cw.some - case GmosSouthSpectroscopyRow(_, _, _, Some(GmosSpectroscopyOverrides(cw, _, _))) => cw.some - case _ => none - - private val instrumentRow: Option[InstrumentRow] = - finalConfig.map(_.configuration) + case InstrumentConfig.GmosNorthSpectroscopy( + _, + _, + _, + Some(InstrumentOverrides.GmosSpectroscopy(cw, _, _)) + ) => + cw.some + case InstrumentConfig.GmosSouthSpectroscopy( + _, + _, + _, + Some(InstrumentOverrides.GmosSpectroscopy(cw, _, _)) + ) => + cw.some + case _ => none + + private val instrumentConfig: Option[InstrumentConfig] = + finalConfig.map(_.instrumentConfig) val itcTargets: Option[NonEmptyList[ItcTarget]] = asterismIds.itcTargets(allTargets).filter(_.canQueryITC).toNel @@ -89,7 +99,7 @@ case class ItcProps( val targets: List[ItcTarget] = itcTargets.foldMap(_.toList) private val queryProps: List[Option[?]] = - List(itcTargets, finalConfig, wavelength, instrumentRow, signalToNoise) + List(itcTargets, finalConfig, wavelength, instrumentConfig, signalToNoise) val isExecutable: Boolean = queryProps.forall(_.isDefined) @@ -110,19 +120,16 @@ case class ItcProps( sn <- signalToNoise snAt <- signalToNoiseAt t <- itcTargets - mode <- instrumentRow - yield IO.println( - s"requesting graphs; wavelength: $w, signalToNoise $sn, signalToNoiseAt $snAt, instrumentRow $mode" - ) >> - ItcClient[IO] - .requestSingle: - ItcMessage.GraphQuery(w, sn, snAt, constraints, t, mode) - .map: - _.toRight(new Throwable("No response from ITC server.")) - .rethrow - .flatTap: result => - IO.println: - s"result: ${result.asterismGraphs.values.map(_.toOption.map(_.itcExposureTime))}" + mode <- instrumentConfig + yield ItcClient[IO] + .requestSingle: + ItcMessage.GraphQuery(w, sn, snAt, constraints, t, mode) + .map: + _.toRight(new Throwable("No response from ITC server.")) + .rethrow + .flatTap: result => + IO.println: + s"result: ${result.asterismGraphs.values.map(_.toOption.map(_.itcExposureTime))}" action.getOrElse: IO.raiseError: diff --git a/explore/src/main/scala/explore/itc/ItcResultsCache.scala b/explore/src/main/scala/explore/itc/ItcResultsCache.scala index c8ac7e321b..35bad965c5 100644 --- a/explore/src/main/scala/explore/itc/ItcResultsCache.scala +++ b/explore/src/main/scala/explore/itc/ItcResultsCache.scala @@ -35,7 +35,7 @@ case class ItcResultsCache( def signalToNoiseAt(w: Option[Wavelength]): EitherNec[ItcQueryProblem, Wavelength] = Either.fromOption(w, NonEmptyChain.of(ItcQueryProblem.MissingSignalToNoiseAt)) - def mode(r: SpectroscopyModeRow): EitherNec[ItcQueryProblem, InstrumentRow] = + def mode(r: SpectroscopyModeRow): EitherNec[ItcQueryProblem, InstrumentConfig] = Either.fromOption( ItcResultsCache.enabledRow(r).option(r.instrument), NonEmptyChain.of(ItcQueryProblem.UnsupportedMode) diff --git a/explore/src/main/scala/explore/tabs/ConfigurationTile.scala b/explore/src/main/scala/explore/tabs/ConfigurationTile.scala index d0c9e7ae66..2a69eba6c4 100644 --- a/explore/src/main/scala/explore/tabs/ConfigurationTile.scala +++ b/explore/src/main/scala/explore/tabs/ConfigurationTile.scala @@ -10,14 +10,14 @@ import explore.components.Tile import explore.components.ui.ExploreStyles import explore.config.ConfigurationPanel import explore.model.AsterismIds -import explore.model.BasicConfigAndItc +import explore.model.InstrumentConfigAndItcResult import explore.model.ObsConfiguration import explore.model.ObsTabTileIds import explore.model.Observation import explore.model.ScienceRequirements import explore.model.TargetList import explore.model.enums.WavelengthUnits -import explore.modes.InstrumentRow +import explore.modes.InstrumentConfig import explore.modes.SpectroscopyModesMatrix import explore.undo.* import japgolly.scalajs.react.Callback @@ -32,22 +32,22 @@ import queries.schemas.itc.syntax.* object ConfigurationTile: def configurationTile( - userId: Option[User.Id], - programId: Program.Id, - obsId: Observation.Id, - requirements: UndoSetter[ScienceRequirements], - mode: UndoSetter[Option[ObservingMode]], - posAngleConstraint: View[PosAngleConstraint], - scienceTargetIds: AsterismIds, - baseCoordinates: Option[CoordinatesAtVizTime], - obsConf: ObsConfiguration, - selectedConfig: View[Option[BasicConfigAndItc]], - instrumentRow: Option[InstrumentRow], // configuration selected if reverted - modes: SpectroscopyModesMatrix, - allTargets: TargetList, - sequenceChanged: Callback, - readonly: Boolean, - units: WavelengthUnits + userId: Option[User.Id], + programId: Program.Id, + obsId: Observation.Id, + requirements: UndoSetter[ScienceRequirements], + mode: UndoSetter[Option[ObservingMode]], + posAngleConstraint: View[PosAngleConstraint], + scienceTargetIds: AsterismIds, + baseCoordinates: Option[CoordinatesAtVizTime], + obsConf: ObsConfiguration, + selectedConfig: View[Option[InstrumentConfigAndItcResult]], + revertedInstrumentConfig: Option[InstrumentConfig], // configuration selected if reverted + modes: SpectroscopyModesMatrix, + allTargets: TargetList, + sequenceChanged: Callback, + readonly: Boolean, + units: WavelengthUnits )(using Logger[IO]) = Tile( ObsTabTileIds.ConfigurationId.id, @@ -65,7 +65,7 @@ object ConfigurationTile: scienceTargetIds.itcTargets(allTargets), baseCoordinates, selectedConfig, - instrumentRow, + revertedInstrumentConfig, modes, sequenceChanged, readonly, diff --git a/explore/src/main/scala/explore/tabs/ObsTabTiles.scala b/explore/src/main/scala/explore/tabs/ObsTabTiles.scala index 09cd028741..5a79bf3c83 100644 --- a/explore/src/main/scala/explore/tabs/ObsTabTiles.scala +++ b/explore/src/main/scala/explore/tabs/ObsTabTiles.scala @@ -106,7 +106,6 @@ case class ObsTabTiles( val targetObservations: Map[Target.Id, SortedSet[Observation.Id]] = programSummaries.targetObservations val obsExecution: Pot[Execution] = programSummaries.obsExecutionPots.getPot(obsId) - // val allTargets: TargetList = programSummaries.targets val obsTargets: TargetList = programSummaries.obsTargets.get(obsId).getOrElse(SortedMap.empty) val obsAttachmentAssignments: ObsAttachmentAssignmentMap = programSummaries.obsAttachmentAssignments @@ -138,13 +137,6 @@ object ObsTabTiles: ) ) - private def itcQueryProps( - obs: Observation, - selectedConfig: Option[BasicConfigAndItc], - targetList: TargetList - ): ItcProps = - ItcProps(obs, selectedConfig, targetList /*, obs.toModeOverride(targetList)*/ ) - private case class Offsets( science: Option[NonEmptyList[Offset]], acquisition: Option[NonEmptyList[Offset]] @@ -178,13 +170,12 @@ object ObsTabTiles: // Ags state .useStateView[AgsState](AgsState.Idle) // the configuration the user has selected from the spectroscopy modes table, if any - .useStateView(none[BasicConfigAndItc]) + .useStateView(none[InstrumentConfigAndItcResult]) .useStateWithReuseBy: (props, _, _, _, selectedConfig) => // itcQueryProps - // println(props.obsTargets) - itcQueryProps(props.observation.get, selectedConfig.get, props.obsTargets) + ItcProps(props.observation.get, selectedConfig.get, props.obsTargets) .useState(Pot.pending[ItcAsterismGraphResults]) // itcGraphResults .useAsyncEffectWithDepsBy((props, _, _, _, selectedConfig, _, _) => - itcQueryProps(props.observation.get, selectedConfig.get, props.obsTargets) + ItcProps(props.observation.get, selectedConfig.get, props.obsTargets) ): (props, ctx, _, _, _, oldItcProps, itcGraphResults) => itcProps => import ctx.given @@ -511,7 +502,7 @@ object ObsTabTiles: targetCoords, obsConf, selectedConfig, - props.observation.get.toInstrumentRow(props.obsTargets), + props.observation.get.toInstrumentConfig(props.obsTargets), props.modes, props.obsTargets, sequenceChanged.mod: diff --git a/model/shared/src/main/scala/explore/events/ItcMessage.scala b/model/shared/src/main/scala/explore/events/ItcMessage.scala index 380a3fea49..a860bc951e 100644 --- a/model/shared/src/main/scala/explore/events/ItcMessage.scala +++ b/model/shared/src/main/scala/explore/events/ItcMessage.scala @@ -11,7 +11,7 @@ import explore.model.itc.ItcRequestParams import explore.model.itc.ItcResult import explore.model.itc.ItcTarget import explore.model.itc.ItcTargetProblem -import explore.modes.InstrumentRow +import explore.modes.InstrumentConfig import explore.modes.SpectroscopyModeRow import lucuma.core.math.SignalToNoise import lucuma.core.math.Wavelength @@ -45,7 +45,7 @@ object ItcMessage extends ItcPicklers: signalToNoiseAt: Wavelength, constraints: ConstraintSet, asterism: NonEmptyList[ItcTarget], - modes: InstrumentRow + modes: InstrumentConfig ) extends Request: type ResponseType = ItcAsterismGraphResults diff --git a/model/shared/src/main/scala/explore/cats/package.scala b/model/shared/src/main/scala/explore/givens/package.scala similarity index 92% rename from model/shared/src/main/scala/explore/cats/package.scala rename to model/shared/src/main/scala/explore/givens/package.scala index 6591bfb5f4..a301f2fb77 100644 --- a/model/shared/src/main/scala/explore/cats/package.scala +++ b/model/shared/src/main/scala/explore/givens/package.scala @@ -1,7 +1,7 @@ // 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 explore.cats +package explore.givens import cats.Endo import cats.Monoid diff --git a/model/shared/src/main/scala/explore/model/BasicConfigAndItc.scala b/model/shared/src/main/scala/explore/model/InstrumentConfigAndItcResult.scala similarity index 51% rename from model/shared/src/main/scala/explore/model/BasicConfigAndItc.scala rename to model/shared/src/main/scala/explore/model/InstrumentConfigAndItcResult.scala index 8a39a315b8..3a0a263cbb 100644 --- a/model/shared/src/main/scala/explore/model/BasicConfigAndItc.scala +++ b/model/shared/src/main/scala/explore/model/InstrumentConfigAndItcResult.scala @@ -9,28 +9,27 @@ import cats.derived.* import cats.syntax.all.* import explore.model.itc.ItcResult import explore.model.itc.ItcTargetProblem -import explore.modes.GmosNorthSpectroscopyRow -import explore.modes.GmosSouthSpectroscopyRow -import explore.modes.InstrumentRow +import explore.modes.InstrumentConfig import lucuma.schemas.model.BasicConfiguration import monocle.Focus import monocle.Lens -case class BasicConfigAndItc( - configuration: InstrumentRow, - itcResult: Option[EitherNec[ItcTargetProblem, ItcResult]] +case class InstrumentConfigAndItcResult( + instrumentConfig: InstrumentConfig, + itcResult: Option[EitherNec[ItcTargetProblem, ItcResult]] ) derives Eq: def toBasicConfiguration: Option[BasicConfiguration] = - configuration match - case GmosNorthSpectroscopyRow(grating, fpu, filter, Some(cw, _, _)) => + instrumentConfig match + case InstrumentConfig.GmosNorthSpectroscopy(grating, fpu, filter, Some(cw, _, _)) => BasicConfiguration.GmosNorthLongSlit(grating, filter, fpu, cw).some - case GmosSouthSpectroscopyRow(grating, fpu, filter, Some(cw, _, _)) => + case InstrumentConfig.GmosSouthSpectroscopy(grating, fpu, filter, Some(cw, _, _)) => BasicConfiguration.GmosSouthLongSlit(grating, filter, fpu, cw).some - case _ => none + case _ => none -object BasicConfigAndItc: - val configuration: Lens[BasicConfigAndItc, InstrumentRow] = - Focus[BasicConfigAndItc](_.configuration) +object InstrumentConfigAndItcResult: + val configuration: Lens[InstrumentConfigAndItcResult, InstrumentConfig] = + Focus[InstrumentConfigAndItcResult](_.instrumentConfig) - val itcResult: Lens[BasicConfigAndItc, Option[EitherNec[ItcTargetProblem, ItcResult]]] = - Focus[BasicConfigAndItc](_.itcResult) + val itcResult + : Lens[InstrumentConfigAndItcResult, Option[EitherNec[ItcTargetProblem, ItcResult]]] = + Focus[InstrumentConfigAndItcResult](_.itcResult) diff --git a/model/shared/src/main/scala/explore/model/Observation.scala b/model/shared/src/main/scala/explore/model/Observation.scala index 3bc802d568..eaabb4e000 100644 --- a/model/shared/src/main/scala/explore/model/Observation.scala +++ b/model/shared/src/main/scala/explore/model/Observation.scala @@ -10,13 +10,10 @@ import cats.derived.* import cats.syntax.all.* import eu.timepit.refined.cats.* import eu.timepit.refined.types.string.NonEmptyString -import explore.cats.given +import explore.givens.given import explore.model.syntax.all.* -import explore.modes.GmosNorthSpectroscopyRow -import explore.modes.GmosSouthSpectroscopyRow -import explore.modes.GmosSpectroscopyOverrides +import explore.modes.InstrumentConfig import explore.modes.InstrumentOverrides -import explore.modes.InstrumentRow import explore.modes.syntax.* import io.circe.Decoder import io.circe.generic.semiauto.* @@ -151,7 +148,11 @@ case class Observation( defaultAmpGain )(defaultMode) - GmosSpectroscopyOverrides(centralWavelength, mode, explicitRoi.getOrElse(defaultRoi)) + InstrumentOverrides.GmosSpectroscopy( + centralWavelength, + mode, + explicitRoi.getOrElse(defaultRoi) + ) case ObservingMode.GmosSouthLongSlit( _, grating, @@ -189,12 +190,16 @@ case class Observation( defaultAmpGain )(defaultMode) - GmosSpectroscopyOverrides(centralWavelength, mode, explicitRoi.getOrElse(defaultRoi)) + InstrumentOverrides.GmosSpectroscopy( + centralWavelength, + mode, + explicitRoi.getOrElse(defaultRoi) + ) - def toInstrumentRow(targets: TargetList): Option[InstrumentRow] = + def toInstrumentConfig(targets: TargetList): Option[InstrumentConfig] = (toModeOverride(targets), observingMode) .mapN: - case (overrides @ GmosSpectroscopyOverrides(_, _, _), + case (overrides @ InstrumentOverrides.GmosSpectroscopy(_, _, _), ObservingMode.GmosNorthLongSlit( _, grating, @@ -220,8 +225,8 @@ case class Observation( _ ) ) => - GmosNorthSpectroscopyRow(grating, fpu, filter, overrides.some).some - case (overrides @ GmosSpectroscopyOverrides(_, _, _), + InstrumentConfig.GmosNorthSpectroscopy(grating, fpu, filter, overrides.some).some + case (overrides @ InstrumentOverrides.GmosSpectroscopy(_, _, _), ObservingMode.GmosSouthLongSlit( _, grating, @@ -247,7 +252,7 @@ case class Observation( _ ) ) => - GmosSouthSpectroscopyRow(grating, fpu, filter, overrides.some).some + InstrumentConfig.GmosSouthSpectroscopy(grating, fpu, filter, overrides.some).some case _ => none .flatten diff --git a/model/shared/src/main/scala/explore/model/boopickle/ItcPickler.scala b/model/shared/src/main/scala/explore/model/boopickle/ItcPickler.scala index 0c6e5e0f02..d051cd77a6 100644 --- a/model/shared/src/main/scala/explore/model/boopickle/ItcPickler.scala +++ b/model/shared/src/main/scala/explore/model/boopickle/ItcPickler.scala @@ -21,7 +21,7 @@ import explore.model.itc.ItcTarget import explore.model.itc.ItcTargetProblem import explore.model.itc.OverridenExposureTime import explore.modes.* -import explore.modes.InstrumentRow +import explore.modes.InstrumentConfig import explore.modes.ModeAO import explore.modes.ModeSlitSize import explore.modes.ModeWavelength @@ -82,28 +82,28 @@ trait ItcPicklers extends CommonPicklers { given Pickler[GmosCcdMode] = generatePickler - given Pickler[GmosSpectroscopyOverrides] = generatePickler + given Pickler[InstrumentOverrides.GmosSpectroscopy] = generatePickler - given Pickler[GmosNorthSpectroscopyRow] = generatePickler + given Pickler[InstrumentConfig.GmosNorthSpectroscopy] = generatePickler - given Pickler[GmosSouthSpectroscopyRow] = generatePickler + given Pickler[InstrumentConfig.GmosSouthSpectroscopy] = generatePickler - given Pickler[Flamingos2SpectroscopyRow] = generatePickler + given Pickler[InstrumentConfig.Flamingos2Spectroscopy] = generatePickler - given Pickler[GpiSpectroscopyRow] = generatePickler + given Pickler[InstrumentConfig.GpiSpectroscopy] = generatePickler - given Pickler[GnirsSpectroscopyRow] = generatePickler + given Pickler[InstrumentConfig.GnirsSpectroscopy] = generatePickler - given Pickler[GenericSpectroscopyRow] = generatePickler + given Pickler[InstrumentConfig.GenericSpectroscopy] = generatePickler - given Pickler[InstrumentRow] = - compositePickler[InstrumentRow] - .addConcreteType[GmosNorthSpectroscopyRow] - .addConcreteType[GmosSouthSpectroscopyRow] - .addConcreteType[Flamingos2SpectroscopyRow] - .addConcreteType[GpiSpectroscopyRow] - .addConcreteType[GnirsSpectroscopyRow] - .addConcreteType[GenericSpectroscopyRow] + given Pickler[InstrumentConfig] = + compositePickler[InstrumentConfig] + .addConcreteType[InstrumentConfig.GmosNorthSpectroscopy] + .addConcreteType[InstrumentConfig.GmosSouthSpectroscopy] + .addConcreteType[InstrumentConfig.Flamingos2Spectroscopy] + .addConcreteType[InstrumentConfig.GpiSpectroscopy] + .addConcreteType[InstrumentConfig.GnirsSpectroscopy] + .addConcreteType[InstrumentConfig.GenericSpectroscopy] given Pickler[ModeWavelength] = picklerNewType(ModeWavelength) diff --git a/model/shared/src/main/scala/explore/model/display.scala b/model/shared/src/main/scala/explore/model/display.scala index 2e55c33211..9de1ea3a68 100644 --- a/model/shared/src/main/scala/explore/model/display.scala +++ b/model/shared/src/main/scala/explore/model/display.scala @@ -7,9 +7,7 @@ import cats.syntax.all.* import eu.timepit.refined.cats.* import explore.model.enums.WavelengthUnits import explore.model.itc.ItcQueryProblem -import explore.modes.GmosNorthSpectroscopyRow -import explore.modes.GmosSouthSpectroscopyRow -import explore.modes.InstrumentRow +import explore.modes.InstrumentConfig import lucuma.core.enums.* import lucuma.core.enums.EducationalStatus import lucuma.core.enums.ObservationWorkflowState @@ -241,13 +239,14 @@ trait DisplayImplicits: case BasicConfiguration.GmosSouthLongSlit(grating, _, fpu, _) => s"GMOS-S ${grating.shortName} ${fpu.shortName}" - extension (instrumentRow: InstrumentRow) - def configurationSummary: Option[String] = instrumentRow match - case GmosNorthSpectroscopyRow(grating, fpu, _, _) => - s"GMOS-N ${grating.shortName} ${fpu.shortName}".some - case GmosSouthSpectroscopyRow(grating, fpu, _, _) => - s"GMOS-S ${grating.shortName} ${fpu.shortName}".some - case _ => - none + extension (revertedInstrumentConfig: InstrumentConfig) + def configurationSummary: Option[String] = + revertedInstrumentConfig match + case InstrumentConfig.GmosNorthSpectroscopy(grating, fpu, _, _) => + s"GMOS-N ${grating.shortName} ${fpu.shortName}".some + case InstrumentConfig.GmosSouthSpectroscopy(grating, fpu, _, _) => + s"GMOS-S ${grating.shortName} ${fpu.shortName}".some + case _ => + none object display extends DisplayImplicits diff --git a/model/shared/src/main/scala/explore/model/itc/ItcRequestParams.scala b/model/shared/src/main/scala/explore/model/itc/ItcRequestParams.scala index 9636dbf764..6d46bcc00a 100644 --- a/model/shared/src/main/scala/explore/model/itc/ItcRequestParams.scala +++ b/model/shared/src/main/scala/explore/model/itc/ItcRequestParams.scala @@ -4,7 +4,7 @@ package explore.model.itc import cats.data.* -import explore.modes.InstrumentRow +import explore.modes.InstrumentConfig import lucuma.core.math.SignalToNoise import lucuma.core.math.Wavelength import lucuma.core.model.ConstraintSet @@ -16,7 +16,7 @@ case class ItcRequestParams( signalToNoiseAt: Wavelength, constraints: ConstraintSet, asterism: NonEmptyList[ItcTarget], - mode: InstrumentRow + mode: InstrumentConfig ) case class ItcGraphRequestParams( @@ -25,5 +25,5 @@ case class ItcGraphRequestParams( signalToNoiseAt: Wavelength, constraints: ConstraintSet, asterism: NonEmptyList[ItcTarget], - mode: InstrumentRow + mode: InstrumentConfig ) diff --git a/model/shared/src/main/scala/explore/modes/InstrumentConfig.scala b/model/shared/src/main/scala/explore/modes/InstrumentConfig.scala new file mode 100644 index 0000000000..69eb64a887 --- /dev/null +++ b/model/shared/src/main/scala/explore/modes/InstrumentConfig.scala @@ -0,0 +1,126 @@ +// 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 explore.modes + +import cats.Eq +import cats.derived.* +import cats.implicits.* +import eu.timepit.refined.* +import eu.timepit.refined.cats.* +import eu.timepit.refined.types.string.* +import lucuma.core.enums.* +import lucuma.core.math.Wavelength +import lucuma.core.math.units.* +import lucuma.core.model.sequence.gmos.GmosCcdMode +import lucuma.core.util.Enumerated +import lucuma.schemas.model.CentralWavelength +import monocle.Getter + +sealed trait InstrumentConfig derives Eq: + def instrument: Instrument + + type Grating + val grating: Grating + + type FPU + val fpu: FPU + + type Filter + val filter: Filter + + val site: Site + + def hasFilter: Boolean + + type Override + def modeOverrides: Option[Override] = None + +object InstrumentConfig: + case class GmosNorthSpectroscopy( + grating: GmosNorthGrating, + fpu: GmosNorthFpu, + filter: Option[GmosNorthFilter], + override val modeOverrides: Option[InstrumentOverrides.GmosSpectroscopy] + ) extends InstrumentConfig derives Eq { + type Grating = GmosNorthGrating + type Filter = Option[GmosNorthFilter] + type FPU = GmosNorthFpu + type Override = InstrumentOverrides.GmosSpectroscopy + val instrument = Instrument.GmosNorth + val site = Site.GN + val hasFilter = filter.isDefined + } + + case class GmosSouthSpectroscopy( + grating: GmosSouthGrating, + fpu: GmosSouthFpu, + filter: Option[GmosSouthFilter], + override val modeOverrides: Option[InstrumentOverrides.GmosSpectroscopy] + ) extends InstrumentConfig derives Eq { + type Grating = GmosSouthGrating + type Filter = Option[GmosSouthFilter] + type FPU = GmosSouthFpu + type Override = InstrumentOverrides.GmosSpectroscopy + val instrument = Instrument.GmosSouth + val site = Site.GS + val hasFilter = filter.isDefined + } + + case class Flamingos2Spectroscopy(grating: F2Disperser, filter: F2Filter) extends InstrumentConfig + derives Eq { + type Grating = F2Disperser + type Filter = F2Filter + type FPU = Unit + type Override = Unit + val fpu = () + val instrument = Instrument.Flamingos2 + val site = Site.GS + val hasFilter = true + } + + case class GpiSpectroscopy(grating: GpiDisperser, filter: GpiFilter) extends InstrumentConfig + derives Eq { + type Grating = GpiDisperser + type Filter = GpiFilter + type FPU = Unit + type Override = Unit + val fpu = () + val instrument = Instrument.Gpi + val site = Site.GN + val hasFilter = true + } + + case class GnirsSpectroscopy(grating: GnirsDisperser, filter: GnirsFilter) + extends InstrumentConfig derives Eq { + type Grating = GnirsDisperser + type Filter = GnirsFilter + type FPU = Unit + type Override = Unit + val fpu = () + val instrument = Instrument.Gnirs + val site = Site.GN + val hasFilter = true + } + + // Used for Instruments not fully defined + case class GenericSpectroscopy(i: Instrument, grating: String, filter: NonEmptyString) + extends InstrumentConfig derives Eq { + type Grating = String + type Filter = NonEmptyString + type FPU = Unit + type Override = Unit + val fpu = () + val instrument = i + val site = Site.GN + val hasFilter = true + } + + val instrument: Getter[InstrumentConfig, Instrument] = + Getter[InstrumentConfig, Instrument](_.instrument) + + def grating: Getter[InstrumentConfig, InstrumentConfig#Grating] = + Getter[InstrumentConfig, InstrumentConfig#Grating](_.grating) + + def filter: Getter[InstrumentConfig, InstrumentConfig#Filter] = + Getter[InstrumentConfig, InstrumentConfig#Filter](_.filter) diff --git a/model/shared/src/main/scala/explore/modes/InstrumentOverrides.scala b/model/shared/src/main/scala/explore/modes/InstrumentOverrides.scala new file mode 100644 index 0000000000..5620226171 --- /dev/null +++ b/model/shared/src/main/scala/explore/modes/InstrumentOverrides.scala @@ -0,0 +1,16 @@ +// 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 explore.modes + +import cats.Eq +import cats.derived.* +import lucuma.core.enums.GmosRoi +import lucuma.core.math.Wavelength +import lucuma.core.math.units.* +import lucuma.core.model.sequence.gmos.GmosCcdMode +import lucuma.core.util.Enumerated +import lucuma.schemas.model.CentralWavelength + +enum InstrumentOverrides derives Eq: + case GmosSpectroscopy(centralWavelength: CentralWavelength, ccdMode: GmosCcdMode, roi: GmosRoi) diff --git a/model/shared/src/main/scala/explore/modes/SpectroscopyModesMatrix.scala b/model/shared/src/main/scala/explore/modes/SpectroscopyModesMatrix.scala index d0ebe47ba5..e5f25d209f 100644 --- a/model/shared/src/main/scala/explore/modes/SpectroscopyModesMatrix.scala +++ b/model/shared/src/main/scala/explore/modes/SpectroscopyModesMatrix.scala @@ -3,9 +3,9 @@ package explore.modes -import _root_.cats.data.NonEmptyList import cats.Eq import cats.Order +import cats.data.NonEmptyList import cats.derived.* import cats.implicits.* import coulomb.* @@ -39,131 +39,6 @@ import monocle.Lens import monocle.macros.GenLens import spire.math.Rational -sealed trait InstrumentRow derives Eq { - def instrument: Instrument - - type Grating - val grating: Grating - - type FPU - val fpu: FPU - - type Filter - val filter: Filter - - val site: Site - - def hasFilter: Boolean - - type Override - def modeOverrides: Option[Override] = None - - // override def toString(): String = s"Mode KKK: ${instrument.shortName}, $grating, $filter, $fpu" -} - -sealed trait InstrumentOverrides derives Eq -case class GmosSpectroscopyOverrides( - centralWavelength: CentralWavelength, - ccdMode: GmosCcdMode, - roi: GmosRoi -) extends InstrumentOverrides derives Eq - -object InstrumentOverrides - -case class GmosNorthSpectroscopyRow( - grating: GmosNorthGrating, - fpu: GmosNorthFpu, - filter: Option[GmosNorthFilter], - override val modeOverrides: Option[GmosSpectroscopyOverrides] -) extends InstrumentRow { - type Grating = GmosNorthGrating - type Filter = Option[GmosNorthFilter] - type FPU = GmosNorthFpu - type Override = GmosSpectroscopyOverrides - val instrument = Instrument.GmosNorth - val site = Site.GN - val hasFilter = filter.isDefined - override def toString(): String = - s"Mode GN: ${instrument.shortName}, $grating, $filter, $fpu, OVER: $modeOverrides" -} - -case class GmosSouthSpectroscopyRow( - grating: GmosSouthGrating, - fpu: GmosSouthFpu, - filter: Option[GmosSouthFilter], - override val modeOverrides: Option[GmosSpectroscopyOverrides] -) extends InstrumentRow { - type Grating = GmosSouthGrating - type Filter = Option[GmosSouthFilter] - type FPU = GmosSouthFpu - type Override = GmosSpectroscopyOverrides - val instrument = Instrument.GmosSouth - val site = Site.GS - val hasFilter = filter.isDefined - override def toString(): String = - s"Mode GS: ${instrument.shortName}, $grating, $filter, $fpu, OVER: $modeOverrides" -} - -case class Flamingos2SpectroscopyRow(grating: F2Disperser, filter: F2Filter) extends InstrumentRow { - type Grating = F2Disperser - type Filter = F2Filter - type FPU = Unit - type Override = Unit - val fpu = () - val instrument = Instrument.Flamingos2 - val site = Site.GS - val hasFilter = true -} - -case class GpiSpectroscopyRow(grating: GpiDisperser, filter: GpiFilter) extends InstrumentRow { - type Grating = GpiDisperser - type Filter = GpiFilter - type FPU = Unit - type Override = Unit - val fpu = () - val instrument = Instrument.Gpi - val site = Site.GN - val hasFilter = true -} - -case class GnirsSpectroscopyRow(grating: GnirsDisperser, filter: GnirsFilter) - extends InstrumentRow { - type Grating = GnirsDisperser - type Filter = GnirsFilter - type FPU = Unit - type Override = Unit - val fpu = () - val instrument = Instrument.Gnirs - val site = Site.GN - val hasFilter = true -} - -// Used for Instruments not fully defined -case class GenericSpectroscopyRow(i: Instrument, grating: String, filter: NonEmptyString) - extends InstrumentRow { - type Grating = String - type Filter = NonEmptyString - type FPU = Unit - type Override = Unit - val fpu = () - val instrument = i - val site = Site.GN - val hasFilter = true -} - -object InstrumentRow { - - val instrument: Getter[InstrumentRow, Instrument] = - Getter[InstrumentRow, Instrument](_.instrument) - - def grating: Getter[InstrumentRow, InstrumentRow#Grating] = - Getter[InstrumentRow, InstrumentRow#Grating](_.grating) - - def filter: Getter[InstrumentRow, InstrumentRow#Filter] = - Getter[InstrumentRow, InstrumentRow#Filter](_.filter) - -} - trait ModeCommonWavelengths { val λmin: ModeWavelength val λmax: ModeWavelength @@ -204,7 +79,7 @@ type SlitWidth = SlitWidth.Type case class SpectroscopyModeRow( id: Option[Int], // we number the modes for the UI - instrument: InstrumentRow, + instrument: InstrumentConfig, config: NonEmptyString, focalPlane: FocalPlane, capability: Option[SpectroscopyCapabilities], @@ -238,31 +113,35 @@ case class SpectroscopyModeRow( imageQuality: ImageQuality ): Option[SpectroscopyModeRow] = intervalCenter(wavelength).flatMap: cw => - val instrumentRow: Option[InstrumentRow] = + val instrumentConfig: Option[InstrumentConfig] = instrument.instrument match case Instrument.GmosNorth | Instrument.GmosSouth => instrument match - case i @ GmosNorthSpectroscopyRow(grating, fpu, _, None) => + case i @ InstrumentConfig.GmosNorthSpectroscopy(grating, fpu, _, None) => i.copy(modeOverrides = - GmosSpectroscopyOverrides( - cw, - GmosCcdMode.defaultGmosNorth(profiles, fpu, grating, imageQuality), - DefaultRoi - ).some + InstrumentOverrides + .GmosSpectroscopy( + cw, + GmosCcdMode.defaultGmosNorth(profiles, fpu, grating, imageQuality), + DefaultRoi + ) + .some ).some - case i @ GmosSouthSpectroscopyRow(grating, fpu, _, None) => + case i @ InstrumentConfig.GmosSouthSpectroscopy(grating, fpu, _, None) => i.copy(modeOverrides = - GmosSpectroscopyOverrides( - cw, - GmosCcdMode.defaultGmosSouth(profiles, fpu, grating, imageQuality), - DefaultRoi - ).some + InstrumentOverrides + .GmosSpectroscopy( + cw, + GmosCcdMode.defaultGmosSouth(profiles, fpu, grating, imageQuality), + DefaultRoi + ) + .some ).some - case i => + case i => i.some case _ => none - instrumentRow.map: i => + instrumentConfig.map: i => copy(instrument = i) } @@ -270,11 +149,11 @@ object SpectroscopyModeRow { given ValueConversion[NonNegBigDecimal, BigDecimal] = _.value - val instrumentRow: Lens[SpectroscopyModeRow, InstrumentRow] = + val instrumentConfig: Lens[SpectroscopyModeRow, InstrumentConfig] = GenLens[SpectroscopyModeRow](_.instrument) val instrument: Getter[SpectroscopyModeRow, Instrument] = - instrumentRow.andThen(InstrumentRow.instrument) + instrumentConfig.andThen(InstrumentConfig.instrument) val config: Lens[SpectroscopyModeRow, NonEmptyString] = GenLens[SpectroscopyModeRow](_.config) @@ -288,14 +167,14 @@ object SpectroscopyModeRow { val slitLength: Lens[SpectroscopyModeRow, SlitLength] = GenLens[SpectroscopyModeRow](_.slitLength) - def grating: Getter[SpectroscopyModeRow, InstrumentRow#Grating] = - instrumentRow.andThen(InstrumentRow.grating) + def grating: Getter[SpectroscopyModeRow, InstrumentConfig#Grating] = + instrumentConfig.andThen(InstrumentConfig.grating) def fpu: Lens[SpectroscopyModeRow, FocalPlane] = GenLens[SpectroscopyModeRow](_.focalPlane) - def filter: Getter[SpectroscopyModeRow, InstrumentRow#Filter] = - instrumentRow.andThen(InstrumentRow.filter) + def filter: Getter[SpectroscopyModeRow, InstrumentConfig#Filter] = + instrumentConfig.andThen(InstrumentConfig.filter) import lucuma.core.math.units.* @@ -303,19 +182,19 @@ object SpectroscopyModeRow { Getter(_.resolution) // decoders for instruments are used locally as they are not lawful - private given Decoder[GmosNorthSpectroscopyRow] = c => + private given Decoder[InstrumentConfig.GmosNorthSpectroscopy] = c => for { grating <- c.downField("grating").as[GmosNorthGrating] fpu <- c.downField("fpu").as[GmosNorthFpu] filter <- c.downField("filter").as[Option[GmosNorthFilter]] - } yield GmosNorthSpectroscopyRow(grating, fpu, filter, none) + } yield InstrumentConfig.GmosNorthSpectroscopy(grating, fpu, filter, none) - private given Decoder[GmosSouthSpectroscopyRow] = c => + private given Decoder[InstrumentConfig.GmosSouthSpectroscopy] = c => for { grating <- c.downField("grating").as[GmosSouthGrating] fpu <- c.downField("fpu").as[GmosSouthFpu] filter <- c.downField("filter").as[Option[GmosSouthFilter]] - } yield GmosSouthSpectroscopyRow(grating, fpu, filter, none) + } yield InstrumentConfig.GmosSouthSpectroscopy(grating, fpu, filter, none) given Decoder[SpectroscopyModeRow] = c => for { @@ -331,8 +210,8 @@ object SpectroscopyModeRow { resolution <- c.downField("resolution").as[PosInt] slitWidth <- c.downField("slitWidth").as[Angle] slitLength <- c.downField("slitLength").as[Angle] - gmosNorth <- c.downField("gmosNorth").as[Option[GmosNorthSpectroscopyRow]] - gmosSouth <- c.downField("gmosSouth").as[Option[GmosSouthSpectroscopyRow]] + gmosNorth <- c.downField("gmosNorth").as[Option[InstrumentConfig.GmosNorthSpectroscopy]] + gmosSouth <- c.downField("gmosSouth").as[Option[InstrumentConfig.GmosSouthSpectroscopy]] } yield gmosNorth .orElse(gmosSouth) .map { i => diff --git a/model/shared/src/main/scala/queries/schemas/itc/syntax.scala b/model/shared/src/main/scala/queries/schemas/itc/syntax.scala index d5d1e06501..9f5d8ad71d 100644 --- a/model/shared/src/main/scala/queries/schemas/itc/syntax.scala +++ b/model/shared/src/main/scala/queries/schemas/itc/syntax.scala @@ -8,9 +8,7 @@ import cats.syntax.all.* import explore.model.AsterismIds import explore.model.TargetList import explore.model.itc.ItcTarget -import explore.modes.GmosNorthSpectroscopyRow -import explore.modes.GmosSouthSpectroscopyRow -import explore.modes.InstrumentRow +import explore.modes.InstrumentConfig import explore.optics.all.* import lucuma.core.enums.GmosRoi import lucuma.core.math.RadialVelocity @@ -22,22 +20,22 @@ import lucuma.itc.client.TargetInput trait syntax: - extension (row: InstrumentRow) + extension (row: InstrumentConfig) def toItcClientMode: Option[InstrumentMode] = row match - case GmosNorthSpectroscopyRow(grating, fpu, filter, modeOverrides) => + case InstrumentConfig.GmosNorthSpectroscopy(grating, fpu, filter, modeOverrides) => val roi: Option[GmosRoi] = modeOverrides.map(_.roi) val ccd: Option[GmosCcdMode] = modeOverrides.map(_.ccdMode) InstrumentMode .GmosNorthSpectroscopy(grating, filter, GmosFpu.North(fpu.asRight), ccd, roi) .some - case GmosSouthSpectroscopyRow(grating, fpu, filter, modeOverrides) => + case InstrumentConfig.GmosSouthSpectroscopy(grating, fpu, filter, modeOverrides) => val roi: Option[GmosRoi] = modeOverrides.map(_.roi) val ccd: Option[GmosCcdMode] = modeOverrides.map(_.ccdMode) InstrumentMode .GmosSouthSpectroscopy(grating, filter, GmosFpu.South(fpu.asRight), ccd, roi) .some - case _ => None + case _ => None // We may consider adjusting this to consider small variations of RV identical for the // purpose of doing ITC calculations diff --git a/workers/src/main/scala/workers/itc/ITCGraphRequests.scala b/workers/src/main/scala/workers/itc/ITCGraphRequests.scala index dab71b928f..7cf235aacc 100644 --- a/workers/src/main/scala/workers/itc/ITCGraphRequests.scala +++ b/workers/src/main/scala/workers/itc/ITCGraphRequests.scala @@ -9,9 +9,7 @@ import cats.effect.* import cats.syntax.all.* import explore.model.boopickle.ItcPicklers.given import explore.model.itc.* -import explore.modes.GmosNorthSpectroscopyRow -import explore.modes.GmosSouthSpectroscopyRow -import explore.modes.InstrumentRow +import explore.modes.InstrumentConfig import lucuma.core.math.SignalToNoise import lucuma.core.math.Wavelength import lucuma.core.model.ConstraintSet @@ -37,13 +35,13 @@ object ITCGraphRequests: signalToNoiseAt: Wavelength, constraints: ConstraintSet, targets: NonEmptyList[ItcTarget], - mode: InstrumentRow, + mode: InstrumentConfig, cache: Cache[F], callback: ItcAsterismGraphResults => F[Unit] )(using Monoid[F[Unit]], ItcClient[F]): F[Unit] = val itcRowsParams = mode match // Only handle known modes - case m @ GmosNorthSpectroscopyRow(_, _, _, _) => + case m @ InstrumentConfig.GmosNorthSpectroscopy(_, _, _, _) => ItcGraphRequestParams( wavelength, signalToNoise, @@ -52,7 +50,7 @@ object ITCGraphRequests: targets, m ).some - case m @ GmosSouthSpectroscopyRow(_, _, _, _) => + case m @ InstrumentConfig.GmosSouthSpectroscopy(_, _, _, _) => ItcGraphRequestParams( wavelength, signalToNoise, @@ -61,7 +59,7 @@ object ITCGraphRequests: targets, m ).some - case _ => + case _ => none def doRequest(request: ItcGraphRequestParams): F[ItcAsterismGraphResults] = diff --git a/workers/src/main/scala/workers/itc/ITCRequests.scala b/workers/src/main/scala/workers/itc/ITCRequests.scala index f6bfb5a2c0..b073391912 100644 --- a/workers/src/main/scala/workers/itc/ITCRequests.scala +++ b/workers/src/main/scala/workers/itc/ITCRequests.scala @@ -12,9 +12,7 @@ import cats.syntax.all.* import explore.model.Constants import explore.model.boopickle.ItcPicklers.given import explore.model.itc.* -import explore.modes.GmosNorthSpectroscopyRow -import explore.modes.GmosSouthSpectroscopyRow -import explore.modes.InstrumentRow +import explore.modes.InstrumentConfig import explore.modes.SpectroscopyModeRow import lucuma.core.math.SignalToNoise import lucuma.core.math.Wavelength @@ -112,9 +110,9 @@ object ITCRequests: .map(x => (x.intervalCenter(wavelength), x.instrument)) // Only handle known modes .collect: - case (Some(wavelength), m: GmosNorthSpectroscopyRow) => + case (Some(wavelength), m @ InstrumentConfig.GmosNorthSpectroscopy(_, _, _, _)) => ItcRequestParams(wavelength, signalToNoise, signalToNoiseAt, constraints, asterism, m) - case (Some(wavelength), m: GmosSouthSpectroscopyRow) => + case (Some(wavelength), m @ InstrumentConfig.GmosSouthSpectroscopy(_, _, _, _)) => ItcRequestParams(wavelength, signalToNoise, signalToNoiseAt, constraints, asterism, m) parTraverseN(