modware-annotation

module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 18, 2026 License: BSD-2-Clause

README

modware-annotation

License
GitHub action codecov
Last commit
Funding

gRPC microservice for managing biological annotations and feature annotations in dictyBase. Backed by ArangoDB.

On every create, update, or delete mutation the service publishes a protobuf-serialized event to NATS so that downstream services can react without polling.

Running the Server

Two gRPC servers are available: start-server for tagged annotations (port 9560) and start-feature-server for feature annotations (port 9570). See --help on each command for the full flag list.

# Tagged annotation server
modware-annotation start-server \
  --port 9560 \
  --arangodb-database annotation \
  --arangodb-user root \
  --arangodb-pass secret \
  --arangodb-host arangodb \
  --arangodb-port 8529 \
  --nats-host nats \
  --nats-port 4222

# Feature annotation server
modware-annotation start-feature-server \
  --port 9570 \
  --arangodb-database annofeature \
  --arangodb-user root \
  --arangodb-pass secret \
  --arangodb-host arangodb \
  --arangodb-port 8529 \
  --nats-host nats \
  --nats-port 4222
Core Flags

Common to all commands.

Flag Default Description
--log-format json Logging output format (json or text)
--log-level error Log level (debug, warn, error, fatal, panic)
Server Flags (both start-server and start-feature-server)
Flag Default Env Variable Description
--port 9560 / 9570 — gRPC server listen port
--arangodb-database, --db annotation / annofeature ARANGODB_DATABASE ArangoDB database name
--arangodb-user — ARANGODB_USER ArangoDB user
--arangodb-pass — ARANGODB_PASS ArangoDB password
--arangodb-host — ARANGODB_SERVICE_HOST ArangoDB host
--arangodb-port — ARANGODB_SERVICE_PORT ArangoDB port
--is-secure false — Use TLS for ArangoDB
--nats-host — NATS_SERVICE_HOST NATS host
--nats-port — NATS_SERVICE_PORT NATS port
ArangoDB Collection Flags — Tagged Annotations

Control the names of collections, edges, and graphs used by start-server. Defaults match the dictyBase production configuration.

Flag Default Description
--anno-collection annotation Document collection for annotations
--annogroup-collection annotation_group Document collection for annotation groups
--annoterm-collection annotation_cvterm Edge collection linking annotation → ontology term
--annover-collection annotation_version Edge collection linking old → new annotation versions
--annoterm-graph annotation_tag Named graph over annotation_cvterm edges
--annover-graph annotation_history Named graph over annotation_version edges
ArangoDB Collection Flags — Feature Annotations

Control the names of collections, edges, and graphs used by start-feature-server.

Flag Default Description
--feature-collection feature Document collection for feature annotations
--pub-collection publication Document collection for publications
--edge-collection feature_publication Edge collection linking feature → publication
--feature-graph feature_pub_graph Named graph over feature_publication edges
Ontology Flags

These flags configure which ontologies are loaded into ArangoDB and used by the tagged annotation service. The referenced ontologies must be loaded before the service starts (see load-ontologies command).

Flag Default Description
--term-collection cvterm Collection for ontology terms
--rel-collection cvterm_relationship Edge collection for term relationships
--cv-collection cv Collection for ontology metadata
--obograph obograph Named graph for the ontology graph
# Load ontologies before starting the server
modware-annotation load-ontologies \
  --arangodb-database annotation \
  --arangodb-user root \
  --arangodb-pass secret \
  --arangodb-host arangodb \
  --obograph path/to/obograph.json

NATS Events

Tagged Annotations
Operation NATS Subject Payload
Create annotation AnnotationService.Create TaggedAnnotation
Update annotation AnnotationService.Update TaggedAnnotation
Delete annotation AnnotationService.Delete TaggedAnnotation
Feature Annotations
Operation NATS Subject Payload
Create feature annotation FeatureAnnotationService.Create FeatureAnnotation
Update feature annotation FeatureAnnotationService.Update FeatureAnnotation
Add / set / remove tags FeatureAnnotationService.Update FeatureAnnotation

Deserialize using proto.Unmarshal with the generated types from github.com/dictyBase/go-genproto/dictybaseapis/annotation or github.com/dictyBase/go-genproto/dictybaseapis/feature_annotation.

gRPC API

Full protobuf definitions: dictybaseapis/annotation.proto and dictybaseapis/feature_annotation.proto.

