Skip to content

Commit

Permalink
require groups of regional timepoints (for trace merger) to be named; c…
Browse files Browse the repository at this point in the history
  • Loading branch information
vreuter committed Dec 2, 2024
1 parent 194a852 commit 5868529
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 72 deletions.
1 change: 1 addition & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ lazy val root = (project in file("."))
gerlibs ++
logging ++
Seq( // only for tests
catsLaws,
gerlibTesting,
ironScalacheck,
scalaCsv,
Expand Down
8 changes: 7 additions & 1 deletion project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ import sbt._

/** Dependencies for the project */
object Dependencies {
/** Get a typelevel cats dependency specification. */
object Cats {
def getModuleId(name: String) = "org.typelevel" %% s"cats-$name" % "2.12.0"
}

/** gerlichlab dependency declaration helper */
object Gerlib {
def getModuleId(name: String) = groupId %% artifact(name) % version
Expand Down Expand Up @@ -37,7 +42,7 @@ object Dependencies {
lazy val scalatestVersion = "3.2.18"

/* core libraries */
lazy val catsCore = "org.typelevel" %% "cats-core" % "2.12.0"
lazy val catsCore = Cats.getModuleId("core")
lazy val gerlibs = Seq(
"graph",
"io",
Expand Down Expand Up @@ -69,6 +74,7 @@ object Dependencies {
lazy val uPickle = HaoyiJson.getModuleId("upickle")

/* testing-related dependencies */
lazy val catsLaws = Cats.getModuleId("laws")
lazy val gerlibTesting = Gerlib.getModuleId("testing")
lazy val scalacheck = "org.scalacheck" %% "scalacheck" % "1.18.0"
lazy val scalactic = "org.scalactic" %% "scalactic" % scalatestVersion
Expand Down
10 changes: 6 additions & 4 deletions src/main/scala/ImagingRoundsConfiguration.scala
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,7 @@ object ImagingRoundsConfiguration extends LazyLogging:

/** How to redefine trace IDs and filter ROIs on the basis of proximity to one another */
final case class TraceIdDefinitionRule(
name: String,
mergeGroup: ProximityGroup[EuclideanDistance.Threshold, ImagingTimepoint],
requirement: RoiPartnersRequirementType,
)
Expand Down Expand Up @@ -567,16 +568,17 @@ object ImagingRoundsConfiguration extends LazyLogging:
.flatMap{ (strictness, maybeThreshold, maybeRequirementType) =>
kvPairs.get(groupsKey)
.toRight(s"Missing key for groups: $groupsKey")
.flatMap(_.arrOpt.toRight(s"Can't parse groups (from '$groupsKey') as array-like"))
.flatMap(_.toList.toNel.toRight(s"Groups (from '$groupsKey') is empty"))
.flatMap(_.objOpt.toRight(s"Can't parse groups (from '$groupsKey') as map-like"))
.flatMap(_.toList.toNel.toRight(s"Data for groups (from '$groupsKey') is empty"))
.leftMap(NonEmptyList.one)
.flatMap(_.nonEmptyTraverse(v => parseGroupMembersSimple(v).leftMap(NonEmptyList.one)))
.flatMap(_.nonEmptyTraverse{ (k, v) => parseGroupMembersSimple(v).bimap(NonEmptyList.one, k -> _) })
.flatMap(groups => (maybeThreshold, maybeRequirementType) match {
case (None, None) => NonEmptyList.one("Missing threshold and requirement type for ROI merge").asLeft
case (Some(threshold), None) => NonEmptyList.one("Missing requirement type for ROI merge").asLeft
case (None, Some(reqType)) => NonEmptyList.one("Missing threshold for ROI merge").asLeft
case (Some(threshold), Some(reqType)) =>
groups.map{ g => TraceIdDefinitionRule(
groups.map{ (k, g) => TraceIdDefinitionRule(
k,
ProximityGroup(threshold, g),
reqType,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"discardRoisNotInGroupsOfInterest": true,
"distanceThreshold": 2000,
"requirementType": "Conjunctive",
"groups": [[0, 7], [8, 9]]
"groups": {"A": [0, 7], "B": [8, 9]}
},
"imagingRounds": [
{"time": 0, "name": "pre_image", "isBlank": true},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"discardRoisNotInGroupsOfInterest": true,
"distanceThreshold": 2000,
"requirementType": "Conjunctive",
"groups": [[5, 7], [8, 9]]
"groups": {"A": [5, 7], "B": [8, 9]}
},
"imagingRounds": [
{"time": 0, "name": "pre_image", "isBlank": true},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"discardRoisNotInGroupsOfInterest": true,
"distanceThreshold": 2000,
"requirementType": "Conjunctive",
"groups": [[6, 7], [8, 9]]
"groups": {"A": [6, 7], "B": [8, 9]}
},
"imagingRounds": [
{"time": 0, "name": "pre_image", "isBlank": true},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"discardRoisNotInGroupsOfInterest": true,
"distanceThreshold": 2000,
"requirementType": "Conjunctive",
"groups": [[6, 7], [8, 9]]
"groups": {"A": [6, 7], "B": [8, 9]}
},
"imagingRounds": [
{"time": 0, "name": "pre_image", "isBlank": true},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"discardRoisNotInGroupsOfInterest": true,
"distanceThreshold": 2000,
"requirementType": "Conjunctive",
"groups": [[6, 7], [8, 9]]
"groups": {"A": [6, 7], "B": [8, 9]}
},
"imagingRounds": [
{"time": 0, "name": "pre_image", "isBlank": true},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,14 +215,16 @@ class TestImagingRoundsConfigurationExamplesParsability extends AnyFunSuite with
val expDistance =
import io.github.iltotore.iron.autoRefine
EuclideanDistance.Threshold(NonnegativeReal(2000))
NonEmptyList.of(Set(6, 7), Set(8, 9))
.map(_.map(ImagingTimepoint.unsafe).pipe(AtLeast2.unsafe))
.map{ g =>
TraceIdDefinitionRule(
ProximityGroup(expDistance, g),
RoiPartnersRequirementType.Conjunctive,
)
}
NonEmptyList.of(
"A" -> MergeBag.unsafe(Set(6, 7)),
"B" -> MergeBag.unsafe(Set(8, 9)),
).map{ (k, g) =>
TraceIdDefinitionRule(
k,
ProximityGroup(expDistance, g),
RoiPartnersRequirementType.Conjunctive,
)
}
Table(
("configFileName", "expectedMergeRules"),
("good_example__legitimate_tracing_merge_groups.json", expRules),
Expand Down Expand Up @@ -287,6 +289,9 @@ class TestImagingRoundsConfigurationExamplesParsability extends AnyFunSuite with
}
}

object MergeBag:
def unsafe = (_: Set[Int]).map(ImagingTimepoint.unsafe).pipe(AtLeast2.unsafe)

private def checkParseFailure(configFile: os.Path, expectedMessage: String, check: (String, String) => Boolean = cats.Eq[String].eqv) =
ImagingRoundsConfiguration.fromJsonFile(configFile) match {
case Left(messages) =>
Expand Down
Loading

0 comments on commit 5868529

Please sign in to comment.