Skip to main content

Research-as-code framework for sociological surveys.

Project description

siamang

Research-as-code framework for sociological surveys.
Define variables, questionnaires, and logic in pure Python — then deploy, collect, and analyze in a single pipeline.

Quick start · Full pipeline example · API Reference


pip install git+https://github.com/hanelias/siamang.git
siamang validate my_survey.py
siamang preview  my_survey.py        # local preview
siamang deploy   my_survey.py --backend supabase --frontend vercel

What it does

siamang turns a survey into a running web application from a single Python script:

my_survey.py          ← you write this
    │
    ├─ siamang validate   → catches errors before deployment
    ├─ siamang preview    → local frontend (hot-reload)
    ├─ siamang deploy     → Vercel + Supabase (cloud deployment)
    └─ survey.simulate()  → synthetic data for testing

No GUI builders. No drag-and-drop. No lock-in. Your survey is a Python module — version-control it, test it, reuse it.


Quick start

from siamang.core import (
    Variable, SingleChoice, LikertScale, Page, Questionnaire,
)

# Define variables with full metadata
satisfaction = Variable(
    "satisfaction", scale="ordinal",
    label="Overall satisfaction",
    labels={1: "Very dissatisfied", 2: "Dissatisfied",
            3: "Neutral", 4: "Satisfied", 5: "Very satisfied"},
)
remote_freq = Variable(
    "remote_freq", scale="ordinal",
    label="Remote work frequency",
    labels={1: "Never", 2: "1-2 days/week",
            3: "3-4 days/week", 4: "Fully remote"},
)

# Build questions
q_sat = LikertScale("How satisfied are you with your current role?",
                    var=satisfaction, points=5, required=True)
q_remote = SingleChoice("How often do you work remotely?",
                        var=remote_freq, display="radio", required=True)

# Assemble questionnaire
survey = Questionnaire(
    title="Work Attitudes Study",
    pages=[Page("main", items=[q_sat, q_remote])],
)

# Simulate and analyze
data = survey.simulate(n=200)
print(data.report.freq("satisfaction").to_markdown())

# Visualize (requires: pip install siamang[charts])
data.plot.bar("satisfaction").show()

Full Pipeline Example

The examples/full_pipeline/ directory contains a complete Jupyter notebook demonstrating the entire research workflow — from survey design to statistical analysis:

  1. Survey Design — 12 variables, 5 pages, conditional routing (show_if), matrix questions, Likert scales
  2. Simulation & Deployment — 250 synthetic respondents, local SQLite storage, interactive HTML preview
  3. Declarative Reporting — frequency tables, cross-tabs with Chi², grouped means with auto-selected tests, correlation heatmaps
  4. Visualizations — bar charts, boxplots, heatmaps, scatter plots — all with one line of code
cd examples/full_pipeline
jupyter notebook full_pipeline_demo.ipynb

The folder also includes survey_preview.html — an interactive HTML survey you can open in any browser to see how the questionnaire looks for respondents.


Features

Area Capabilities
Core Variables (nominal/ordinal/interval/ratio), questions (single/multi/open/numeric/likert/matrix/ranking), pages, skip logic (show_if/hide_if), quotas, validation
Reporting Declarative tables (FreqTable, CrossTable, GroupMeanTable) and charts (BarChart, BoxPlot, HeatMap, ScatterPlot) — automatic labels, statistical tests, and metadata awareness
Scripts Inline JavaScript for survey-side behaviour — 7 trigger points
Frontend SurveyJS and React 18 runtimes, dark mode, auto-save, access codes, 6 theme presets
Backend Local SQLite for development, Supabase for production, Google Sheets for collaborative access
Deploy Vercel and Netlify frontends with CSP headers; self-contained HTML bundle for offline use
Data I/O CSV, Excel (.xlsx), SPSS (.sav), Stata (.dta), R (.rda) — round-trip with labels and missing values preserved

Declarative Reporting API

Siamang automatically uses variable metadata (labels, scales, missing values) to produce publication-ready outputs — like SPSS, but in Python:

data = survey.simulate(n=300)

# Tables — automatic labels, tests, and formatting
data.report.freq("it_role")                              # frequency table
data.report.crosstab("gender", "satisfaction", pct="col") # cross-tab + Chi²
data.report.means("autonomy", by="remote_freq")          # means + Kruskal-Wallis

# Charts — one line, automatic axis labels
data.plot.bar("it_role")
data.plot.boxplot("satisfaction", by="remote_freq", show_points=True)
data.plot.heatmap(["surv_keystroke", "surv_camera"], by="remote_freq")
data.plot.scatter("satisfaction", "autonomy", hue="gender")

# Export
data.report.freq("it_role").to_markdown()   # Markdown string
data.report.freq("it_role").to_frame()       # pandas DataFrame
data.report.freq("it_role").to_html()       # HTML table

Deployment

Local (development)

siamang preview my_survey.py        # → http://127.0.0.1:8000

Cloud — Vercel + Supabase (high concurrency)

siamang init                        # one-time: stores credentials
siamang deploy my_survey.py --backend supabase --frontend vercel

Cloud — Netlify + Google Sheets (lightweight)

export SIAMANG_GSHEETS_CREDENTIALS_FILE=./service-account-key.json
export NETLIFY_AUTH_TOKEN=nfp_...
siamang deploy my_survey.py --backend gsheets --frontend netlify