Tagged Annotation Service Methods
Method Request Response Description
GetAnnotation AnnotationId TaggedAnnotation Retrieve an annotation by ID
GetEntryAnnotation EntryAnnotationRequest TaggedAnnotation Retrieve an annotation by entry ID
ListAnnotations ListParameters TaggedAnnotationCollection Paginated annotation listing with filters
CreateAnnotation NewTaggedAnnotation TaggedAnnotation Create a new annotation
UpdateAnnotation TaggedAnnotationUpdate TaggedAnnotation Update an existing annotation
DeleteAnnotation DeleteAnnotationRequest Empty Delete an annotation
CreateAnnotationGroup AnnotationIdList TaggedAnnotationGroup Create a group from multiple annotations
GetAnnotationGroup GroupEntryId TaggedAnnotationGroup Retrieve an annotation group by ID
AddToAnnotationGroup AnnotationGroupId TaggedAnnotationGroup Add annotations to an existing group
DeleteAnnotationGroup GroupEntryId Empty Delete an annotation group
ListAnnotationGroups ListGroupParameters TaggedAnnotationGroupCollection Paginated group listing with filters
GetAnnotationTag TagRequest AnnotationTag Retrieve an ontology tag by ID
AutocompleteAnnotation AnnotationAutocompleteParameters AnnotationSuggestionCollection Suggest strain synonyms and genotypes for partial text
SearchAnnotation AnnotationSearchParameters AnnotationSearchResultCollection Search strain annotations across 10 fields and 4 score bands
OboJSONFileUpload stream FileUploadRequest FileUploadResponse Stream-upload an OBO JSON ontology file
Autocomplete Annotation

The AutocompleteAnnotation method returns short suggestions for a partial strain synonym or a partial strain genotype. The request is an AnnotationAutocompleteParameters message. The response is an AnnotationSuggestionCollection message.

Request fields:

Field Value Behavior
data.type annotation The resource name of the request.
data.attributes.query 3 characters or more The service trims the text, converts it to lower case, and removes accents.
data.attributes.limit 5 by default, 50 maximum The service uses 5 when the value is 0. The service rejects a value above 50 with InvalidArgument.

Search behavior:

  • The service searches the synonym and genotype tags of the dicty_annotation ontology.
  • The service searches strain entries only. The entry identifier starts with DBS.
  • The service uses active annotations only. The is_obsolete attribute is false.
  • The service ignores annotations with other tags, for example description.
  • The service returns one suggestion for each strain. It keeps the suggestion with the best score.
  • The service accepts a whole-value prefix and an allele prefix inside a multi-allele genotype value. The query axea and the query sada both match the genotype axeA1, axeB1, sadA-.
  • The service accepts a small typographical error. A fuzzy match uses an n-gram similarity of 0.3 or more.

Order of results:

  1. A prefix match comes before a fuzzy match. A prefix match has a score of 1000 or more.
  2. A fuzzy match has a score less than 1000.
  3. The metadata gives the number of suggestions in meta.total and the effective limit in meta.limit.

Response fields of one AnnotationSuggestion message:

Field Meaning
entry_id The strain identifier of the match, for example DBS0236126.
field The tag of the match. The value is ANNOTATION_SEARCH_FIELD_SYNONYM or ANNOTATION_SEARCH_FIELD_GENOTYPE.
display_text The annotation value.
score The rank of the match.

The method returns an empty collection and no error when no annotation matches. The method does not return NotFound for an empty result.

Search Annotation

The SearchAnnotation method searches 10 strain annotation fields. The request is an AnnotationSearchParameters message. The response is an AnnotationSearchResultCollection message.

Request fields:

Field Value Behavior
data.type annotation The resource name of the request.
data.attributes.query 2 characters or more The service trims the text, converts it to lower case, and removes accents. The service rejects a query that has only stopwords.
data.attributes.limit 50 by default, 50 maximum The service uses 50 when the value is 0. The service rejects a value below 0 or above 50 with InvalidArgument.

Searched strain fields:

