Skip to content

Commit d6d9ed8

Browse files
mickaphdclaude
andcommitted
Helix 1.0.0
Scientific data analysis, simplified: organize, analyze and visualize scientific data, from raw numbers to publication-ready graphs. A free, open-source and private alternative to GraphPad Prism for macOS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
0 parents  commit d6d9ed8

120 files changed

Lines changed: 43835 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/release.yml‎

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Builds Helix for a release: pushing a version tag (v1.1.0) runs the checks, then
2+
# builds the two DMGs (Apple Silicon, Intel) on GitHub's Macs and attaches them to a
3+
# draft release of that tag. Publishing the draft is what "Check for Updates" sees.
4+
name: Release
5+
6+
on:
7+
push:
8+
tags: ["v*"]
9+
10+
jobs:
11+
check:
12+
runs-on: macos-latest
13+
steps:
14+
- uses: actions/checkout@v5
15+
- uses: actions/setup-node@v5
16+
with:
17+
node-version: 24
18+
cache: npm
19+
- run: npm ci
20+
- run: npm run check
21+
- run: npm test
22+
23+
build:
24+
needs: check
25+
runs-on: macos-latest
26+
permissions:
27+
contents: write # to create the release and upload the DMGs
28+
strategy:
29+
matrix:
30+
target: [aarch64-apple-darwin, x86_64-apple-darwin]
31+
steps:
32+
- uses: actions/checkout@v5
33+
- uses: actions/setup-node@v5
34+
with:
35+
node-version: 24
36+
cache: npm
37+
- uses: dtolnay/rust-toolchain@stable
38+
with:
39+
targets: ${{ matrix.target }}
40+
- run: npm ci
41+
- uses: tauri-apps/tauri-action@v0
42+
env:
43+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
44+
with:
45+
tagName: ${{ github.ref_name }}
46+
releaseName: Helix ${{ github.ref_name }}
47+
releaseDraft: true
48+
tauriScript: npx tauri
49+
args: --target ${{ matrix.target }}
50+
releaseBody: |
51+
Download the DMG for your Mac: **aarch64** for Apple Silicon (M1 and later), **x64** for Intel.
52+
53+
Helix isn't signed by Apple yet, so macOS blocks it the first time. Open the DMG, drag Helix
54+
to Applications, open it once, then go to **System Settings › Privacy & Security** and click
55+
**Open Anyway**. [Why, step by step](https://github.com/mickaphd/Helix#first-launch-why-macos-asks-and-what-to-do)

‎.gitignore‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules/
2+
dist/
3+
src-tauri/target/
4+
src-tauri/gen/
5+
.DS_Store

‎FILE-FORMAT.md‎

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# The Helix project file (`.hlx`)
2+
3+
A Helix project is one plain-text JSON file (UTF-8). Any program can read or write
4+
it: your data is never locked into Helix.
5+
6+
## Promises
7+
8+
- **Old files always open.** Fields are only ever added in new versions, never
9+
renamed or removed.
10+
- **Newer files open too.** A version of Helix keeps the fields it doesn't know and
11+
writes them back when saving, so opening a newer file in an older Helix loses nothing.
12+
- **Forgiving reading.** Field names and choices are read whatever their case
13+
(`tableType`, `TableType`, `"XY"`). A value of the wrong type falls back to its
14+
default. A broken item is left out on its own, and Helix says so.
15+
- **Nothing about you.** The file holds the project only: no file paths, user
16+
names or app state.
17+
18+
## Layout
19+
20+
```json
21+
{
22+
"app": "helix",
23+
"schemaVersion": 1,
24+
"savedAt": "2026-09-24T12:00:00.000Z",
25+
"project": {
26+
"nodes": { "<id>": { … }, … },
27+
"rootOrder": ["<table id>", …],
28+
"childOrder": { "<table id>": ["<analysis or graph id>", …] },
29+
"activeNodeId": "<id>"
30+
}
31+
}
32+
```
33+
34+
- `app` is always `"helix"`. `schemaVersion` and `savedAt` are informative.
35+
- `nodes` holds every item, keyed by its `id`.
36+
- `rootOrder` lists the data tables in sidebar order; `childOrder` the analyses and
37+
graphs of each table. Items missing from these lists are shown after the others.
38+
- `activeNodeId` is the item shown when the file opens.
39+
40+
## Items
41+
42+
Every item has `id`, `type` (`"table"`, `"analysis"` or `"graph"`), `name`, and
43+
`parentId`: `null` for a table, the table's id for an analysis or a graph.
44+
45+
### Data table
46+
47+
```json
48+
{
49+
"id": "table_x1y2", "type": "table", "name": "Table 1", "parentId": null,
50+
"tableType": "grouped",
51+
"data": {
52+
"columns": ["Title", "A:Y1", "A:Y2", "B:Y1", "B:Y2"],
53+
"rows": [
54+
["Day 1", "10", "11", "14", "15"],
55+
["Day 2", "12", null, "18", "19"]
56+
],
57+
"groups": 2,
58+
"replicates": 2
59+
}
60+
}
61+
```
62+
63+
- `tableType`: `"column"`, `"xy"`, `"grouped"`, `"multiple"` (Multiple Variables)
64+
or `"contingency"`.
65+
- `columns`: the column names. The first is always the row-title column (`Title`);
66+
in an XY table the second is X.
67+
- `rows`: one list per row, one cell per column, as typed: text, or `null` for an
68+
empty cell. Numbers are written as text (`"2.5"`), exactly as entered. A row may
69+
be shorter than `columns`: the missing cells are empty.
70+
- A grouped table names its sub-columns `<group>:<sub-column>` (`"A:Y1"`) and gives
71+
`groups` and `replicates` (sub-columns per group).
72+
73+
Optional fields:
74+
75+
| Field | Meaning |
76+
| --- | --- |
77+
| `excluded` | Cells excluded from analyses and graphs, as `"row,column"` (0-based, column 0 is Title): `["2,1"]` |
78+
| `seriesColors` | A color per column (or per group of a grouped table): `{"Control": "red"}` |
79+
| `pointColors` | A color per cell, as `"column name#row"`: `{"Control#3": "green"}` |
80+
| `widths` | Column widths set by the user, in pixels, by column name |
81+
| `freezeTitle` | `true` keeps the Title column visible while scrolling |
82+
83+
Colors are `"blue"`, `"red"`, `"green"`, `"purple"`, `"orange"` or `"black"`.
84+
85+
### Analysis
86+
87+
```json
88+
{
89+
"id": "analysis_k3m4", "type": "analysis", "name": "Analysis 1", "parentId": "table_x1y2",
90+
"analysisType": "two-way-anova",
91+
"analysisParams": { "design": "ordinary", "posthoc": "tukey", "posthocTarget": "groups" }
92+
}
93+
```
94+
95+
An analysis stores what to compute, never its results: Helix computes them again
96+
from the table when the file opens, so results always match the data.
97+
`analysisParams` holds the choices made in the analysis's wizard (see
98+
`src/stats/types.ts`).
99+
100+
### Graph
101+
102+
```json
103+
{
104+
"id": "graph_p5q6", "type": "graph", "name": "Graph 1", "parentId": "table_x1y2",
105+
"graphType": "grouped-bars",
106+
"graphOptions": { "center": "mean", "error": "sem", "width": 640, "height": 460, … }
107+
}
108+
```
109+
110+
`graphOptions` holds every display setting (see `GraphOptions` in
111+
`src/store/types.ts`). A missing setting takes its default.

0 commit comments

Comments
 (0)