Responses are written to a Google Spreadsheet (one row per respondent) via an Apps Script proxy that acts as a secure intermediary. The survey is hosted on Netlify CDN with automatic HTTPS and global edge distribution.

Note: The Google Sheets backend is currently experimental for public web deployments. Browser-to-Sheets writes require an Apps Script Web App URL to avoid exposing credentials. See docs/reference/deploy.md for setup instructions.

Deployment combinations

Use case Backend Frontend
Local development / testing local local
Small survey, shared with team gsheets netlify
Production, high concurrency supabase vercel or netlify
Offline / air-gapped local local (HTML bundle)

Project Layout

siamang/
├── core/        Variable, Question types, Block, Page, Questionnaire, Expression, Quota, Script
├── data/        SurveyData, DataAnalysis, DataProcessing, SurveyTables
├── reporting/   Declarative tables (FreqTable, CrossTable, GroupMeanTable) and charts (BarChart, BoxPlot, HeatMap, ScatterPlot)
├── frontend/    SurveyJS & React runtimes, bundle builder, UIConfig theme engine, presets
├── deploy/      Backends (SQLite, Supabase, Google Sheets), frontends (Vercel, Netlify, local), pipeline orchestration
├── cli/         validate, preview, deploy, init
├── io/          Import/export for CSV, Excel, SPSS, Stata, R
└── config/      User configuration (~/.siamang.toml), secrets

Documentation

Resource Description
docs/reference/core.md API reference — Variable, Expression, all Question types, Page, Questionnaire
docs/reference/data.md API reference — SurveyData, DataAnalysis, DataProcessing, SurveyTables
docs/reference/reporting.md API reference — Declarative tables and charts
docs/reference/frontend.md API reference — UIConfig, theme presets, runtimes, bundle builder
docs/reference/deploy.md API reference — Backends (Local, Supabase, Google Sheets), Frontends (Local, Vercel, Netlify), pipeline
examples/full_pipeline/ Complete worked example: design → deploy → analyze

Requirements

  • Python 3.11+
  • For cloud deployment (option A): a Supabase project and a Vercel account
  • For cloud deployment (option B): a Google Cloud service account and a Netlify account

Dependencies

All core dependencies are installed automatically with pip install siamang.

Core (installed automatically)

Package Version Purpose
pandas ≥ 2.0 Data manipulation, SurveyData backbone
scipy ≥ 1.11 Statistical tests (chi-square, t-test, ANOVA)
openpyxl ≥ 3.1 Excel (.xlsx) import/export
pyreadstat ≥ 1.2 SPSS (.sav) and Stata (.dta) import/export
fastapi ≥ 0.110 Local preview server (siamang preview)
uvicorn ≥ 0.29 ASGI server for local preview
supabase ≥ 2.0 Supabase backend (Postgres + RLS + Edge Functions)
requests ≥ 2.31 HTTP client for Netlify/Vercel deployment APIs

Charts (optional)

pip install siamang[charts]
Package Version Purpose
matplotlib ≥ 3.7 Chart rendering (data.plot.bar(), .boxplot(), .scatter(), .heatmap())
seaborn ≥ 0.13 Statistical visualization helpers

Charts are optional — if you only use tables (data.report.freq(), data.report.crosstab()), matplotlib is not needed. A clear error message will guide you if you try to render a chart without it.

Google Sheets backend (optional)

pip install siamang[gsheets]
Package Version Purpose
google-auth ≥ 2.0 Service account authentication
google-auth-httplib2 ≥ 0.1 HTTP transport for Google APIs
google-api-python-client ≥ 2.0 Google Sheets API and Google Drive API client

Development

pip install siamang[dev]
Package Version Purpose
ruff ≥ 0.4 Linting and formatting
mypy ≥ 1.10 Static type checking
pytest ≥ 8.0 Test runner
matplotlib ≥ 3.7 Required for chart tests
seaborn ≥ 0.13 Required for chart tests

License

Siamang is released under the MIT License. Free for any use — academic, commercial, personal.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

siamang-0.5.0.tar.gz (228.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

siamang-0.5.0-py3-none-any.whl (216.8 kB view details)

Uploaded Python 3

File details

Details for the file siamang-0.5.0.tar.gz.

File metadata

  • Download URL: siamang-0.5.0.tar.gz
  • Upload date:
  • Size: 228.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.1

File hashes

Hashes for siamang-0.5.0.tar.gz
Algorithm Hash digest
SHA256 0abd345ca1bf48ea2f7c96f64221463aff48d63b6c627b3337b0f6624875884b
MD5 89ce809b769c8d8b2f80b5ed49922557
BLAKE2b-256 c256d8b86e32fb5808d4bb6f0bcd61e9b878d5ca582340301d69888af5adfee7

See more details on using hashes here.

File details

Details for the file siamang-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: siamang-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 216.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.1

File hashes

Hashes for siamang-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4a821ade0995e6878a702cf4a6faaa0e42c36aed8f7f8260e51d3766bb7c3c0b
MD5 e1ce8675a0f3ea204a3abe032f20cd2b
BLAKE2b-256 c78c12f755292044e53d6c94a4304c2a16a6c3d60629914d49800402f0fd528c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page