The service searches 10 strain fields across active strain annotations (DBS... entry identifiers):

  • 6 annotation value fields:
    • synonym (dicty_annotation ontology)
    • genotype (dicty_annotation ontology, whole-value and interior allele prefix)
    • systematic_name (dicty_annotation ontology, tag systematic name)
    • genetic_modification (dicty_annotation ontology, tag mutant type)
    • mutagenesis_method (Dd Mutagenesis Method ontology, tag mutagenesis method)
    • public_note (dicty_annotation ontology, tag public note, token and phrase match)
  • 4 ontology term fields (term label matched through a 1-hop inbound traversal):
    • phenotype (Dicty Phenotypes ontology)
    • environment (Dicty Environment ontology)
    • assay (Dictyostelium Assay ontology)
    • characteristic (dicty_strain_characteristics ontology)

Search behavior:

  • The service searches strain entries only. The entry identifier starts with DBS.
  • The service uses active annotations only. The is_obsolete attribute is false.
  • The service uses active ontology terms only. The deprecated attribute is false.
  • The service ignores annotations with other tags. It also ignores non-strain annotations (DDB_G..., DBP...).
  • The service returns one result for each strain. It keeps the result with the best score.
  • The service tolerates missing ontologies. If an ontology is not loaded, its branches return zero results and other branches continue.
  • The service accepts a whole-value prefix and an allele prefix inside a multi-allele genotype value.
  • The service accepts a small typographical error. A fuzzy match uses an n-gram similarity of 0.3 or more.

Order of results (4 score bands):

  1. A prefix match comes first. A prefix match has a score of 1000 or more (1000 + BM25(d)).
  2. A phrase match comes second. A phrase match has a score between 500 and 750 (500 + BM25(d)).
  3. A token match comes third. A token match has a score between 250 and 500 (250 + BM25(d)).
  4. A fuzzy match comes fourth. A fuzzy match has a score less than 250 (BM25(d)).
  5. The metadata gives the number of results in meta.total and the effective limit in meta.limit.

Response fields of one AnnotationSearchResult message:

Field Meaning
entry_id The strain identifier of the match, for example DBS0236126.
field The field enum of the match, for example ANNOTATION_SEARCH_FIELD_PHENOTYPE.
display_text The matched annotation value or ontology term label.
score The rank of the match.

The method returns an empty collection and no error when no annotation matches. The method does not return NotFound for an empty result.

Feature Annotation Service Methods
Method Request Response Description
CreateFeatureAnnotation NewFeatureAnnotation FeatureAnnotation Create a new feature annotation
GetFeatureAnnotation FeatureAnnotationId FeatureAnnotation Retrieve a feature annotation by ID
GetFeatureAnnotationByName FeatureName FeatureAnnotation Retrieve a feature annotation by name
UpdateFeatureAnnotation FeatureAnnotationUpdate FeatureAnnotation Update an existing feature annotation
DeleteFeatureAnnotation DeleteFeatureAnnotationRequest Empty Delete a feature annotation
AddTag AddTagRequest FeatureAnnotation Add a single tag to a feature
AddTags AddTagsRequest FeatureAnnotation Add multiple tags to a feature
SetTags SetTagsRequest FeatureAnnotation Replace all tags on a feature
RemoveTags RemoveTagsRequest FeatureAnnotation Remove specific tags from a feature
ListFeatureAnnotationsByPubmedId PubmedId FeatureAnnotationCollection List feature annotations by PubMed ID
ListFeatureAnnotationsByDOI DOI FeatureAnnotationCollection List feature annotations by DOI
Connect with Go
import (
    "context"
    "log"

    "github.com/dictyBase/go-genproto/dictybaseapis/annotation"
    "github.com/dictyBase/go-genproto/dictybaseapis/feature_annotation"
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials/insecure"
)

func main() {
    // Tagged annotation client
    annoConn, err := grpc.NewClient(
        "localhost:9560",
        grpc.WithTransportCredentials(insecure.NewCredentials()),
    )
    if err != nil {
        log.Fatal(err)
    }
    defer annoConn.Close()
    annoClient := annotation.NewTaggedAnnotationServiceClient(annoConn)

    // Feature annotation client
    featConn, err := grpc.NewClient(
        "localhost:9570",
        grpc.WithTransportCredentials(insecure.NewCredentials()),
    )
    if err != nil {
        log.Fatal(err)
    }
    defer featConn.Close()
    featClient := feature_annotation.NewFeatureAnnotationServiceClient(featConn)

    ctx := context.Background()
    _, _ = annoClient, featClient // use clients below
}
Create an Annotation

value, entry_id, created_by, tag, and ontology are required.

