1 Synesis: In-Memory API (synesis.load)

Version 0.2.0


1.1 Introduction

The synesis.load API allows compiling Synesis projects directly in memory, without dependency on files on disk. This functionality is ideal for:

  • Jupyter Notebooks: Interactive analysis of qualitative data
  • Python Scripts: Research pipeline automation
  • Pandas Integration: Direct export to DataFrames
  • Testing and Prototyping: Quick annotation validation

1.1.1 Difference between CLI and API

Aspect CLI (synesis compile) API (synesis.load)
Input Files on disk (.synp, .syn, .synt) Strings in memory
Output JSON/CSV/Excel files Dicts, DataFrames
Usage Terminal, CI/CD Notebooks, Scripts
I/O Disk read/write Zero I/O

1.2 Installation

1.2.1 Requirements

pip install synesis

1.2.3 Verify installation

import synesis
print(synesis.__version__)  # 0.2.0

1.3 Quick Start

import synesis

# In-memory contents
template = """
TEMPLATE Minimal
SOURCE FIELDS
    OPTIONAL date
END SOURCE FIELDS
ITEM FIELDS
    REQUIRED quote
END ITEM FIELDS
FIELD date TYPE DATE SCOPE SOURCE END FIELD
FIELD quote TYPE QUOTATION SCOPE ITEM END FIELD
END TEMPLATE
"""

project = """
PROJECT Demo
    TEMPLATE "template.synt"
END PROJECT
"""

annotations = {
    "sample.syn": """
SOURCE @ref2024
    date: 2024-06-15

    ITEM
        quote: The technology shows promising results.
    END ITEM
END SOURCE
"""
}

bibliography = """
@article{ref2024,
    author = {Silva, Maria},
    title = {Technology Study},
    year = {2024}
}
"""

# Compile
result = synesis.load(
    project_content=project,
    template_content=template,
    annotation_contents=annotations,
    bibliography_content=bibliography,
)

# Check result
if result.success:
    print(f"Compiled: {result.stats.item_count} items")
    df = result.to_dataframe("items")
    print(df)
else:
    print(result.get_diagnostics())

1.4 Function synesis.load()

1.4.1 Signature

def load(
    project_content: str,
    template_content: str,
    annotation_contents: Optional[Dict[str, str]] = None,
    ontology_contents: Optional[Dict[str, str]] = None,
    bibliography_content: Optional[str] = None,
    project_filename: str = "<project>",
    template_filename: str = "<template>",
) -> MemoryCompilationResult

1.4.2 Parameters

Parameter Type Required Description
project_content str Yes .synp file content
template_content str Yes .synt file content
annotation_contents Dict[str, str] No Dictionary {filename: content} for .syn files
ontology_contents Dict[str, str] No Dictionary {filename: content} for .syno files
bibliography_content str No .bib file content (BibTeX)
project_filename str No Virtual name for error messages
template_filename str No Virtual name for error messages

1.4.3 Return

Returns a MemoryCompilationResult object with compiled data and export methods.

1.4.4 Complete Example

import synesis

