Category Question Structure¶
Overview¶
This document provides detailed documentation of the question structure for each annotation category in SyRF. Each category has unique rules about how questions are organized, what system questions exist, and where custom questions can be placed.
Related Documentation¶
- Annotation Questions Business Logic - Core business rules
- Formal Specification - Precise rules, referential integrity, cross-language validation
- Architecture Analysis - Where logic should live
- Question Hierarchy Diagrams - Visual representations
Note: For formal, precise rule definitions (including referential integrity for lookups), see the Formal Rule Specification section.
Category Visibility Context¶
CRITICAL: The availability of categories depends on the Stage.Extraction boolean setting:
stage.extraction |
Available Categories | Use Case |
|---|---|---|
false |
Study only (custom questions only) | Simple screening without structured data extraction |
true |
All categories (Study + unit-based categories) | Full data extraction with structured outcome capture |
Unit-Based Categories (require stage.extraction = true):
- Disease Model Induction - Define disease models with control/non-control indicator
- Treatment - Define treatments with control/non-control indicator
- Outcome Assessment - Define outcome measures with statistical metadata (these system questions feed into OutcomeData)
- Cohort - Group disease models, treatments, and outcomes via lookup questions
- Experiment - Group cohorts into experiments via lookup questions
OutcomeData Connection: When stage.extraction = true, the system questions in Outcome Assessment (Average Type, Error Type, Units, Greater Is Worse) and Cohort (Number of Animals) populate the OutcomeData entity. OutcomeData can only be entered once Experiments, Cohorts, and Outcomes are created and linked via the lookup questions. See OutcomeData for full details.
Implementation: See Stage Data Extraction Settings in the main README for code-level details of how Stage.Extraction controls question visibility.
Category Quick Reference¶
| Category | Label Question | Control Question | First-Level Custom Parent¹ | Has Lookups |
|---|---|---|---|---|
| Study | None | None | Root (null) | No |
| Disease Model Induction | Yes | Yes (Model Control) | Control Question | No |
| Treatment | Yes | Yes (Treatment Control) | Control Question | No |
| Outcome Assessment | Yes | No | Label Question | Yes (PDF) |
| Cohort | Yes | No | Label Question | Yes (3 lookups) |
| Experiment | Yes | No | Label Question | Yes (Cohorts) |
| Hidden | N/A | N/A | N/A | N/A |
¹ Note: This column shows where first-level custom questions must parent. Nested custom questions (created via "Add Related" on an existing custom question) parent to their custom question parent instead, forming arbitrarily deep trees within each category.
Study Category¶
Overview¶
The Study category is the simplest - it has no unit concept, no label question, and no control question. Custom questions are created at the root level.
Structure¶
Study Category
══════════════
[Root Level - No System Questions]
┌────────────────────────────────────────┐
│ Custom Question 1 │
│ ────────────────── │
│ root: true │
│ target: null │
│ system: false │
│ │
│ ┌────────────────────────────────────┐│
│ │ Child Question 1.1 ││
│ │ target.parentId: CustomQ1.Id ││
│ └────────────────────────────────────┘│
└────────────────────────────────────────┘
┌────────────────────────────────────────┐
│ Custom Question 2 │
│ ────────────────── │
│ root: true │
│ target: null │
└────────────────────────────────────────┘
Rules¶
| Rule | Enforcement |
|---|---|
| Custom questions at root level | Frontend only |
| Child questions parent to custom questions | Backend + Frontend |
| No system questions in this category | Definition |
Code Reference¶
// create-question.component.ts - Study case
: null; // Study category - root question, no parent required
Disease Model Induction Category¶
Overview¶
Disease Model Induction uses a unit-based structure with a Control Question. First-level custom questions must be children of the Control Question and specify whether they apply to control procedures (true) or non-control procedures (false). Nested custom questions can parent to other custom questions within the same category.
System Questions¶
| Question | GUID | Type | Purpose |
|---|---|---|---|
| Disease Model Label | bdb6e257-5a08-42ef-aad0-829668679b0e |
Label (textbox) | Creates named disease model instances |
| Model Control | b18aa936-a4c6-446b-ac98-88ac38930878 |
Boolean (checkbox) | Indicates if this is a control procedure |
Structure¶
Disease Model Induction Category
════════════════════════════════
┌─────────────────────────────────────────────────────────────┐
│ Disease Model Label [SYSTEM] │
│ ───────────────────────────── │
│ id: bdb6e257-5a08-42ef-aad0-829668679b0e │
│ root: true │
│ labelQuestion: true │
│ controlType: textbox │
│ │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Model Control [SYSTEM] ││
│ │ ───────────────────── ││
│ │ id: b18aa936-a4c6-446b-ac98-88ac38930878 ││
│ │ target.parentId: diseaseModelInductionLabel ││
│ │ questionType: boolean ││
│ │ controlType: checkbox ││
│ │ ││
│ │ ┌───────────────────────────────────────────────────┐ ││
│ │ │ Custom Question (Control=true) │ ││
│ │ │ ───────────────────────────── │ ││
│ │ │ target.parentId: modelControl GUID │ ││
│ │ │ conditionalParentAnswers: │ ││
│ │ │ conditionType: Boolean (0) │ ││
│ │ │ targetParentBoolean: true │ ││
│ │ │ │ ││
│ │ │ Shows when: Model Control checkbox = checked │ ││
│ │ └───────────────────────────────────────────────────┘ ││
│ │ ││
│ │ ┌───────────────────────────────────────────────────┐ ││
│ │ │ Custom Question (Control=false) │ ││
│ │ │ ───────────────────────────── │ ││
│ │ │ target.parentId: modelControl GUID │ ││
│ │ │ conditionalParentAnswers: │ ││
│ │ │ conditionType: Boolean (0) │ ││
│ │ │ targetParentBoolean: false │ ││
│ │ │ │ ││
│ │ │ Shows when: Model Control checkbox = unchecked │ ││
│ │ └───────────────────────────────────────────────────┘ ││
│ │ ││
│ │ ┌───────────────────────────────────────────────────┐ ││
│ │ │ Custom Question (Control=null/both) │ ││
│ │ │ ───────────────────────────── │ ││
│ │ │ target.parentId: modelControl GUID │ ││
│ │ │ conditionalParentAnswers: null │ ││
│ │ │ │ ││
│ │ │ Shows always (regardless of control value) │ ││
│ │ └───────────────────────────────────────────────────┘ ││
│ └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘
Rules¶
| Rule | Enforcement | Details |
|---|---|---|
| First-level custom questions must parent to Model Control | Frontend only | target.parentId = b18aa936-a4c6-446b-ac98-88ac38930878 |
| Nested custom questions parent to custom question | Frontend only | target.parentId = {customQuestionId} |
| Control parameter must be specified (first-level only) | Frontend only | conditionalParentAnswers set to true, false, or null |
| Cannot place custom questions under Label | Frontend only | Not allowed by UI |
Code Reference¶
// create-question.component.ts:389-393
: category === categories.modelInduction
? createTarget(
systemAnnotationQuestionGuids.modelControl,
this.data.control // Boolean: true, false, or undefined (both)
)
Treatment Category¶
Overview¶
Treatment is structurally identical to Disease Model Induction - uses a unit-based structure with a Control Question.
System Questions¶
| Question | GUID | Type | Purpose |
|---|---|---|---|
| Treatment Label | b02e3072-74f0-44e0-a468-f472b3b09991 |
Label (textbox) | Creates named treatment instances |
| Treatment Control | d04ec2d7-3e10-4847-9999-befe7ee4c454 |
Boolean (checkbox) | Indicates if this is a control procedure |
Structure¶
Treatment Category
══════════════════
┌─────────────────────────────────────────────────────────────┐
│ Treatment Label [SYSTEM] │
│ ───────────────────────── │
│ id: b02e3072-74f0-44e0-a468-f472b3b09991 │
│ root: true │
│ labelQuestion: true │
│ │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Treatment Control [SYSTEM] ││
│ │ ─────────────────────── ││
│ │ id: d04ec2d7-3e10-4847-9999-befe7ee4c454 ││
│ │ target.parentId: treatmentLabel ││
│ │ questionType: boolean ││
│ │ ││
│ │ ┌───────────────────────────────────────────────────┐ ││
│ │ │ Custom Questions... │ ││
│ │ │ (Same structure as Disease Model Induction) │ ││
│ │ └───────────────────────────────────────────────────┘ ││
│ └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘
Rules¶
Same as Disease Model Induction, but with Treatment-specific GUIDs.
Outcome Assessment Category¶
Overview¶
Outcome Assessment uses a unit-based structure without a Control Question. It has several specialized system questions for outcome measurement metadata and a lookup for PDF graphs.
System Questions¶
| Question | GUID | Type | Parent | Purpose |
|---|---|---|---|---|
| Outcome Label | dbe2720c-2e08-4f47-bcd0-3fe4ae8b8c7f |
Label (textbox) | Root | Creates named outcome instances |
| Average Type | 3a287115-5000-4d3f-8c41-7c46fae9adcf |
Dropdown | Label | Mean vs Median selection |
| Error Type | 8dbea59f-54d2-4e41-87e7-fde9e73a72d5 |
Dropdown | Average Type | SD/SEM/IQR based on average |
| Greater Is Worse | 45351e04-47b2-4785-9a72-713284e917b8 |
Boolean (checkbox) | Label | Outcome directionality |
| Units | 66eb1736-a838-4692-a78b-96b0671a377c |
Textbox | Label | Measurement units |
| PDF Graphs | 016278e8-7e60-40d4-9568-d7fa42670c32 |
Lookup | Label | References PDF annotations |
Structure¶
Outcome Assessment Category
═══════════════════════════
┌─────────────────────────────────────────────────────────────┐
│ Outcome Label [SYSTEM] │
│ ─────────────────────── │
│ id: dbe2720c-2e08-4f47-bcd0-3fe4ae8b8c7f │
│ root: true │
│ labelQuestion: true │
│ │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Average Type [SYSTEM] ││
│ │ ───────────────────── ││
│ │ id: 3a287115-5000-4d3f-8c41-7c46fae9adcf ││
│ │ controlType: dropdown ││
│ │ options: [Mean, Median] ││
│ │ ││
│ │ ┌─────────────────────────────────────────────────────┐││
│ │ │ Error Type [SYSTEM] │││
│ │ │ ────────────────── │││
│ │ │ id: 8dbea59f-54d2-4e41-87e7-fde9e73a72d5 │││
│ │ │ controlType: dropdown │││
│ │ │ options: [SD, SEM, IQR] with parent filters: │││
│ │ │ SD, SEM → shown when Average = Mean │││
│ │ │ IQR → shown when Average = Median │││
│ │ └─────────────────────────────────────────────────────┘││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Greater Is Worse [SYSTEM] ││
│ │ ───────────────────────── ││
│ │ id: 45351e04-47b2-4785-9a72-713284e917b8 ││
│ │ questionType: boolean ││
│ │ controlType: checkbox ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Units [SYSTEM] ││
│ │ ───────────── ││
│ │ id: 66eb1736-a838-4692-a78b-96b0671a377c ││
│ │ controlType: textbox ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ PDF Graphs [SYSTEM - Hidden] ││
│ │ ────────────────────────── ││
│ │ id: 016278e8-7e60-40d4-9568-d7fa42670c32 ││
│ │ annotationLookup: true ││
│ │ Looks up: PDF References from Hidden category ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ [Custom Questions] ││
│ │ ────────────────── ││
│ │ target.parentId: outcomeAssessmentLabel ││
│ └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘
Option Parent Filters¶
The Error Type question demonstrates option-level parent filtering:
// Error Type options with parentFilter
options: [
{
value: "SD",
parentFilter: {
filterType: OptionType.Option,
value: ["Mean"] // Only shown when Average Type = Mean
}
},
{
value: "SEM",
parentFilter: {
filterType: OptionType.Option,
value: ["Mean"] // Only shown when Average Type = Mean
}
},
{
value: "IQR",
parentFilter: {
filterType: OptionType.Option,
value: ["Median"] // Only shown when Average Type = Median
}
}
]
Rules¶
| Rule | Enforcement |
|---|---|
| First-level custom questions must parent to Outcome Label | Frontend only |
| Nested custom questions parent to custom question | Frontend only |
| No control parameter required | Definition |
Cohort Category¶
Overview¶
Cohort is a unit-based category that aggregates entities from other categories via lookup questions. It links disease models, treatments, and outcomes to form experimental cohorts.
System Questions¶
| Question | GUID | Type | Parent | Looks Up |
|---|---|---|---|---|
| Cohort Label | 62c852ad-3390-48a4-ac13-439bf6b6587f |
Label (textbox) | Root | - |
| Disease Models | ecb550a5-ed95-473f-84bf-262c9faa7541 |
Lookup (checklist) | Label | Disease Model Label annotations |
| Treatments | a3f2e5bb-3ade-4830-bb66-b5550a3cc85b |
Lookup (checklist) | Label | Treatment Label annotations |
| Outcomes | 12ecd826-85a4-499a-844c-bd35ea6624ad |
Lookup (checklist) | Label | Outcome Label annotations |
| Number of Animals | 83caa64f-86a1-4f6e-a278-ebbd25297677 |
Integer (textbox) | Label | - |
Structure¶
Cohort Category
═══════════════
┌─────────────────────────────────────────────────────────────┐
│ Cohort Label [SYSTEM] │
│ ───────────────────── │
│ id: 62c852ad-3390-48a4-ac13-439bf6b6587f │
│ root: true │
│ labelQuestion: true │
│ │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Disease Models [SYSTEM - Lookup] ││
│ │ ───────────────────────────────── ││
│ │ id: ecb550a5-ed95-473f-84bf-262c9faa7541 ││
│ │ annotationLookup: true ││
│ │ controlType: checklist ││
│ │ multiple: true ││
│ │ ││
│ │ Looks up: All Disease Model Label annotations ││
│ │ from current study ││
│ │ ││
│ │ emptyLookupText: "Empty - First Enter A Disease ││
│ │ Model Induction Procedure" ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Treatments [SYSTEM - Lookup] ││
│ │ ─────────────────────────── ││
│ │ id: a3f2e5bb-3ade-4830-bb66-b5550a3cc85b ││
│ │ annotationLookup: true ││
│ │ controlType: checklist ││
│ │ multiple: true ││
│ │ ││
│ │ Looks up: All Treatment Label annotations ││
│ │ from current study ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Outcomes [SYSTEM - Lookup] ││
│ │ ───────────────────────── ││
│ │ id: 12ecd826-85a4-499a-844c-bd35ea6624ad ││
│ │ annotationLookup: true ││
│ │ controlType: checklist ││
│ │ multiple: true ││
│ │ ││
│ │ Looks up: All Outcome Label annotations ││
│ │ from current study ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Number of Animals [SYSTEM] ││
│ │ ────────────────────────── ││
│ │ id: 83caa64f-86a1-4f6e-a278-ebbd25297677 ││
│ │ questionType: integer ││
│ │ controlType: textbox ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ [Custom Questions] ││
│ │ ────────────────── ││
│ │ target.parentId: cohortLabel ││
│ └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘
Lookup Resolution¶
// annotation-form.service.ts - How lookups resolve
getOptions(question: IAnnotationQuestion): AnnotationQuestionOption[] {
switch (question.id) {
case systemAnnotationQuestionGuids.cohortDiseaseModels:
// Returns all Disease Model label annotations
return getOptionsFor('diseaseModels');
case systemAnnotationQuestionGuids.cohortTreatments:
// Returns all Treatment label annotations
return getOptionsFor('treatments');
case systemAnnotationQuestionGuids.cohortOutcomes:
// Returns all Outcome label annotations
return getOptionsFor('outcomes');
}
}
Experiment Category¶
Overview¶
Experiment is the highest-level unit, aggregating cohorts. It creates experimental groupings that reference the cohorts defined in the Cohort category.
System Questions¶
| Question | GUID | Type | Parent | Looks Up |
|---|---|---|---|---|
| Experiment Label | 7c555b6e-1fb6-4036-9982-c09a5db82ace |
Label (textbox) | Root | - |
| Cohorts | e7a84ba2-4ef2-4a14-83cb-7decf469d1a2 |
Lookup (checklist) | Label | Cohort Label annotations |
Structure¶
Experiment Category
═══════════════════
┌─────────────────────────────────────────────────────────────┐
│ Experiment Label [SYSTEM] │
│ ───────────────────────── │
│ id: 7c555b6e-1fb6-4036-9982-c09a5db82ace │
│ root: true │
│ labelQuestion: true │
│ │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Cohorts [SYSTEM - Lookup] ││
│ │ ───────────────────────── ││
│ │ id: e7a84ba2-4ef2-4a14-83cb-7decf469d1a2 ││
│ │ annotationLookup: true ││
│ │ controlType: checklist ││
│ │ multiple: true ││
│ │ ││
│ │ Looks up: All Cohort Label annotations ││
│ │ from current study ││
│ │ ││
│ │ emptyLookupText: "Empty - First Enter A Cohort" ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ [Custom Questions] ││
│ │ ────────────────── ││
│ │ target.parentId: experimentLabel ││
│ └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘
Hidden Category¶
Overview¶
The Hidden category contains system questions that should not be displayed in the UI but are used for internal linking purposes.
System Questions¶
| Question | GUID | Type | Purpose |
|---|---|---|---|
| PDF References | 7ee21ff9-e309-4387-8d30-719201497682 |
Label | Stores PDF page/graph references |
Structure¶
Hidden Category
═══════════════
[Not displayed in Question Designer]
[Used for system-level data tracking]
┌─────────────────────────────────────────────────────────────┐
│ PDF References [SYSTEM] │
│ ─────────────────────── │
│ id: 7ee21ff9-e309-4387-8d30-719201497682 │
│ labelQuestion: true │
│ │
│ Purpose: Allows outcome assessments to reference │
│ specific pages/graphs in uploaded PDFs │
│ │
│ Referenced by: Outcome Assessment > PDF Graphs lookup │
└─────────────────────────────────────────────────────────────┘
Data Flow Between Categories¶
┌─────────────────────────────────────────────────────────────────────────────┐
│ CATEGORY DATA FLOW │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Disease Model Induction │
│ ────────────────────── │
│ [Creates labels] ─────────────────────────┐ │
│ │ │
│ Treatment │ │
│ ───────── │ │
│ [Creates labels] ─────────────────────────┼──────────► Cohort │
│ │ ────── │
│ Outcome Assessment │ [Aggregates │
│ ────────────────── │ via lookups] │
│ [Creates labels] ─────────────────────────┘ │ │
│ │ │
│ │ │
│ Hidden (PDF References) │ │
│ ────────────────────── │ │
│ [Creates labels] ──────► Outcome Assessment │ │
│ (PDF Graphs lookup) │ │
│ │ │
│ ▼ │
│ Experiment │
│ ────────── │
│ [Aggregates │
│ cohorts] │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Appendix: Complete GUID Reference¶
export enum systemAnnotationQuestionGuids {
// Label Questions (create named instances)
diseaseModelInductionLabel = 'bdb6e257-5a08-42ef-aad0-829668679b0e',
treatmentLabel = 'b02e3072-74f0-44e0-a468-f472b3b09991',
outcomeAssessmentLabel = 'dbe2720c-2e08-4f47-bcd0-3fe4ae8b8c7f',
cohortLabel = '62c852ad-3390-48a4-ac13-439bf6b6587f',
experimentLabel = '7c555b6e-1fb6-4036-9982-c09a5db82ace',
pdfReferences = '7ee21ff9-e309-4387-8d30-719201497682',
// Control Questions (is this a control procedure?)
treatmentControl = 'd04ec2d7-3e10-4847-9999-befe7ee4c454',
modelControl = 'b18aa936-a4c6-446b-ac98-88ac38930878',
// Lookup Questions (cross-reference other categories)
cohortDiseaseModels = 'ecb550a5-ed95-473f-84bf-262c9faa7541',
cohortTreatments = 'a3f2e5bb-3ade-4830-bb66-b5550a3cc85b',
cohortOutcomes = '12ecd826-85a4-499a-844c-bd35ea6624ad',
experimentCohorts = 'e7a84ba2-4ef2-4a14-83cb-7decf469d1a2',
outcomePdfGraphs = '016278e8-7e60-40d4-9568-d7fa42670c32',
// Outcome Assessment metadata
outcomeAverageType = '3a287115-5000-4d3f-8c41-7c46fae9adcf',
outcomeErrorType = '8dbea59f-54d2-4e41-87e7-fde9e73a72d5',
outcomeGreaterIsWorse = '45351e04-47b2-4785-9a72-713284e917b8',
outcomeUnits = '66eb1736-a838-4692-a78b-96b0671a377c',
// Cohort specific
cohortNumberOfAnimals = '83caa64f-86a1-4f6e-a278-ebbd25297677',
}