{"id":47844404,"url":"https://github.com/epiviz/epiviz.gl","last_synced_at":"2026-04-03T21:06:41.539Z","repository":{"id":41867375,"uuid":"375502378","full_name":"epiviz/epiviz.gl","owner":"epiviz","description":"Visualize genomic data using webgl and webworkers, in an effort to provide a fluid, high-performance user experience.","archived":false,"fork":false,"pushed_at":"2024-05-24T00:11:46.000Z","size":71357,"stargazers_count":10,"open_issues_count":19,"forks_count":5,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-10-31T14:21:06.657Z","etag":null,"topics":["epiviz","genomics-visualization","offscreencanvas","webgl","webworker"],"latest_commit_sha":null,"homepage":"https://epiviz.github.io/epiviz.gl/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/epiviz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-06-09T22:15:48.000Z","updated_at":"2024-08-27T23:24:10.000Z","dependencies_parsed_at":"2024-06-21T15:36:03.054Z","dependency_job_id":null,"html_url":"https://github.com/epiviz/epiviz.gl","commit_stats":{"total_commits":137,"total_committers":4,"mean_commits":34.25,"dds":"0.26277372262773724","last_synced_commit":"81aa0abc32b5d7ea4f3a94de4c882e3a9e78295c"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/epiviz/epiviz.gl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/epiviz%2Fepiviz.gl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/epiviz%2Fepiviz.gl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/epiviz%2Fepiviz.gl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/epiviz%2Fepiviz.gl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/epiviz","download_url":"https://codeload.github.com/epiviz/epiviz.gl/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/epiviz%2Fepiviz.gl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31377452,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-03T17:53:18.093Z","status":"ssl_error","status_checked_at":"2026-04-03T17:53:17.617Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["epiviz","genomics-visualization","offscreencanvas","webgl","webworker"],"created_at":"2026-04-03T21:06:40.955Z","updated_at":"2026-04-03T21:06:41.495Z","avatar_url":"https://github.com/epiviz.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# epiviz.gl\n\nThe `epiviz.gl` project is meant to visualize genomic data using webgl and webworkers, in an effort to give a fluid, high-performance user experience. Visualizations are defined via a declarative specification.\n\n**Live demo: https://epiviz.github.io/epiviz.gl/**\n\n# Install\n\nPackage is published to npm registry @ https://www.npmjs.com/package/epiviz.gl\n\n```\n$ yarn add epiviz.gl\n```\n\nor through `npm`\n\n```\n$ npm install --save epiviz.gl\n```\n\n## Usage\n\nSee [app/index.js](https://github.com/epiviz/epiviz.gl/blob/main/app/scripts/index.js) for a more comprehensive example.\n\n```javascript\nimport WebGLVis from \"epiviz.gl\";\n\nconst container = document.createElement(\"div\");\n\nconst visualization = new WebGLVis(container);\nvisualization.addToDom();\nvisualization.setSpecification({\n  defaultData: [\"day,price\", \"1,10\", \"2,22\", \"3,35\"],\n  tracks: [\n    {\n      mark: \"line\",\n      x: {\n        attribute: \"day\",\n        type: \"quantitative\",\n        domain: [1, 10],\n      },\n      y: {\n        attribute: \"price\",\n        type: \"quantitative\",\n        domain: [0, 40],\n      },\n      color: {\n        value: \"red\",\n      },\n    },\n  ],\n});\n```\n\n## Features\n\n### Zooming and Panning:\n\nAll visualizations automatically include zooming and panning:\n\n![zooming and panning](./docs/images/zooming.gif)\n\n### Selection:\n\nAll visualizations also include an ability to box or lasso select:\n\n![selection](./docs/images/selection.gif)\n\n### Unidirectional Selection:\n\nFor box-selections, `epiviz.gl` supports unidirectional selection in the plot, which restricts the selection to occur either horizontally or vertically based on mouse movement. This enhances box selection by allowing the user to select a region in a single direction. It is disabled by default and can be enabled by using the `setViewOptions` function.\n\n```javascript\nplot.setViewOptions({\n  uniDirectionalSelectionEnabled: true,\n}); // enables unidirectional selection\nplot.setViewOptions({\n  uniDirectionalSelectionEnabled: false,\n}); // disables unidirectional selection\n```\n\nBy setting the argument to true, the unidirectional selection will be enabled. Setting it to false will disable this feature.\n\n### Graph Zoom Control\n\nThe enhanced graph visualization tool now offers refined zoom controls, ensuring a precise and adaptable data representation. You can now set max zoom level allowed in the graph using the `setViewOptions` function.\n\n```javascript\nsetViewOptions({\n  maxZoomLevel: 0,\n});\n```\n\n### SVG Options\n\nYou can now specify the SVG options for the visualization using the `setSVGOptions` function. Default value is\n\n```javascript\n{\n  svgStyle: {\n    width: \"100%\",\n    height: \"100%\",\n    position: \"absolute\",\n    pointerEvents: \"none\",\n    overflow: \"visible\",\n  },\n  selectionMarkerAttributes: {\n    fill: \"rgba(124, 124, 247, 0.3)\",\n    stroke: \"rgb(136, 128, 247)\",\n    \"stroke-width\": \"1\",\n    \"stroke-dasharray\": \"5,5\",\n  },\n}\n```\n\nIt supports the following options:\n\n- `svgStyle`: An object containing the style attributes for the SVG element.\n- `selectionMarkerAttributes`: An object containing the style attributes for the selection marker.\n\n### Zoom Control Direction\n\nYou can now specify to use natural scrolling or inverted scrolling for zooming in and out using the `setViewOptions` function. Default value is `true`.\n\n```javascript\nsetViewOptions({\n  useNaturalScrolling: false,\n});\n```\n\n# Specifications\n\nDocumentation for specifications can be found in [docs/specification_doc.md](https://github.com/epiviz/epiviz.gl/blob/main/docs/specification_doc.md). Documentation for the specifications can be generated with [json-schema-for-humans](https://pypi.org/project/json-schema-for-humans/):\n\n```shell\ncd src/epiviz.gl/specification-validation\ngenerate-schema-doc visualization.json --config template_name=md\n```\n\n## Examples\n\n### Scatterplot\n\n**Specification:**\n\n```json\n{\n  \"xAxis\": \"center\",\n  \"yAxis\": \"center\",\n  \"defaultData\": \"path/to/tsne.csv\",\n  \"tracks\": [\n    {\n      \"mark\": \"point\",\n      \"x\": {\n        \"attribute\": \"x\",\n        \"type\": \"quantitative\",\n        \"domain\": [-10, 10]\n      },\n      \"y\": {\n        \"attribute\": \"y\",\n        \"type\": \"quantitative\",\n        \"domain\": [-10, 10]\n      },\n      \"color\": {\n        \"attribute\": \"sample\",\n        \"type\": \"categorical\",\n        \"cardinality\": 32,\n        \"colorScheme\": \"interpolateRainbow\"\n      },\n      \"opacity\": { \"value\": 0.05 }\n    }\n  ]\n}\n```\n\n![selection](./docs/images/scatterplot.gif)\n\n### Box Track\n\n**Specification:**\n\n```json\n{\n  \"margins\": {\n    \"left\": \"10%\"\n  },\n  \"labels\": [\n    {\n      \"y\": 0.05,\n      \"x\": -1.3,\n      \"text\": \"Box 1\",\n      \"fixedX\": true\n    }\n  ],\n  \"xAxis\": \"zero\",\n  \"yAxis\": \"none\",\n  \"defaultData\": \"path/to/box-track.csv\",\n  \"tracks\": [\n    {\n      \"tooltips\": 1,\n      \"mark\": \"rect\",\n      \"layout\": \"linear\",\n      \"x\": {\n        \"type\": \"genomicRange\",\n        \"chrAttribute\": \"chr\",\n        \"startAttribute\": \"start\",\n        \"endAttribute\": \"end\",\n        \"domain\": [\"chr2:3049800\", \"chr2:9001000\"],\n        \"genome\": \"hg38\"\n      },\n      \"y\": {\n        \"value\": 0\n      },\n      \"height\": {\n        \"value\": 10\n      },\n      \"color\": {\n        \"type\": \"quantitative\",\n        \"attribute\": \"score\",\n        \"domain\": [0, 8],\n        \"colorScheme\": \"interpolateBlues\"\n      }\n    }\n  ]\n}\n```\n\n![selection](./docs/images/box-track.gif)\n\n### Line Track\n\n**Specification:**\n\n```json\n{\n  \"defaultData\": \"path/to/box-track.csv\",\n  \"tracks\": [\n    {\n      \"tooltips\": 1,\n      \"mark\": \"line\",\n      \"layout\": \"linear\",\n      \"x\": {\n        \"type\": \"genomic\",\n        \"chrAttribute\": \"chr\",\n        \"geneAttribute\": \"start\",\n        \"domain\": [\"chr2:3049800\", \"chr2:9001000\"],\n        \"genome\": \"hg38\"\n      },\n      \"y\": {\n        \"type\": \"quantitative\",\n        \"attribute\": \"score\",\n        \"domain\": [0, 10],\n        \"colorScheme\": \"interpolateBlues\"\n      },\n      \"color\": {\n        \"type\": \"quantitative\",\n        \"attribute\": \"score\",\n        \"domain\": [0, 8],\n        \"colorScheme\": \"interpolateBlues\"\n      }\n    }\n  ]\n}\n```\n\n![selection](./docs/images/line-track.gif)\n\n### Arc Track\n\n**Specification:**\n\n```json\n{\n  \"xAxis\": \"zero\",\n  \"yAxis\": \"none\",\n  \"defaultData\": \"path/to/arcs.csv\",\n  \"tracks\": [\n    {\n      \"mark\": \"rect\",\n      \"x\": {\n        \"type\": \"genomicRange\",\n        \"chrAttribute\": \"region1Chrom\",\n        \"startAttribute\": \"region1Start\",\n        \"endAttribute\": \"regionEnd\",\n        \"domain\": [\"chr2:46000\", \"chr2:243149000\"],\n        \"genome\": \"hg19\"\n      },\n      \"y\": {\n        \"value\": 0\n      },\n      \"height\": {\n        \"value\": 10\n      },\n      \"color\": {\n        \"type\": \"quantitative\",\n        \"attribute\": \"value\",\n        \"domain\": [0, 60],\n        \"colorScheme\": \"interpolateBlues\"\n      },\n      \"opacity\": {\n        \"value\": 0.25\n      }\n    },\n    {\n      \"mark\": \"rect\",\n      \"x\": {\n        \"type\": \"genomicRange\",\n        \"chrAttribute\": \"region2Chrom\",\n        \"startAttribute\": \"region2Start\",\n        \"endAttribute\": \"region2End\",\n        \"domain\": [\"chr2:38000\", \"chr2:243149000\"],\n        \"genome\": \"hg19\"\n      },\n      \"y\": {\n        \"value\": 0\n      },\n      \"height\": {\n        \"value\": 10\n      },\n      \"color\": {\n        \"type\": \"quantitative\",\n        \"attribute\": \"value\",\n        \"domain\": [0, 60],\n        \"colorScheme\": \"interpolateReds\"\n      },\n      \"opacity\": {\n        \"value\": 0.25\n      }\n    },\n    {\n      \"mark\": \"arc\",\n      \"x\": {\n        \"type\": \"genomicRange\",\n        \"chrAttribute\": \"region1Chrom\",\n        \"startAttribute\": \"region1Start\",\n        \"endAttribute\": \"regionEnd\",\n        \"domain\": [\"chr2:38000\", \"chr2:243149000\"],\n        \"genome\": \"hg19\"\n      },\n      \"width\": {\n        \"type\": \"genomicRange\",\n        \"chrAttribute\": \"region2Chrom\",\n        \"startAttribute\": \"region2Start\",\n        \"endAttribute\": \"region2End\",\n        \"domain\": [\"chr2:38000\", \"chr2:243149000\"],\n        \"genome\": \"hg19\"\n      },\n      \"y\": {\n        \"value\": 0.1\n      },\n      \"height\": {\n        \"value\": 0\n      },\n      \"color\": {\n        \"type\": \"quantitative\",\n        \"attribute\": \"value\",\n        \"domain\": [0, 60],\n        \"colorScheme\": \"interpolateBuGn\"\n      }\n    }\n  ]\n}\n```\n\n![selection](./docs/images/arc-track.gif)\n\n# Development\n\n## Prepare the repository\n\n```shell\nyarn install\nyarn build\n```\n\n## Use the app\n\n```shell\nyarn start\n```\n\nThen navigate to `localhost:1234`\n\n## Build the package\n\n```shell\nyarn build-package\n```\n\nBe sure to commit the `dist` folder if changes made should be distributed.\n\n## Deploy to Github Pages\n\n```shell\nyarn deploy\n```\n\n## Run the tests\n\n```shell\nyarn start\n```\n\nVia command line:\n\n```shell\nnpx cypress run\n```\n\nVia GUI:\n\n```shell\nnpx cypress open\n```\n\nThis will open an additional window, where tests can be run on a live version of chrome.\n\n### Record the tests\n\nA method of doing of integration tests is to record the state of the application when it is working properly. Then, after making changes, compare the current state of the app and assert the state is equivalent. If it is not equivalent, either something is broken OR it is an anticipated change in which case it is justified to rerecord the tests and commit the change.\n\nCheck if current state matches recordings:\n\n```shell\nnpx cypress run --spec \"cypress/integration/expected-images.spec.js\"\n```\n\nRerecord the tests:\n\n```shell\nnpx cypress run --spec \"cypress/integration/record-tests.spec.js\" --env recording=true\n```\n\n## Development Notes\n\n### Rasterization\n\nEssentially, the project works by building all of the vertices for a visualization upfront. When visualizing data at a large scale, this can cause some vertices and their primitives (triangles, points, lines) to be VERY small which may cause them to not rasterize (be displayed) consistently. This is most apparent when flickering occurs by zooming/panning on genomic tracks or on a large matrix. This problem has been partially solved via the `SemanticZoomer`, which will render rects in a box track as lines and then as actual rectangles (in the form of two triangles) when zoomed in sufficiently. Altogether, this paragraph is mostly written to recommend developers to consult the [OpenGL ES 3 Specification](https://www.khronos.org/registry/OpenGL/specs/es/3.0/es_spec_3.0.pdf) when encountering these issues, particularly Chapter 3 (Rasterization) to gain some insight on how some vertices will be rendered.\n\n### Adding an Example\n\n1. Either add a .csv file to `app/examples/data` or specify inline data.\n2. Create an example in `app/examples/` which should follow this template:\n\n```javascript\nimport yourData from \"url:./data/your-data-if-you-put-it-here.csv\";\n\nexport default JSON.stringify(\n  {\n    defaultData: yourData, // or inline data\n    tracks: [\n      ...\n    ],\n  },\n  null,\n  2\n);\n```\n\n3. In `app/index.html` add an option to the `\u003cselect\u003e` element:\n\n```html\n\u003coption value=\"your-example\"\u003eYour Example\u003c/option\u003e\n```\n\n4. In `app/scripts/toolbar` import your example and add an entry to the exampleMap:\n\n```javascript\nimport yourExample from \"../examples/your-example\";\n\nconst exampleMap = new Map([\n  ...[\"your-example\", yourExample], // first element is the value attribute from the \u003coption\u003e element\n]);\n```\n\n5. If you feel that your example is instructive of some functionality of the library and would be worth becoming an integration test, go to `cypress/support/index.js` and add the value attribute from the `\u003coption\u003e` element to [`allPresetNames`](https://github.com/epiviz/epiviz.gl/blob/main/cypress/support/index.js#:~:text=const-,allPresetNames,-%3D%20%5B).\n\nIf your example is particularly long to render due to many vertices or a large amount of data, consider adding it to the [`longPresets`](https://github.com/epiviz/epiviz.gl/blob/main/cypress/support/index.js#:~:text=const-,longPresets,-%3D%20%5B%22tsne%22%2C%20%22tsne-10th) array.\n\n6. If you completed step 5, rerecord the tests, but be sure to **only commit only the test-image from your example (provided it is correct)**.\n\n```\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fepiviz%2Fepiviz.gl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fepiviz%2Fepiviz.gl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fepiviz%2Fepiviz.gl/lists"}