result = synesis.load(
    project_content="""
        PROJECT QualitativeResearch
            TEMPLATE "analysis.synt"
            INCLUDE BIBLIOGRAPHY "refs.bib"
            INCLUDE ANNOTATIONS "data.syn"
            INCLUDE ONTOLOGY "concepts.syno"
        END PROJECT
    """,
    template_content="""
        TEMPLATE QualitativeAnalysis

        SOURCE FIELDS
            REQUIRED date
            OPTIONAL country
        END SOURCE FIELDS

        ITEM FIELDS
            REQUIRED quote
            REQUIRED BUNDLE note, chain
            OPTIONAL code
        END ITEM FIELDS

        ONTOLOGY FIELDS
            REQUIRED description
            OPTIONAL topic
        END ONTOLOGY FIELDS

        FIELD date TYPE DATE SCOPE SOURCE END FIELD
        FIELD country TYPE TEXT SCOPE SOURCE END FIELD
        FIELD quote TYPE QUOTATION SCOPE ITEM END FIELD
        FIELD note TYPE MEMO SCOPE ITEM END FIELD
        FIELD code TYPE CODE SCOPE ITEM END FIELD
        FIELD chain TYPE CHAIN
            SCOPE ITEM
            ARITY >= 2
            RELATIONS
                INFLUENCES: Influence relationship
                ENABLES: Enablement relationship
            END RELATIONS
        END FIELD
        FIELD description TYPE TEXT SCOPE ONTOLOGY END FIELD
        FIELD topic TYPE TOPIC SCOPE ONTOLOGY END FIELD

        END TEMPLATE
    """,
    annotation_contents={
        "interviews.syn": """
            SOURCE @silva2024
                date: 2024-03-15
                country: Brazil

                ITEM
                    quote: Cost is a significant barrier.
                    note: Interviewee identifies economic factor
                    chain: Cost -> INFLUENCES -> Adoption
                END ITEM

                ITEM
                    quote: Public acceptance facilitates implementation.
                    note: Relationship between social and technical factors
                    chain: Public Acceptance -> ENABLES -> Implementation
                END ITEM
            END SOURCE
        """
    },
    ontology_contents={
        "concepts.syno": """
            ONTOLOGY Cost
                description: Economic cost factor
                topic: Economics
            END ONTOLOGY

            ONTOLOGY Public Acceptance
                description: Community acceptance
                topic: Social Factors
            END ONTOLOGY

            ONTOLOGY Adoption
                description: Technology adoption
                topic: Technology
            END ONTOLOGY

            ONTOLOGY Implementation
                description: Technical implementation
                topic: Technology
            END ONTOLOGY
        """
    },
    bibliography_content="""
        @article{silva2024,
            author = {Silva, João and Santos, Maria},
            title = {Technology Adoption Factors},
            journal = {Brazilian Research Journal},
            year = {2024}
        }
    """,
)

if result.success:
    print(f"Sources: {result.stats.source_count}")
    print(f"Items: {result.stats.item_count}")
    print(f"Ontologies: {result.stats.ontology_count}")
    print(f"Chains: {result.stats.chain_count}")

1.5 Class MemoryCompilationResult

The object returned by synesis.load() offers methods to access and export compiled data.

1.5.1 Attributes

Attribute Type Description
success bool True if compilation without errors
linked_project LinkedProject Linked project (or None if errors)
validation_result ValidationResult Errors, warnings, and information
template TemplateNode Loaded template
bibliography Dict[str, BibEntry] Indexed bibliography
stats CompilationStats Compilation statistics

1.5.2 Statistics (CompilationStats)

result.stats.source_count    # Number of SOURCEs
result.stats.item_count      # Number of ITEMs
result.stats.ontology_count  # Number of ONTOLOGYs
result.stats.code_count      # Unique codes
result.stats.chain_count     # Number of CHAINs
result.stats.triple_count    # Extracted triples (from, rel, to)

1.5.3 Verification Methods

# Check success
if result.success:
    # Process data
    ...

# Check specific errors
if result.has_errors():
    print("Errors found")

if result.has_warnings():
    print("Warnings found")

# Get formatted diagnostics
print(result.get_diagnostics())

1.6 Export Methods

1.6.1 to_json_dict()

Returns complete JSON structure as Python dictionary.

data = result.to_json_dict()

# Access data
project_name = data["project"]["name"]
sources = data["sources"]

for source in sources:
    print(f"Source: {source['bibref']}")
    for item in source["items"]:
        print(f"  Quote: {item['quote']}")

# Serialize to JSON
import json
json_str = json.dumps(data, indent=2, ensure_ascii=False)

1.6.2 to_csv_tables()

Returns all tables as dictionary of tuples (headers, rows).

tables = result.to_csv_tables()

# List available tables
print(tables.keys())  # dict_keys(['sources', 'items', 'ontologies', 'chains', 'codes'])

# Access specific table
headers, rows = tables["items"]
for row in rows:
    print(row)

1.6.3 to_dataframe(table_name)

Returns a specific table as pandas.DataFrame.

import pandas as pd

# Items table
df_items = result.to_dataframe("items")
print(df_items.head())

# Chains table
df_chains = result.to_dataframe("chains")
print(df_chains)

1.6.4 to_dataframes()

Returns all tables as dictionary of DataFrames.

dfs = result.to_dataframes()

