Tags
Labelling trial objects and recovering them later by tag.
See Tagging and recovery for the narrative introduction.
ModelManager.appendTags! — Method
appendTags!(df, T, id_column; include_auto=false, inherit=true)Pivot the tags of the objects listed in df[!, id_column] into columns and append them, returning df.
Column names are prefixed with tag: so they can never collide with the folder, parameter, or ID columns already produced by simulationsTable. A key carrying several values on one object is rendered as its values joined by |. Objects with no value for a key get missing.
With inherit=true (the default) a tag on a parent object contributes to its constituents' columns, matching findSimulationIDs — otherwise a simulation recovered by a sampling-level tag would show no column for it. T may also be Calibration, which has no parent, so inherit makes no difference there.
Used by simulationsTable(...; tags = true); call it directly only to pivot tags onto a table you have built yourself.
Example
df = simulationsTable(ids)
appendTags!(df, Simulation, :SimID) # adds tag:<key> columns
appendTags!(df, Simulation, :SimID; inherit = false) # only tags on the simulationsModelManager.findMonads — Method
findMonads(; tags=nothing, any_of=nothing, inherit=true, limit=MAX_MATERIALIZED_TRIALS) -> Vector{Monad}Return the Monad objects matching the given tag filters.
Behaves like findSimulationIDs one level up the hierarchy: with inherit=true a tag on a Sampling or Trial matches its constituent monads. Tags placed on individual simulations never propagate upward.
Example
findMonads(tags = ("project" => "immune-escape",))ModelManager.findSimulationIDs — Method
findSimulationIDs(; tags=nothing, any_of=nothing, status=nothing, inherit=true) -> Vector{Int}Return the sorted IDs of simulations matching the given tag filters.
tags: a collection of filters that must all match (AND). Each filter is akey => valuepair for an exact match, or a bare key meaning "has this key with any value".any_of: a collection of filters of which at least one must match (OR). Combined withtagsby intersection when both are given.status: restrict to simulations with this status code, e.g."Completed".inherit: whentrue(the default), a tag on aMonad,Sampling, orTrialalso matches its constituent simulations. Set tofalseto match only tags placed directly on simulations.
Results are always intersected with the simulations that actually exist, so tag rows orphaned by an interrupted deletion never surface.
This is the ID-returning form; use it for large result sets and feed it straight into simulationsTable. findSimulations returns constructed Simulation objects instead.
Example
ids = findSimulationIDs(tags = ("project" => "immune-escape", "arm" => "control"),
status = "Completed")
simulationsTable(ids)ModelManager.findSimulations — Method
findSimulations(; limit=MAX_MATERIALIZED_TRIALS, kwargs...) -> Vector{Simulation}Return the Simulation objects matching the given tag filters.
Accepts the same keyword arguments as findSimulationIDs, plus limit. Objects are built in a single query, but a very large result set is still expensive to hold — so this throws above limit rather than materializing it. Use findSimulationIDs when you only need IDs.
Example
sims = findSimulations(tags = ("figure" => "3b",))ModelManager.findTrials — Method
findTrials(T; tags=nothing, any_of=nothing, inherit=true, status=nothing, limit=MAX_MATERIALIZED_TRIALS)Return the objects of type T matching the given tag filters.
T may be Simulation, Monad, Sampling, Trial, or Calibration. For Simulation and Monad this dispatches to findSimulations and findMonads, which support downward inheritance. For the other three only tags placed directly on those objects are considered: there is nothing above a Sampling or Trial to inherit from, and a Calibration sits outside the containment hierarchy entirely.
Example
findTrials(Simulation; tags = ("project" => "immune-escape",), status = "Completed")
findTrials(Sampling; tags = ("purpose" => "sensitivity",))
findTrials(Calibration; tags = ("mm:method" => "ABCSMC",))See also tag!.
ModelManager.gitState — Method
gitState(dir) -> NamedTupleReturn (commit, branch, dirty) for the repository containing dir, or empty strings when dir is not inside a git repository.
dirty is "true" when the working tree has uncommitted changes and "" otherwise — a commit hash alone is a false promise of reproducibility if the tree was modified.
Example
gitState(pwd())
# (commit = "8e196deb...", branch = "main", dirty = "")ModelManager.hasTag — Method
hasTag(target, tag) -> BoolReturn true if target carries tag directly.
tag may be a key => value pair (exact match) or a bare key (any value).
Example
hasTag(sim, "arm" => "high_dose")
hasTag(sim, "arm")ModelManager.orphanedTagCounts — Method
orphanedTagCounts() -> Dict{String,Int}Return, per tagged class, the number of tag rows pointing at objects that no longer exist. Used by databaseDiagnostics.
A healthy database returns zeros for every class. Non-zero counts mean tag rows outlived their objects — usually an interrupted deletion.
Example
orphanedTagCounts()
# Dict("simulation" => 0, "monad" => 0, "sampling" => 0, "trial" => 0, "calibration" => 0)ModelManager.printTagsTable — Method
printTagsTable(args...; sink=println, kwargs...)Print the table produced by tagsTable.
Example
printTagsTable(include_auto = false)ModelManager.recommendedTagKeys — Method
recommendedTagKeys() -> NTuple{6,String}Return the small vocabulary of tag keys ModelManager suggests as a starting point: project, purpose, figure, arm, verdict, note.
These are recommendations only — any key matching the rules in tag! is accepted. A shared vocabulary mostly helps so that scripts written months apart remain mutually searchable.
Example
recommendedTagKeys()
# ("project", "purpose", "figure", "arm", "verdict", "note")ModelManager.setTagHints! — Method
setTagHints!(on::Bool)Enable or disable the one-time-per-session hint shown when trials are created without any user tags. Returns the new setting.
ModelManager also honors the MODELMANAGER_TAG_HINTS environment variable, so the hints can be silenced without changing code — the better option in a job script.
Example
setTagHints!(false)MODELMANAGER_TAG_HINTS=0 julia scripts/GenerateData.jlModelManager.tag! — Method
tag!(target, tags...)Attach one or more tags to an object (or to many at once) and return target.
Each tag is a Pair such as "arm" => "high_dose", or a bare key such as "baseline" which is stored with an empty value. Keys are lowercased and must match [a-z0-9][a-z0-9_.-]*; values are stored as given (with surrounding whitespace trimmed). Re-applying an existing tag is a no-op, and a single key may carry several values.
A tag placed on a Monad, Sampling, or Trial is stored once, on that object — it is not copied onto its constituent simulations. findTrials expands the hierarchy at query time instead, so the answer stays correct when replicates are added later.
Accepted targets
tag!(simulation, "arm" => "high_dose") # any AbstractTrial
tag!(Simulation, 42, "verdict" => "suspect") # type + id
tag!(Simulation, [1, 2, 3], "project" => "x") # type + ids
tag!([sim_a, sim_b], "project" => "x") # vector of objects
tag!([1, 2, 3], "project" => "x") # bare ids are interpreted as simulations
tag!(df.SimID, "project" => "x") # a column straight out of `simulationsTable`
tag!(output, "project" => "x") # an MMOutput from `run`
tag!(calibration, "project" => "x") # a Calibration from runABCA Calibration is tagged the same way, but it is a run rather than a container of simulations, so its tags do not reach the monads it evaluated. Use the mm:calibration tag that every generation's sampling already carries for that: findMonads(tags = ("mm:calibration" => string(calibration.id),)). The trade is durability — the calibrations database row outlives any monad cascade, so a tag placed there survives even when every simulation of the run is deleted.
Returns
The target, so calls can be chained or piped.
Example
sampling = createTrial(inputs, variations)
tag!(sampling, "project" => "immune-escape", "purpose" => "figure", "figure" => "3b")
# Retroactive curation: label what you found interesting after looking at results.
tag!(findSimulationIDs(tags = ("project" => "immune-escape",)), "verdict" => "good")See also untag!, tags, findTrials.
ModelManager.tagKeys — Method
tagKeys(; include_auto::Bool=false) -> Vector{String}Return the sorted list of tag keys currently in use.
This is the cheap way to discover the vocabulary you have actually been using and to spot typos ("cohort" alongside "chohort"). ModelManager's own mm: keys are omitted by default.
Example
tagKeys()
# ["arm", "figure", "project", "purpose"]ModelManager.tagValues — Method
tagValues(key) -> Vector{String}Return the sorted list of distinct values stored under key.
Example
tagValues("arm")
# ["anti_pd1", "control"]ModelManager.tags — Method
tags(target; include_auto::Bool=true) -> Dict{String,Vector{String}}Return the tags attached directly to an object, as a mapping from key to the sorted list of values stored under that key.
target may be any trial object or a Calibration, or a type and ID.
Only tags placed on this exact object are returned; tags inherited from a parent Sampling or Trial are not, since inheritance is resolved at query time by findTrials. Pass include_auto=false to omit the mm: keys ModelManager records itself.
Example
tags(sim)
# Dict("mm:created" => ["2026-07-29T14:02:11"], "arm" => ["high_dose"])
tags(sim; include_auto=false)
# Dict("arm" => ["high_dose"])ModelManager.tagsTable — Method
tagsTable(; include_auto::Bool=true) -> DataFrame
tagsTable(target; include_auto::Bool=true) -> DataFrameReturn the tag store as a long-format DataFrame with columns Class, ID, Key, Value, and DateTime.
With no argument the whole store is returned; with a trial object, a Calibration, or a type and ID, only that object's rows are. Pass include_auto=false to omit mm: keys.
Example
tagsTable() # everything
tagsTable(sampling) # one object
tagsTable(include_auto = false) # only what a human assertedModelManager.untag! — Method
untag!(target, tags...)Remove tags from an object (or from many at once) and return target.
Each argument may be a full key => value pair, which removes exactly that pair, or a bare key, which removes every value stored under that key. Removing a tag that is not present is a no-op.
Calling untag!(target) with no tags removes all user tags from the target. ModelManager's own mm: tags are never removed by untag! — delete the object itself if you need them gone.
Example
untag!(sim, "verdict" => "suspect") # drop one specific pair
untag!(sim, "verdict") # drop every verdict value
untag!(sim) # drop all user tags, keep mm: provenanceSee also tag!.