resp, err := annoClient.CreateAnnotation(ctx, &annotation.NewTaggedAnnotation{
    Data: &annotation.NewTaggedAnnotation_Data{
        Type: "annotation",
        Attributes: &annotation.NewTaggedAnnotationAttributes{
            Value:     "localizes to nucleus",
            EntryId:   "DDB_G0285418",
            CreatedBy: "user@dictybase.org",
            Tag:       "GO:0005634",
            Ontology:  "cellular_component",
            Version:   1,
            Rank:      0,
        },
    },
})
// resp.Data.Id — auto-generated annotation ID
Get an Annotation
resp, err := annoClient.GetAnnotation(ctx, &annotation.AnnotationId{Id: "12345"})

// Or by entry ID
resp, err := annoClient.GetEntryAnnotation(ctx, &annotation.EntryAnnotationRequest{
    EntryId: "DDB_G0285418",
})
Update an Annotation

All attributes are optional; unset fields are left unchanged.

resp, err := annoClient.UpdateAnnotation(ctx, &annotation.TaggedAnnotationUpdate{
    Data: &annotation.TaggedAnnotationUpdate_Data{
        Type: "annotation",
        Id:   "12345",
        Attributes: &annotation.TaggedAnnotationUpdateAttributes{
            Value:        "localizes to nucleolus",
            EditableValue: "updated description",
            IsObsolete:   false,
        },
    },
})
Delete an Annotation
_, err := annoClient.DeleteAnnotation(ctx, &annotation.DeleteAnnotationRequest{
    Id: "12345",
})
List Annotations with Pagination and Filters

ListAnnotations uses cursor-based pagination. The default page size is 10.

resp, err := annoClient.ListAnnotations(ctx, &annotation.ListParameters{
    Limit:  10,
    Cursor: 0,
    Filter: "entry_id===DDB_G0285418",
})
// resp.Data           — slice of annotations for this page
// resp.Meta.NextCursor — pass as Cursor to retrieve the next page (0 means last page)
// resp.Meta.Total      — total number of records matching the filter
// resp.Meta.Limit      — the effective page size

// Fetch the next page
if resp.Meta.NextCursor != 0 {
    next, err := annoClient.ListAnnotations(ctx, &annotation.ListParameters{
        Limit:  10,
        Cursor: resp.Meta.NextCursor,
        Filter: "entry_id===DDB_G0285418",
    })
}
Filtering

ListAnnotations accepts a filter string in ListParameters. Filters follow the syntax field operator value and can be combined with boolean connectors.

Boolean Connectors
Symbol Meaning Precedence
; AND Higher
, OR Lower

AND takes precedence over OR.

String Operators
Operator Meaning
=== Equals
!== Not equals
=~ Contains substring
!~ Does not contain substring
Numeric Operators
Operator Meaning
== Equals
!= Not equals
> Greater than
< Less than
=< Less than or equal to
>= Greater than or equal to
Boolean Operators
Operator Meaning
== Equals
!= Not equals
Filterable Fields
Filter Key Type Operators Description
entry_id string ===, !==, =~, !~ dictyBase gene/feature ID
value string ===, !==, =~, !~ Annotation text
created_by string ===, !==, =~, !~ Creator email
tag string ===, !==, =~, !~ Ontology term label
ontology string ===, !==, =~, !~ Ontology namespace
version number ==, !=, >, <, =<, >= Annotation version
rank number ==, !=, >, <, =<, >= Annotation rank
is_obsolete boolean ==, != Whether the annotation is obsolete
Examples
// Annotations for a specific gene entry
resp, err := annoClient.ListAnnotations(ctx, &annotation.ListParameters{
    Limit:  10,
    Filter: "entry_id===DDB_G0285418",
})

// Annotations containing a keyword
resp, err := annoClient.ListAnnotations(ctx, &annotation.ListParameters{
    Limit:  10,
    Filter: "value=~actin",
})

// Annotations with a specific ontology tag
resp, err := annoClient.ListAnnotations(ctx, &annotation.ListParameters{
    Limit:  10,
    Filter: "tag===GO:0005634",
})

// Non-obsolete annotations of a given version or higher
resp, err := annoClient.ListAnnotations(ctx, &annotation.ListParameters{
    Limit:  10,
    Filter: "entry_id===DDB_G0285418;is_obsolete==false;version>=2",
})

// Annotations with either of two tags (OR)
resp, err := annoClient.ListAnnotations(ctx, &annotation.ListParameters{
    Limit:  10,
    Filter: "tag===GO:0005634,tag===GO:0005737",
})
Annotation Groups

