Skip to content

Commit

Permalink
Merge pull request gemini-hlsw#49 from tpolecat/static-config
Browse files Browse the repository at this point in the history
initial static config
  • Loading branch information
tpolecat authored Jun 5, 2017
2 parents 01dd82d + 3338e0d commit 4eb064c
Show file tree
Hide file tree
Showing 23 changed files with 197 additions and 144 deletions.
1 change: 1 addition & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ lazy val commonSettings = Seq(
"-encoding", "UTF-8",
"-feature",
"-language:higherKinds",
"-language:existentials",
"-unchecked",
// "-Xfatal-warnings",
"-Xlint",
Expand Down
16 changes: 7 additions & 9 deletions modules/core/src/main/scala/gem/Observation.scala
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package gem

import gem.enum.Instrument

import scalaz._, Scalaz._

case class Observation[S](
case class Observation[S, D](
id: Observation.Id,
title: String,
instrument: Option[Instrument], // redundant? this is on the steps too
steps: List[S])
staticConfig: S,
steps: List[D])

object Observation {

Expand All @@ -32,10 +30,10 @@ object Observation {

}

implicit def ObservationTraverse[T]: Traverse[Observation[?]] =
new Traverse[Observation[?]] {
def traverseImpl[G[_]: Applicative, A, B](fa: Observation[A])(f: A => G[B]): G[Observation[B]] =
fa.steps.traverse(f).map(ss => fa.copy(steps = ss))
implicit val ObservationBitraverse: Bitraverse[Observation] =
new Bitraverse[Observation] {
def bitraverseImpl[G[_]: Applicative, A, B, C, D](fab: Observation[A,B])(f: A => G[C], g: B => G[D]): G[Observation[C,D]] =
(f(fab.staticConfig) |@| fab.steps.traverse(g))((c, d) => fab.copy(staticConfig = c, steps = d))
}

}
4 changes: 2 additions & 2 deletions modules/core/src/main/scala/gem/SmartGcal.scala
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package gem

import gem.config.InstrumentConfig
import gem.config.DynamicConfig

object SmartGcal {

sealed trait ExpansionError extends Product with Serializable

type ExpandedSteps = List[GcalStep[InstrumentConfig]]
type ExpandedSteps = List[GcalStep[DynamicConfig]]

final case class StepNotFound(loc: Location.Middle) extends ExpansionError
case object NotSmartGcal extends ExpansionError
Expand Down
14 changes: 7 additions & 7 deletions modules/core/src/main/scala/gem/Step.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import gem.enum.SmartGcalType
import scalaz.Functor

sealed abstract class Step[A] extends Product with Serializable {
def instrument: A
def dynamicConfig: A
}

final case class BiasStep [A](instrument: A) extends Step[A]
final case class DarkStep [A](instrument: A) extends Step[A]
final case class GcalStep [A](instrument: A, gcal: GcalConfig) extends Step[A]
final case class ScienceStep [A](instrument: A, telescope: TelescopeConfig) extends Step[A]
final case class SmartGcalStep[A](instrument: A, smartGcalType: SmartGcalType) extends Step[A]
final case class BiasStep [A](dynamicConfig: A) extends Step[A]
final case class DarkStep [A](dynamicConfig: A) extends Step[A]
final case class GcalStep [A](dynamicConfig: A, gcal: GcalConfig) extends Step[A]
final case class ScienceStep [A](dynamicConfig: A, telescope: TelescopeConfig) extends Step[A]
final case class SmartGcalStep[A](dynamicConfig: A, smartGcalType: SmartGcalType) extends Step[A]

object Step {
implicit val FunctorStep: Functor[Step] = new Functor[Step] {
Expand All @@ -26,4 +26,4 @@ object Step {
case SmartGcalStep(a, s) => SmartGcalStep(f(a), s)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,22 @@ import java.time.Duration

sealed trait SmartGcalKey

sealed abstract class InstrumentConfig extends Product with Serializable {
sealed abstract class DynamicConfig extends Product with Serializable {

type I <: Instrument with Singleton
def instrument: I

def smartGcalKey: Option[SmartGcalKey] =
this match {
case f2: F2Config => Some(f2.key)
case GenericConfig(_) => None
case _ => None
}

def instrument: Instrument = {
import gem.enum.Instrument._

this match {
case _: F2Config => Flamingos2
case GenericConfig(i) => i
}
}
}
object DynamicConfig {
type Aux[I0] = DynamicConfig { type I = I0 }
}


final case class F2SmartGcalKey(
disperser: F2Disperser,
Expand All @@ -39,11 +39,11 @@ final case class F2Config(
mosPreimaging: Boolean,
readMode: F2ReadMode,
windowCover: F2WindowCover
) extends InstrumentConfig {
) extends DynamicConfig {

type I = Instrument.Flamingos2.type
def instrument = valueOf[I]

def key: F2SmartGcalKey =
F2SmartGcalKey(disperser, filter, fpu)
}

// TODO: temporary, until all instruments are supported
case class GenericConfig(i: Instrument) extends InstrumentConfig
32 changes: 32 additions & 0 deletions modules/core/src/main/scala/gem/config/StaticConfig.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package gem
package config

import gem.enum.Instrument

sealed abstract class StaticConfig {
type I <: Instrument with Singleton
def instrument: I
}

object StaticConfig {
type Aux[I0] = StaticConfig { type I = I0 }
sealed abstract class Impl[I0 <: Instrument with Singleton](val instrument: I0) extends StaticConfig {
type I = I0
}
}

final case class PhoenixStaticConfig() extends StaticConfig.Impl(Instrument.Phoenix)
final case class MichelleStaticConfig() extends StaticConfig.Impl(Instrument.Michelle)
final case class GnirsStaticConfig() extends StaticConfig.Impl(Instrument.Gnirs)
final case class NiriStaticConfig() extends StaticConfig.Impl(Instrument.Niri)
final case class TrecsStaticConfig() extends StaticConfig.Impl(Instrument.Trecs)
final case class NiciStaticConfig() extends StaticConfig.Impl(Instrument.Nici)
final case class NifsStaticConfig() extends StaticConfig.Impl(Instrument.Nifs)
final case class GpiStaticConfig() extends StaticConfig.Impl(Instrument.Gpi)
final case class GsaoiStaticConfig() extends StaticConfig.Impl(Instrument.Gsaoi)
final case class GmosSStaticConfig() extends StaticConfig.Impl(Instrument.GmosS)
final case class AcqCamStaticConfig() extends StaticConfig.Impl(Instrument.AcqCam)
final case class GmosNStaticConfig() extends StaticConfig.Impl(Instrument.GmosN)
final case class BhrosStaticConfig() extends StaticConfig.Impl(Instrument.Bhros)
final case class VisitorStaticConfig() extends StaticConfig.Impl(Instrument.Visitor)
final case class Flamingos2StaticConfig() extends StaticConfig.Impl(Instrument.Flamingos2)
11 changes: 0 additions & 11 deletions modules/core/src/main/scala/gem/enum/package.scala
Original file line number Diff line number Diff line change
@@ -1,21 +1,10 @@
package gem

import gem.config._

// The members of this package are generated from database tables, which are the source of truth.
// See project/gen2.scala for details. Associations with other model types, as needed, are provided
// here as implicit classes wrapping the generated companion objects.
package object enum {

/** Add mapping from InstrumentConfig to Instrument. */
implicit class InstrumentCompanionOps(companion: Instrument.type) {
def forConfig(c: InstrumentConfig): Instrument =
c match {
case F2Config(_, _, _, _, _, _, _, _) => Instrument.Flamingos2
case GenericConfig(i) => i
}
}

/** Add mapping from Step to StepType. */
implicit class StepTypeCompanionOps(companion: StepType.type) {
def forStep(s: Step[_]): StepType =
Expand Down
27 changes: 14 additions & 13 deletions modules/db/src/main/scala/gem/dao/ObservationDao.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gem
package dao

import gem.config.StaticConfig
import gem.enum.Instrument

import doobie.imports._
Expand All @@ -9,26 +10,26 @@ import scalaz._, Scalaz._

object ObservationDao {

def insert(o: Observation[_]): ConnectionIO[Int] =
def insert(o: Observation[StaticConfig, _]): ConnectionIO[Int] =
Statements.insert(o).run

/** Select all the observation ids associated with the given program. */
def selectIds(pid: Program.Id): ConnectionIO[List[Observation.Id]] =
Statements.selectIds(pid).list

def selectFlat(id: Observation.Id): ConnectionIO[Observation[Nothing]] =
def selectFlat(id: Observation.Id): ConnectionIO[Observation[StaticConfig, Nothing]] =
Statements.selectFlat(id).unique

def select(id: Observation.Id): ConnectionIO[Observation[Step[_]]] =
def select(id: Observation.Id): ConnectionIO[Observation[StaticConfig, Step[_]]] =
for {
on <- selectFlat(id)
ss <- StepDao.selectAllEmpty(id)
} yield on.copy(steps = ss.values)

def selectAllFlat(pid: Program.Id): ConnectionIO[List[Observation[Nothing]]] =
def selectAllFlat(pid: Program.Id): ConnectionIO[List[Observation[StaticConfig, Nothing]]] =
Statements.selectAllFlat(pid).list

def selectAll(pid: Program.Id): ConnectionIO[List[Observation[Step[_]]]] =
def selectAll(pid: Program.Id): ConnectionIO[List[Observation[StaticConfig, Step[_]]]] =
for {
ids <- selectIds(pid)
oss <- ids.traverseU(select)
Expand All @@ -44,7 +45,7 @@ object ObservationDao {
Distinct.integer("id_index").xmap(ObservationIndex(_), _.toInt)
}

def insert(o: Observation[_]): Update0 =
def insert(o: Observation[StaticConfig, _]): Update0 =
sql"""
INSERT INTO observation (observation_id,
program_id,
Expand All @@ -55,7 +56,7 @@ object ObservationDao {
${o.id.pid},
${ObservationIndex(o.id.index)},
${o.title},
${o.instrument})
${o.staticConfig.instrument : Instrument})
""".update

def selectIds(pid: Program.Id): Query0[Observation.Id] =
Expand All @@ -65,25 +66,25 @@ object ObservationDao {
WHERE program_id = $pid
""".query[Observation.Id]

def selectFlat(id: Observation.Id): Query0[Observation[Nothing]] =
def selectFlat(id: Observation.Id): Query0[Observation[StaticConfig, Nothing]] =
sql"""
SELECT title, instrument
FROM observation
WHERE observation_id = ${id}
""".query[(String, Option[Instrument])]
""".query[(String, Instrument)]
.map { case (t, i) =>
Observation(id, t, i, Nil)
Observation(id, t, StaticConfigDao.forInstrument(i), Nil)
}

def selectAllFlat(pid: Program.Id): Query0[Observation[Nothing]] =
def selectAllFlat(pid: Program.Id): Query0[Observation[StaticConfig, Nothing]] =
sql"""
SELECT observation_index, title, instrument
FROM observation
WHERE program_id = ${pid}
ORDER BY observation_index
""".query[(Short, String, Option[Instrument])]
""".query[(Short, String, Instrument)]
.map { case (n, t, i) =>
Observation(Observation.Id(pid, n.toInt), t, i, Nil)
Observation(Observation.Id(pid, n.toInt), t, StaticConfigDao.forInstrument(i), Nil)
}

}
Expand Down
4 changes: 3 additions & 1 deletion modules/db/src/main/scala/gem/dao/ProgramDao.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package gem
package dao

import gem.config.StaticConfig

import edu.gemini.spModel.core._
import edu.gemini.spModel.core.ProgramId._

Expand Down Expand Up @@ -41,7 +43,7 @@ object ProgramDao {
Statements.selectFlat(pid).option

/** Select a program by id, with full Observation information. */
def selectFull(pid: Program.Id): ConnectionIO[Option[Program[Observation[Step[_]]]]] =
def selectFull(pid: Program.Id): ConnectionIO[Option[Program[Observation[StaticConfig, Step[_]]]]] =
for {
opn <- selectFlat(pid)
os <- ObservationDao.selectAll(pid)
Expand Down
6 changes: 3 additions & 3 deletions modules/db/src/main/scala/gem/dao/SmartGcalDao.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ object SmartGcalDao {

type ExpansionResult[A] = EitherConnectionIO[ExpansionError, A]

private def lookup(step: MaybeConnectionIO[Step[InstrumentConfig]], loc: Location.Middle): ExpansionResult[ExpandedSteps] = {
private def lookup(step: MaybeConnectionIO[Step[DynamicConfig]], loc: Location.Middle): ExpansionResult[ExpandedSteps] = {
// Information we need to extract from a smart gcal step in order to expand
// it into manual gcal steps. The key is used to look up the gcal config
// from the instrument's smart table (e.g., smart_f2). The type is used to
// extract the matching steps (arc vs. flat, or night vs. day baseline).
// The instrument config is needed to create the corresponding gcal steps.
type SmartContext = (SmartGcalKey, SmartGcalType, InstrumentConfig)
type SmartContext = (SmartGcalKey, SmartGcalType, DynamicConfig)

// Get the key, type, and instrument config from the step. We'll need this
// information to lookup the corresponding GcalConfig.
Expand Down Expand Up @@ -97,7 +97,7 @@ object SmartGcalDao {
// Find the previous and next location for the smart gcal step that we are
// replacing. This is needed to generate locations for the steps that will
// be inserted.
def bounds(steps: Location.Middle ==>> Step[InstrumentConfig]): (Location, Location) =
def bounds(steps: Location.Middle ==>> Step[DynamicConfig]): (Location, Location) =
steps.split(loc) match {
case (prev, next) => (prev.findMax.map(_._1).widen[Location] | Location.beginning,
next.findMin.map(_._1).widen[Location] | Location.end)
Expand Down
39 changes: 39 additions & 0 deletions modules/db/src/main/scala/gem/dao/StaticConfigDao.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package gem
package dao

// import doobie.imports._

import gem.enum.Instrument
import gem.config._


object StaticConfigDao {

// this is just a placeholder … right now the obs table just contains an instrument tag which we
// use to construct an empty static config

def forInstrument(i: Instrument): StaticConfig.Aux[i.type] =
(i match {
case Instrument.Phoenix => PhoenixStaticConfig()
case Instrument.Michelle => MichelleStaticConfig()
case Instrument.Gnirs => GnirsStaticConfig()
case Instrument.Niri => NiriStaticConfig()
case Instrument.Trecs => TrecsStaticConfig()
case Instrument.Nici => NiciStaticConfig()
case Instrument.Nifs => NifsStaticConfig()
case Instrument.Gpi => GpiStaticConfig()
case Instrument.Gsaoi => GsaoiStaticConfig()
case Instrument.GmosS => GmosSStaticConfig()
case Instrument.AcqCam => AcqCamStaticConfig()
case Instrument.GmosN => GmosNStaticConfig()
case Instrument.Bhros => BhrosStaticConfig()
case Instrument.Visitor => VisitorStaticConfig()
case Instrument.Flamingos2 => Flamingos2StaticConfig()
}).asInstanceOf[StaticConfig.Aux[i.type]] // Scala isn't smart enough to know this


object Statements {
// todo
}

}
Loading

0 comments on commit 4eb064c

Please sign in to comment.