# Access any table
dfs["sources"].info()
dfs["items"].describe()
dfs["chains"].head()
dfs["ontologies"].to_csv("ontologies.csv")

1.7 Available Tables

1.7.1 sources

Bibliographic sources with metadata.

Column Description
bibref Bibliographic reference ((key?))
date Date (if defined)
country Country (if defined)
source_file Origin file
source_line Line in file
source_column Column in file

1.7.2 items

Analytical units (excerpts and annotations).

Column Description
bibref Source reference
quote Textual excerpt
notes Analytical annotations (list)
codes Applied codes (list)
source_file Origin file
source_line Line in file
source_column Column in file

1.7.3 chains

Relational triples extracted from chains.

Column Description
bibref Source reference
from_code Origin code
relation Relationship type
to_code Destination code
source_file Origin file
source_line Line in file
source_column Column in file

1.7.4 ontologies

Concept definitions.

Column Description
concept Concept name
description Description
topic Higher category
source_file Origin file
source_line Line in file
source_column Column in file

1.7.5 codes

Code frequency.

Column Description
code Code name
count Usage frequency

1.8 Pandas Integration

1.8.1 Basic Analysis

import synesis
import pandas as pd

result = synesis.load(
    project_content=project,
    template_content=template,
    annotation_contents=annotations,
)

if result.success:
    # Load tables
    dfs = result.to_dataframes()

    # Items analysis
    df_items = dfs["items"]
    print(f"Total items: {len(df_items)}")
    print(f"Items per source: {df_items['bibref'].value_counts()}")

    # Chains analysis
    df_chains = dfs["chains"]
    print(f"Most frequent relations: {df_chains['relation'].value_counts()}")

    # Most used codes
    df_codes = dfs["codes"]
    print(df_codes.sort_values("count", ascending=False))

1.8.2 Filtering and Grouping

# Filter items by source
items_silva = df_items[df_items["bibref"] == "silva2024"]

# Group chains by relation
chains_by_rel = df_chains.groupby("relation").size()

# Ontologies by topic
ontologies_by_topic = dfs["ontologies"].groupby("topic").size()

1.8.3 Export

# To CSV
df_items.to_csv("items_analysis.csv", index=False)

# To Excel (multiple tabs)
with pd.ExcelWriter("analysis.xlsx") as writer:
    for name, df in dfs.items():
        df.to_excel(writer, sheet_name=name, index=False)

1.9 Usage in Jupyter Notebook

1.9.1 Cell 1: Setup

import synesis
import pandas as pd
pd.set_option('display.max_colwidth', 100)

1.9.2 Cell 2: Define Contents

template = """
TEMPLATE JupyterDemo

SOURCE FIELDS
    REQUIRED date
END SOURCE FIELDS

ITEM FIELDS
    REQUIRED quote
    REQUIRED BUNDLE note, chain
END ITEM FIELDS

ONTOLOGY FIELDS
    REQUIRED description
END ONTOLOGY FIELDS

FIELD date TYPE DATE SCOPE SOURCE END FIELD
FIELD quote TYPE QUOTATION SCOPE ITEM END FIELD
FIELD note TYPE MEMO SCOPE ITEM END FIELD
FIELD chain TYPE CHAIN
    SCOPE ITEM
    ARITY >= 2
    RELATIONS
        INFLUENCES: Causal influence
        ENABLES: Enablement
        INHIBITS: Inhibition
    END RELATIONS
END FIELD
FIELD description TYPE TEXT SCOPE ONTOLOGY END FIELD

END TEMPLATE
"""

project = """
PROJECT NotebookAnalysis
    TEMPLATE "template.synt"
END PROJECT
"""

1.9.3 Cell 3: Add Data

annotations = {
    "data.syn": """
SOURCE @study2024
    date: 2024-01-10

    ITEM
        quote: High initial cost hinders adoption.
        note: Economic barrier identified
        chain: Cost -> INHIBITS -> Adoption
    END ITEM

    ITEM
        quote: Government support accelerates implementation.
        note: Positive institutional factor
        chain: Government Support -> ENABLES -> Implementation
    END ITEM

    ITEM
        quote: Lack of technical knowledge limits usage.
        note: Training barrier
        chain: Technical Knowledge -> INFLUENCES -> Usage
    END ITEM
END SOURCE
"""
}