Group multiple annotations together and manage them as a unit.

// Create a group
resp, err := annoClient.CreateAnnotationGroup(ctx, &annotation.AnnotationIdList{
    Id: []string{"12345", "12346", "12347"},
})
// resp.Data.GroupId — the new group's ID

// Get a group
group, err := annoClient.GetAnnotationGroup(ctx, &annotation.GroupEntryId{
    GroupId: resp.Data.GroupId,
})

// Add annotations to an existing group
updated, err := annoClient.AddToAnnotationGroup(ctx, &annotation.AnnotationGroupId{
    GroupId: resp.Data.GroupId,
    Id:      []string{"12348"},
})

// List groups
groups, err := annoClient.ListAnnotationGroups(ctx, &annotation.ListGroupParameters{
    Limit:  10,
    Cursor: 0,
    Filter: "entry_id===DDB_G0285418",
})

// Delete a group
_, err = annoClient.DeleteAnnotationGroup(ctx, &annotation.GroupEntryId{
    GroupId: resp.Data.GroupId,
})
Group Filtering

ListAnnotationGroups uses the same filter syntax and fields as ListAnnotations. The filter is applied in two steps internally: first the matching annotation _key values are collected, then groups whose group array contains at least one of those keys are returned.

Filterable Fields
Filter Key Type Description
entry_id string The entry being annotated
created_by string Email of the annotation creator
tag string Ontology term label
ontology string Ontology namespace
rank number Annotation ordering

Group filtering supports the same operators and boolean connectors (; AND, , OR) as annotation filtering. See Filtering for the full operator reference.

// Groups containing annotations for a specific entry
groups, err := annoClient.ListAnnotationGroups(ctx, &annotation.ListGroupParameters{
    Limit:  10,
    Cursor: 0,
    Filter: "entry_id===DDB_G0285418",
})

// Groups containing annotations with a specific tag
groups, err := annoClient.ListAnnotationGroups(ctx, &annotation.ListGroupParameters{
    Limit:  10,
    Filter: "tag===GO:0005634",
})

// Groups containing annotations matching either of two tags
groups, err := annoClient.ListAnnotationGroups(ctx, &annotation.ListGroupParameters{
    Limit:  10,
    Filter: "tag===GO:0005634,tag===GO:0005737",
})

// Groups containing non-obsolete annotations (is_obsolete is not a group filter
// field; filter by rank or tag instead for active annotations)
groups, err := annoClient.ListAnnotationGroups(ctx, &annotation.ListGroupParameters{
    Limit:  10,
    Filter: "entry_id===DDB_G0285418;rank>=0",
})
Create a Feature Annotation

id, created_by, updated_by, and name are required.

resp, err := featClient.CreateFeatureAnnotation(ctx, &feature_annotation.NewFeatureAnnotation{
    Data: &feature_annotation.NewFeatureAnnotation_Data{
        Type: "feature_annotation",
        Id:   "DDB_G0285418",
        Attributes: &feature_annotation.NewFeatureAnnotationAttributes{
            CreatedBy:  "user@dictybase.org",
            UpdatedBy:  "user@dictybase.org",
            Name:       "act15",
            Synonyms:   []string{"actin15"},
            Pubmed:     []string{"12345678"},
            Publications: []string{"10.1234/example"},
        },
    },
})
Get a Feature Annotation
resp, err := featClient.GetFeatureAnnotation(ctx, &feature_annotation.FeatureAnnotationId{
    Id: "DDB_G0285418",
})

// Or by name
resp, err := featClient.GetFeatureAnnotationByName(ctx, &feature_annotation.FeatureName{
    Name: "act15",
})
Update a Feature Annotation

All attributes are optional; unset fields are left unchanged.

resp, err := featClient.UpdateFeatureAnnotation(ctx, &feature_annotation.FeatureAnnotationUpdate{
    Data: &feature_annotation.FeatureAnnotationUpdate_Data{
        Type: "feature_annotation",
        Id:   "DDB_G0285418",
        Attributes: &feature_annotation.FeatureAnnotationUpdateAttributes{
            UpdatedBy: "user@dictybase.org",
            Synonyms:  []string{"actin15", "act15_v2"},
            Pubmed:    []string{"12345678", "87654321"},
        },
    },
})
Tag Operations on Feature Annotations

Feature annotations support custom tag properties (key–value pairs with optional ontology references).

// Add a single tag
resp, err := featClient.AddTag(ctx, &feature_annotation.AddTagRequest{
    FeatureId: "DDB_G0285418",
    Tag: &feature_annotation.TagProperty{
        Tag:      "expression",
        Value:    "high",
        Ontology: "dicty_expression",
    },
})

// Add multiple tags at once
resp, err := featClient.AddTags(ctx, &feature_annotation.AddTagsRequest{
    FeatureId: "DDB_G0285418",
    Tags: []*feature_annotation.TagProperty{
        {Tag: "expression", Value: "high", Ontology: "dicty_expression"},
        {Tag: "localization", Value: "nucleus", Ontology: "cellular_component"},
    },
})

// Replace all tags (atomically sets the tag list)
resp, err := featClient.SetTags(ctx, &feature_annotation.SetTagsRequest{
    FeatureId: "DDB_G0285418",
    Tags: []*feature_annotation.TagProperty{
        {Tag: "function", Value: "actin binding", Ontology: "molecular_function"},
    },
})

// Remove specific tags
resp, err := featClient.RemoveTags(ctx, &feature_annotation.RemoveTagsRequest{
    FeatureId: "DDB_G0285418",
    Tags: []*feature_annotation.TagProperty{
        {Tag: "expression"},
    },
})
List Feature Annotations by Publication
// By PubMed ID
resp, err := featClient.ListFeatureAnnotationsByPubmedId(ctx, &feature_annotation.PubmedId{
    Id: "12345678",
})

// By DOI
resp, err := featClient.ListFeatureAnnotationsByDOI(ctx, &feature_annotation.DOI{
    Id: "10.1234/example",
})

ArangoDB Schema