ontologies = {
    "concepts.syno": """
ONTOLOGY Cost
    description: Associated financial costs
END ONTOLOGY

ONTOLOGY Adoption
    description: Technology adoption process
END ONTOLOGY

ONTOLOGY Government Support
    description: Public policy support
END ONTOLOGY

ONTOLOGY Implementation
    description: Technical project execution
END ONTOLOGY

ONTOLOGY Technical Knowledge
    description: Required technical knowledge
END ONTOLOGY

ONTOLOGY Usage
    description: Effective technology use
END ONTOLOGY
"""
}

bibliography = """
@article{study2024,
    author = {Oliveira, Ana},
    title = {Barriers to Technology Adoption},
    year = {2024}
}
"""

1.9.4 Cell 4: Compile

result = synesis.load(
    project_content=project,
    template_content=template,
    annotation_contents=annotations,
    ontology_contents=ontologies,
    bibliography_content=bibliography,
)

print(f"Success: {result.success}")
print(f"Sources: {result.stats.source_count}")
print(f"Items: {result.stats.item_count}")
print(f"Chains: {result.stats.chain_count}")

1.9.5 Cell 5: Visualize Items

df_items = result.to_dataframe("items")
df_items[["bibref", "quote", "notes"]]

1.9.6 Cell 6: Analyze Chains

df_chains = result.to_dataframe("chains")
df_chains

1.9.7 Cell 7: Relationship Network

# Relationship frequency
df_chains["relation"].value_counts().plot(kind="bar", title="Relationship Types")

1.9.8 Cell 8: Export JSON

import json

data = result.to_json_dict()
print(json.dumps(data, indent=2, ensure_ascii=False)[:500])

1.10 Function compile_string()

For parsing individual fragments without complete compilation.

1.10.1 Signature

def compile_string(
    content: str,
    filename: str = "<string>"
) -> List[Any]

1.10.2 Usage

import synesis

# Parse annotation fragment
nodes = synesis.compile_string("""
SOURCE @ref2024
    date: 2024-05-20

    ITEM
        quote: Example text.
    END ITEM
END SOURCE
""")

# Access AST nodes
source = nodes[0]
print(f"Bibref: {source.bibref}")
print(f"Items: {len(source.items)}")

for item in source.items:
    print(f"  Quote: {item.quote}")

1.10.3 Returned Node Types

Type Description
SourceNode SOURCE block with nested ITEMs
ItemNode Individual ITEM block
OntologyNode ONTOLOGY block
ProjectNode PROJECT block

1.11 Error Handling

1.11.1 Syntax Errors

Syntax errors raise SynesisSyntaxError exception:

try:
    result = synesis.load(
        project_content="PROJECT Broken",  # Missing END PROJECT
        template_content=template,
    )
except Exception as e:
    print(f"Syntax error: {e}")

1.11.2 Validation Errors

Semantic errors are captured in the result:

result = synesis.load(
    project_content=project,
    template_content=template,
    annotation_contents={
        "bad.syn": """
SOURCE @nonexistent
    ITEM
        quote: Reference doesn't exist in .bib
    END ITEM
END SOURCE
"""
    },
)

if not result.success:
    print("Validation errors:")
    print(result.get_diagnostics())

1.11.3 Diagnostics Format

error: bad.syn:1:8: Bibliographic reference '@nonexistent' not found.
    SOURCE @nonexistent
           ^~~~~~~~~~~

    Available references: @silva2024, @oliveira2023

1.12 Quick Reference

1.12.1 Import

import synesis

# Main functions
synesis.load(...)           # Complete in-memory compilation
synesis.compile_string(...) # Fragment parsing

# Classes
synesis.MemoryCompilationResult  # Compilation result
synesis.CompilationStats         # Statistics

1.12.2 Typical Flow

# 1. Prepare contents
project = "..."
template = "..."
annotations = {"file.syn": "..."}

# 2. Compile
result = synesis.load(project, template, annotations)

# 3. Verify
if result.success:
    # 4. Export
    df = result.to_dataframe("items")
    data = result.to_json_dict()
else:
    print(result.get_diagnostics())

Documentation generated for Synesis v0.2.0