Tagged Annotations
erDiagram
    annotation ||--o{ annotation_cvterm : "annoterm edge"
    annotation ||--o| annotation : "annover edge (previous version)"
    annotation ||--o{ annotation_group : "group membership"

    cv ||--o{ cvterm : "contains"

    annotation {
        string _key PK
        string entry_id
        string value
        string editable_value
        string created_by
        string ontology
        string tag
        string cvtid
        int version
        int rank
        bool is_obsolete
        timestamp created_at
    }

    annotation_group {
        string _key PK
        string group_id
        list group "array of annotation _key values"
        timestamp created_at
        timestamp updated_at
    }

    cvterm {
        string _key PK
        string label
        string name
    }

    cv {
        string _key PK
        string namespace
    }

The annotation collection stores individual annotated statements linked to a dictyBase gene or feature (entry_id). Each annotation references an ontology term through the cvtid field, with the term's label and namespace denormalized into tag and ontology for efficient filtering. Version history is tracked via annotation_version edges connecting old rows to their replacements.

Edge collections and their graphs:

Edge Collection Graph From → To Purpose
annotation_cvterm annotation_tag annotation → cvterm Links an annotation to its ontology term
annotation_version annotation_history annotation → annotation (old → new) Tracks annotation revision history
Autocomplete Search Assets

The AutocompleteAnnotation method uses an ArangoSearch view and three analyzers. NewTaggedAnnotationRepo creates the view and the analyzers at server start. The start is idempotent, so a restart does not change the assets.

Asset Type Purpose
annotation_autocomplete_norm norm analyzer Converts a value to lower case and removes the accents.
annotation_autocomplete_delim pipeline analyzer Splits a value at the commas and the spaces. Then it applies the norm step.
annotation_autocomplete_ngram pipeline analyzer Applies the norm step. Then it indexes the n-grams of 2 and 3 characters.
annotation_autocomplete arangosearch view Indexes the annotation collection.

The view indexes these attributes of the annotation collection:

Attribute Analyzers Purpose
value annotation_autocomplete_norm, annotation_autocomplete_delim, annotation_autocomplete_ngram Whole-value prefix, allele prefix, and fuzzy matches
entry_id annotation_autocomplete_norm The strain filter inside the search
is_obsolete identity The active-annotation filter inside the search

At each start the service compares the stored links of the view with the links that the search needs. The service updates the view in place with SetProperties when the links differ. The service does not delete the view, so the view identifier does not change.

The search resolves the _id of the synonym and genotype terms before it runs the statement. The statement then filters the annotations on the tag edges. Therefore the statement does not scan the cvterm collection.

Full Search Assets

The SearchAnnotation method uses an ArangoSearch view, three custom analyzers, and two built-in analyzers. NewTaggedAnnotationRepo creates the view and the custom analyzers at server start. The start is idempotent, so a restart does not change the assets.

Asset Type Purpose
annotation_search_norm norm analyzer Converts a value to lower case and removes accents.
annotation_search_delim pipeline analyzer Splits a value at commas and spaces. Then it applies the norm step.
annotation_search_ngram pipeline analyzer Applies the norm step. Then it indexes n-grams of 2 and 3 characters.
text_en Built-in text analyzer English stemming and tokenization for token and phrase branches.
identity Built-in identity analyzer Exact match for boolean and filter attributes.
annotation_full_search arangosearch view Indexes the annotation and cvterm collections.

The view links two collections:

annotation collection link:

Attribute Analyzers Purpose
value annotation_search_norm, annotation_search_delim, annotation_search_ngram, text_en Prefix, allele prefix, fuzzy, token, and phrase matches on annotation values
entry_id annotation_search_norm In-index strain prefix filter STARTS_WITH(d.entry_id, "dbs")
is_obsolete identity In-index active-annotation filter d.is_obsolete == false

cvterm collection link:

Attribute Analyzers Purpose
label annotation_search_norm, annotation_search_ngram, text_en Prefix, fuzzy, token, and phrase matches on ontology term labels
graph_id identity In-index ontology filter d.graph_id == @<onto>_graph_id
deprecated identity In-index active-term filter d.deprecated == false

At each start the service compares the stored links of the view with the required links. The service updates the view in place with SetProperties when the links differ. The service does not delete the view, so the view identifier does not change.

Before the search statement runs, a single target-resolution query resolves the six tag term identifiers and the four ontology graph identifiers. If an ontology is not loaded, its identifier defaults to an empty string. The search statement executes with 28 view branches, 0 collection scans, and 28 graph traversals.

Feature Annotations
erDiagram
    feature ||--o{ feature_publication : "edges"
    publication ||--o{ feature_publication : "edges"

    feature {
        string _key PK
        string feature_id UK
        string feature_type
        string name
        string created_by
        string updated_by
        list synonyms
        list publications "DOI references"
        list pubmed "PubMed IDs"
        json dblinks "external database cross-references"
        json properties "custom tag key-value pairs"
        bool is_obsolete
        timestamp created_at
        timestamp updated_at
    }

    publication {
        string _key PK
        string id UK
    }

Feature annotations model biological features (genes, proteins, etc.) with rich metadata including synonyms, publications, database cross-references, and custom tag properties. Publications are stored in a separate publication collection and linked via the feature_publication edge collection, allowing many-to-many relationships.

Edge collections and their graphs:

Edge Collection Graph From → To Purpose
feature_publication feature_pub_graph feature → publication Links a feature annotation to its associated publications

Deploy path: buildless deploy with named just arguments (deploy refactor P0.2/P0.3).

Directories

Path Synopsis
cmd
modware-annotation command
Package main is the entry point for the modware-annotation microservice CLI.
Package main is the entry point for the modware-annotation microservice CLI.
internal
app/server
Package server provides gRPC server startup functions for the annotation service.
Package server provides gRPC server startup functions for the annotation service.
app/service
Package service implements the gRPC service handlers for the annotation service.
Package service implements the gRPC service handlers for the annotation service.
app/validate
Package validate provides argument validation helpers for CLI commands.
Package validate provides argument validation helpers for CLI commands.
collection
Package collection provides generic collection utility functions.
Package collection provides generic collection utility functions.
iterutil
Package iterutil provides generic iterator utility functions for Go's iter.Seq type.
Package iterutil provides generic iterator utility functions for Go's iter.Seq type.
message
Package message defines publisher interfaces for annotation messaging.
Package message defines publisher interfaces for annotation messaging.
message/nats
Package nats provides NATS messaging publisher implementations.
Package nats provides NATS messaging publisher implementations.
model
Package model defines data structures for annotations.
Package model defines data structures for annotations.
pipe
Package pipe provides functional pipeline utilities for composing functions in sequence.
Package pipe provides functional pipeline utilities for composing functions in sequence.
repository
Package repository defines interfaces and error types for annotation data storage.
Package repository defines interfaces and error types for annotation data storage.
repository/arangodb
Package arangodb implements the annotation repository using ArangoDB.
Package arangodb implements the annotation repository using ArangoDB.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL