{"id":16381646,"url":"https://github.com/qwx9/strangepg","last_synced_at":"2025-10-26T10:31:20.282Z","repository":{"id":248720271,"uuid":"613520339","full_name":"qwx9/strangepg","owner":"qwx9","description":"strange pangenome and large graph visualization","archived":false,"fork":false,"pushed_at":"2024-10-24T12:58:19.000Z","size":3676,"stargazers_count":10,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-10-24T13:48:52.255Z","etag":null,"topics":["coarsening","external-memory","gfa-format","graph-visualization","indexing","large-graph","pangenome","pangenome-graph","scalability","visualization"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/qwx9.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2023-03-13T18:23:20.000Z","updated_at":"2024-10-24T12:58:22.000Z","dependencies_parsed_at":"2024-09-18T06:04:29.952Z","dependency_job_id":"b2b07242-8922-4b80-82ff-3ddc4e086bfc","html_url":"https://github.com/qwx9/strangepg","commit_stats":null,"previous_names":["qwx9/strangepg"],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qwx9%2Fstrangepg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qwx9%2Fstrangepg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qwx9%2Fstrangepg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qwx9%2Fstrangepg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/qwx9","download_url":"https://codeload.github.com/qwx9/strangepg/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238310322,"owners_count":19450839,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["coarsening","external-memory","gfa-format","graph-visualization","indexing","large-graph","pangenome","pangenome-graph","scalability","visualization"],"created_at":"2024-10-11T04:00:20.230Z","updated_at":"2025-10-26T10:31:20.269Z","avatar_url":"https://github.com/qwx9.png","language":"C","funding_links":[],"categories":["A list of software capable of analyzing mainly **eukaryotic** genomes for pangenomics.","Graph"],"sub_categories":[],"readme":"# Strange pangenome scale large graph visualization\n\nInteractive visualization of large genome graphs\nin [GFAv1 format](https://github.com/GFA-spec/GFA-spec/blob/master/GFA1.md)\nà la [Bandage](https://github.com/rrwick/Bandage).\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/zoom.png\"/\u003e\u003c/p\u003e\n\nNamed in reference to the Dr. Strangelove character\nin Stanley Kubrick's __Dr. Strangelove or: how I learned to stop\nworrying and love the bomb__ (1964),\nstrangepg provides an interactive visualization of bidirected and undirected graphs\nin a familiar force-directed layout but aims to scale to hundreds of millions of nodes and beyond.\nSuch is the size of pangenome graphs today,\nthe direct application for this tool.\nA big emphasis is placed on performance, reactivity and immediate feedback.\nWhile it currently supports only GFA files as input,\nit will in future be extended to support other formats (GraphML, DOT, Newick, etc)\nand types of trees (Newick for phylogenetic trees, etc.).\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/strangelove.png\"/\u003e\u003c/p\u003e\n\n_Note: this is a work in progress and under heavy development;\nsignificant or breaking changes happen all the time,\nbut always prefer building from source on the latest commit to\nother methods of installation in order to get the latest fixes and\nadditions. Git tags do **not** mark stable releases.\nPlease consider this to be a public beta of sorts\nand feel free to send bug reports, feature requests or comments.\nThanks!_\n\n## Table of contents\n\n- [Features](#features)\n- [TL;DR](#tldr)\n- [Installation](#installation)\n  + [Hardware requirements](#hardware-requirements)\n  + [Software requirements](#software-requirements)\n  + [Bioconda](#bioconda)\n  + [Linux](#linux)\n  + [MacOS](#macos)\n  + [Windows (MinGW64)](#windows-mingw64)\n  + [Windows (Cygwin)](#windows-cygwin)\n  + [Windows (WSL2)](#windows-wsl2)\n  + [OpenBSD](#openbsd)\n  + [9front](#9front)\n- [Usage](#usage)\n  + [Command-line options](#command-line-options)\n- [Layouting](#layouting)\n  + [Basic layouting](#basic-layouting)\n  + [Interaction](#interaction)\n  + [Loading from and saving to file](#loading-from-and-saving-to-file)\n- [Navigation](#navigation)\n  + [2D mode](#2d-mode)\n  + [3D mode](#3d-mode)\n  + [Selection](#selection)\n  + [Keyboard shortcuts](#keyboard-shortcuts)\n- [Graph manipulation](#graph-manipulation)\n  + [Examples](#examples)\n  + [Quick function reference](#quick-function-reference)\n- [Loading tags from CSV files](#loading-tags-from-csv-files)\n  + [Format notes](#format-notes)\n  + [On colors](#on-colors)\n  + [Color palettes](#color-palettes)\n- [Example applications](#example-applications)\n  + [Conga line: linear layout in GFA segments order](#conga-line-linear-layout-in-gfa-segments-order)\n  + [Random coordinates](#random-coordinates)\n  + [Linear layout using bubble id tags from gaftools](#linear-layout-using-bubble-id-tags-from-gaftools)\n  + [Coloring by path in rGFA files](#coloring-by-path-in-rgfa-files)\n  + [Rapid visual inspection of long linear segments](#rapid_visual_inspection_of_long_linear_segments)\n- [Known bugs](#bugs)\n- [Used and bundled alien software](#bundled)\n- [References](#references)\n\n\n## Features\n\n- Scaling to arbitrarily large graphs via coarsening; expanding/retracting parts of the graph on-demand with the mouse or object lookups and commands.\n- Layouting, rendering, drawing to the screen and handling user interface, file loading, graph manipulation\nall in separate and independent threads to reduce any waiting time to a minimum;\nimmediate output and interaction whenever possible.\n- Layouting is in real time and can be interrupted or influenced by moving nodes; it can be saved to or loaded from a file as a final result or an initial/reproducible state, hence guiding/improving previous layouts is possible; tags such as color can be changed at any time.\n- High performance graphics with modern and efficient renderer.\n- Some of the fastest GFA loading, by splitting topology from sequence/tags in separate passes;\nno assumptions about ordering, type of labels (strings or integers) or tags.\n- Console with an embedded graph manipulation language based on GFA tags.\n- Any tags, including user-defined ones, can be loaded from the GFA file,\nCSV files and in the prompt; automatic coloring if one is included.\n- Custom layouting (albeit currently primitive) via special tags and a generic force-directed layout in 2D or 3D space.\n- Written from scratch in C with almost no dependencies: easy and fast to build;\nhighly modular, extensible and cross-platform by design\n(note: code including bundled header-only libs is as portable as possible and supports multiple backends,\nbut it still needs to be actually ported).\n\nWithout coarsening, the current layouting algorithm while a parallelized and slightly improved version of the classic Fruchterman-Reingold __[1]__ force-directed algorithm,\nis still slow for 10k+ node graphs.\nIt will however be adequate for a coarsened graph since it only ever works on whatever is currently loaded;\nother algorithms (SGD2, FM3, etc.) could later be implemented as well.\nRight now, because layouting is parallelized, in real-time and can be interacted with,\nnot that much is left to make it more useful in practice.\n\nNear finished:\n- Offline coarsening and easy import/export of partial graph\n- Finish external memory implementation\n- Alignment visualization\n- Annotations, overlays\n- Path handling: highlighting, coloring\n- Manpage\n\nNear future:\n- Better generic layouts with hooks for user-specific scenarios: fix circular, add spherical, etc.\n- Better UI; macros as user-defined buttons\n- Newick format and phylogenetic tree layouts\n- Additional capabilities in the graph language\n\nFuture:\n- Edge bundling\n- Prettier graphs: node/line thickness and curvature\n- More user-friendly layout specification/implementation\n- Further graphics performance improvements if warranted\n- Multiple graph handling\n- GBZ support\n\nReleased under the terms of the MIT license.\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/darkmode2.png\"/\u003e\u003c/p\u003e\n\n\n## TL;DR\n\nMandatory arguments: a graph in GFA format,\nalways as the last command line parameter.\n\nLoad a gfa file named some.gfa:\n\n```bash\nstrangepg some.gfa\n```\n\nIncrease number of threads for layouting:\n\n```bash\nstrangepg -t 8 some.gfa\n```\n\nSelect a different layout type:\n\n```bash\nstrangepg -l 3d some.gfa\n```\n\nLoad a CSV file named some.csv:\n\n```bash\nstrangepg -c some.csv some.gfa\n```\n\nLoad layout from a file named some.lay\n(note: the layout file format is strangepg-specific):\n\n```bash\nstrangepg -f some.lay some.gfa\n```\n\nCompute a layout offline, ie. non-interactively and without graphics, writing snapshots to a file:\n```bash\nstrangepg -n some.lay some.gfa\n# resuming from snapshot:\nstrangepg -f some.lay -n some.lay some.gfa\n```\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/rna.png\"/\u003e\u003c/p\u003e\n\n## Installation\n\nCurrently Linux, macOS, Windows, OpenBSD and Plan9front\nare supported (x86, amd64, arm64).\nOther BSDs might work as well, but it's untested.\n\nInstallation can be done from source or via [bioconda](https://bioconda.github.io/).\nBinaries for Linux, macOS and Windows, probably out of date,\ncan be downloaded from the Releases github page as well.\n\n#### Hardware requirements\n\nstrangepg requires a graphics card with certain capabilities depending\non the backend which the system it will run on uses:\n\n- Linux: OpenGL 4.3+ or OpenGL ES 3.0+\n- Windows: DirectX 11+ support\n- macOS: Metal support\n\nGraphics cards from around 2013 on should all be compatible.\nIntel machines with Ivy Bridge or later HD Graphics work.\n\nFor arm64/aarch64, the Raspberry Pi 4 and later should work,\nbut so far it's unconfirmed.\nIt's confirmed to work on the Nintendo Switch (on Linux) however.\n\n#### Software requirements\n\n- Linux: OpenGL and X11 libraries, optionally EGL;\nthere's no native Wayland support yet\n- Windows: Windows 7 or later, but might work on XP\n- macOS: macOS 11 or later, but might work on OSX 10.11\n- OpenBSD: gmake, everything else is included\n- 9front: npe\n\nWindows binaries are cross-compiled on Linux.\nThere is currently no plan for adding MSVC support.\n\n#### Bioconda\n\nInstall conda, add the bioconda channel, then:\n\n```bash\nconda install strangepg\n```\n\nmacOS is supported for both Intel and Apple silicon; both should work in the same way,\nbut the former has received much less testing.\n\n#### Linux\n\nDepends on: mesa (GL), X11 (XCB, Xi, Xcursor and dependencies).\n\nInstalling dependencies (command line for Ubuntu systems, adapt for your own):\n\n```bash\napt install libbsd0 libgl-dev libglvnd-dev libglx-dev libmd0 libx11-dev libxau-dev libxcb1-dev libxcursor-dev libxdmcp-dev libxext-dev libxfixes-dev libxi-dev libxrandr-dev\n```\n\nFor arm64, you might also need `libegl-dev` and/or `libgles-dev`.\n\nBuilding and installing strangepg:\n\n```bash\ngit clone https://github.com/qwx9/strangepg\ncd strangepg\nmake -j install\n```\n\n_-j_ is an optional flag to enable parallel building using all available cores.\nThis installs the binary `strangepg`,\nby default in **\\$HOME/.local/bin**.\nIf this directory is not in your `$PATH` or a different installation directory is desired,\nuse the `PREFIX` make variable:\n\n```bash\nsudo make PREFIX=/usr/local install\n```\n\n**NOTE**: manual compilation with **clang is recommended** as it currently __may__ produce noticeably faster binaries.\n\nTo set the compiler, use the `CC` make variable:\n\n```bash\nmake CC=clang -j install\n```\n\nEGL can be enabled as well:\n\n```bash\nmake EGL=1 -j install\n```\n\nstrangepg can be also be built with OpenGL ES\n(implies EGL):\n\n```bash\nmake GLES=1 -j install\n```\n\nMultiple make variables may be specified at the same time.\n\nKnown to work on Ubuntu 22.04/24.04, Arch Linux and Void Linux.\n\n#### MacOS\n\nNative binaries using Metal can be built on both amd64 and arm64 machines.\nInstall the _Xcode Command Line Tools_, then clone the repository and build:\n\n```bash\nxcode-select --install\n\ngit clone https://github.com/qwx9/strangepg\ncd strangepg\nmake -j\nsudo make install\n```\n\nThis will install strangepg in `/usr/local/bin` by default.\nUse the `PREFIX` make variable to override it:\n\n```bash\nmake PREFIX=$HOME/.local install\n```\n\nMake sure that this new installation directory is in your `PATH`.\n\n#### Windows (MinGW64)\n\nNative Windows binaries using DirectX11 may be produced in a Linux environment\nby cross-compiling them with MinGW64.\n\nInstall `gcc-mingw-w64` (or equivalent),\nmake sure that `gcc-mingw-w64-x86-64-posix` is found,\nthen build with:\n\n```bash\nmake TARGET=Win64 CC=gcc-mingw-w64-x86-64-posix -j\n```\n\nInstall the `strangepg.exe` binary somewhere on your Windows system.\nSince there is no Windows-specific GUI yet, you will have to run it\nvia a terminal (Windows includes `cmd.exe` and Powershell)\nin the same way as for other systems.\n\n\n#### Windows (Cygwin)\n\nWindows binaries using OpenGL can also be built directly on Windows via Cygwin.\nTested only via MobaXterm (v24.2+, or any version with gcc 10.1+).\nTo build and run the Cygwin port, install the following packages\nand their dependencies:\n\n```bash\napt install make gcc-core libgl-devel libxcursor-devel libxi-devel\n```\n\nThe command may be `apt` or `apt-get` depending on version.\n\nThen run make as usual:\n\n```bash\ngit clone https://github.com/qwx9/strangepg\ncd strangepg\nmake -j install\n```\n\nThis will install the binaries in `/usr/bin` by default.\n\nIt is no longer possible to build static binaries with Cygwin.\nAs such, strangepg can only be run from within Cygwin's environment.\nIn other words, the .exe files built cannot be used outside of a Cygwin (or MobaXterm) terminal.\n\n#### Windows (WSL2)\n\nUse the same installation procedure as with MinGW to get a native binary\nusing DirectX 11.\nUntested, but should work.\n\nIf building the Linux version (X11+OpenGL), it may or may not work\n(in tests, the success rate on identical setups is so far circa 50%).\nThe installation procedure is identical as with Linux above.\nWhere it worked, WSL2 with Ubuntu 24.04 suffered very poor performance due to upstream bugs;\nfor the time being, if it does in fact work, prefer Ubuntu 22.04.\n\n#### OpenBSD\n\nAll required libraries and headers are already included in the distribution.\nThe only additional build dependency is `gmake`.\nI tried making a BSD makefile, but some things started to get complicated,\nand in the end I decided against wasting more time on that.\n\n```sh\npkg_add -a gmake\n```\n\nInstall with:\n\n```sh\ngmake -j install\n```\n\nThe default `PREFIX` is `$HOME/.local`,\ninstalling the binary in `$HOME/.local/bin`.\nChange this by adding a `PREFIX=` to your gmake command line.\n\nYou might want to enable SMT/Hyperthreading or lose much of the performance.\nCheck the [OpenBSD FAQ](https://www.openbsd.org/faq/faq10.html#SMT)\non how and why this is disabled by default.\n\n#### 9front\n\nBuild with _mk_ instead of _make_ in the usual manner.\nAdditionally requires [npe](https://git.sr.ht/~ft/npe); it's really only required to build khash.\nA better solution might exist since SDL2 isn't used at all.\n\nCurrently broken until the rendering component is brought up to date.\n\n\n## Usage\n\nstrangepg requires one input file as argument.\nIt currently only supports graphs in GFA format.\n\n```bash\nstrangepg file.gfa\n```\n\nSome test examples exist in the `test/` directory.\nFor example:\n\n```bash\nstrangepg test/02.gfa\n```\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/02.png\"/\u003e\u003c/p\u003e\n\n#### Command-line options\n\n```bash\n$ strangepg -h\nusage: ./strangepg [-AEHMWZbhqvw] [-f FILE] [-l ALG] [-n FILE] [-r FILE] [-s LEN WIDE] [-t N] [-c FILE] FILE [CMD..]\n-b             White-on-black color theme\n-c FILE        Load tags from csv FILE\n-f FILE        Load layout from FILE\n-h             Print usage information and exit\n-l ALG         Set layouting algorithm (default: pfr)\n-n FILE        Run layouting headless, saving to FILE periodically\n-q             Avoid printing messages to stdout\n-r FILE        Read coarsening table from FILE\n-s LEN WIDE    Set node length and width (max: 40.0 128.0, default: 1.0 1.0)\n-t N           Set number of layouting threads (1-1024, default: 4)\n-v             Print version and exit\n-w             Do not wait for all files to load to start layouting\n-A             Disable transparency (for performance)\n-E             Disable loading edge tags\n-H             Enable Hi-DPI mode\n-M             Enable 4x multisample anti-aliasing (MSAA)\n-Z             Minimize node depth (z-axis) offsets in 2d layouts\n-W             Do not suppress warning messages\nALG may be one of:\n fr            Parallelized variant of Fruchterman-Reingold (default)\n 3d            Experimental 3d version of the above\n```\n\nThe most important options are:\n\n- `-l ALG`: select the [layouting algorithm](#layouting) to use.\n- `-t N` sets the number of threads spawned for layouting.\nIt's recommended to set it to or near the number of all available cores.\nSingle-threaded layout algorithms will spawn them all but only use one of them.\nThe default should be good enough for graphs with more than 5-10 times the number of threads.\n\nOptional input files:\n\n- `-c FILE` [loads a CSV file](#loading-tags-from-csv-files).\nIt can be specified multiple times to load tags from more than one CSV file.\nEach file's changes are applied on top of previous ones.\n- `-f FILE` loads a layout previous saved to the file.\n- `-n FILE` shunts the entire graphics and UI stack and computes a layout.\nSuitable for running on headless (displayless) servers.\nSnapshots are written every 10 seconds;\nlayouting can be resumed from one by using `-f` flag.\n- `-r FILE` reads a previously computed coarsening table from file\ninstead of generating one at runtime.\nThe file format is not final.\n\nAdditional settings:\n\n- `-b` sets the obligatory dark theme.\n- `-q` disables echoing log messages to standard output.\n- `-E` disable loading edge tags: mostly for saving memory if those won't be used.\n- `-W` disables suppressing warnings:\nredundant edges and such are discarded, but printing warnings about this\nand some other cases is too common;\nthis prevents printing a ton of output that may not be relevant.\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/darkmode.png\"/\u003e\u003c/p\u003e\n\nDrawing options:\n\n- `-s` changes the dimensions of the nodes shown on screen.\nThe default is a compromise between edge length, visibility, and overall layout quality.\nFor bigger graphs, where one has to zoom out a lot, nodes become indistinguishable.\nUse this option to make nodes longer and/or wider.\nThis will affect new layouts somewhat,\nbut it's most effective when used in conjunction with `-f`.\n- `-Z`: by default, nodes are placed with some slight offset in the z axis,\nie. a distance away from the viewer,\nboth to avoid nodes overlapping and to improve graphics performance\nby allowing the GPU to perform z-buffering,\nbut it might look aesthetically unpleasing depending on the camera angle.\nThis option squishes nodes as close to each other as possible\nso as to appear as if there is no depth.\n\nAdditional graphics options\n\n- `-A`: disable transparency, trading visual quality for higher performance.\n- `-H`: enable hi-DPI mode for high resolution screens (macOS only).\n- `-M`: enable 4x multi-sample antialiasing (MSAA), which smooths lines\nand provides much more aesthetically pleasant visuals,\nat the cost of performance.\n\n#### Notes on GFA file format\n\nstrangepg makes no assumptions about the order of records within the file,\nwhether nodes are interspersed with edges or not,\nand what the nodes' labels look like (strings, integers, etc.).\nIt boasts one of the fastest and leanest GFA loading regardless,\nso no preprocessing is needed.\n\necords must conform to the GFAv1 standard; syntax errors are reported,\nbut parsing will continue if possible:\n\n- redundant L and S records are treated as duplicates and discarded\n(note, edge tags are currently unused).\nFor example:\n\n\tL\ta\t+\tb\t+\n\tL\tb\t-\ta\t-\n\nHere, `b-a-` is seen as a duplicate of `a+b+` since\nthe bidirectionality is already captured by `a+b+`.\nWhich of the duplicate edges is kept should be considered arbitrary,\nbut currently the reference edge is the one with the lowest ranked left-hand node.\n- the field separator is a single tab character;\ntwo successive ones are treated as an empty field.\n- nodes must have a non-empty sequence field which cannot exceed 128k characters.\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/ignored.png\"/\u003e\u003c/p\u003e\n\n## Layouting\n\nLayouting is performed and visualized in real time and in parallel.\nCurrently all available layout algorithms are based on a spring model force-directed approach,\nand are variations of the classic Fruchterman-Reingold algorithm __[1]__.\nThey are slow (improvements underway).\nParameters and heuristics are hand-tuned and may require further adjustment\nfor better results, or may warrant better approaches.\nBecause the initial state is random, results are different every time,\nand due to trade-offs for speed some may be better than others.\nThe real-time aspect of the application allows the user to easily restart layouting\nif the result so far is unsatisfactory, or to guide it by loading more information\nor moving nodes manually.\n\nHere the approach to custom or application-specific layouting is\nto combine a basic layout algorithm with specifying a partial or full initial state\nand/or adding constraints.\nFor example, a linear layout may be achieved by fixing the x coordinate of some or all nodes to one or more constant values.\n3D layouting works in the same way -- all layouts are actually in 3D space,\nbut 2D algorithms ignore the 3rd axis.\nReproducible layouting is possible by saving layouts to file and later loading them again.\n\nThe basic layouting algorithm serves as a backbone for more specific visualizations,\nchanging the type of geometry: circular, spherical, non-euclidean, etc.\nThese basic additional layouts are currently under development.\n\n**Note**: to accomodate for navigating in 3 dimensions rather than only 2,\n[navigation](#navigation) in 3D layouts is different.\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/layout.png\"/\u003e\u003c/p\u003e\n\n#### Basic layouting\n\nAvailable algorithms:\n- `-l fr`: the default, a slightly optimized and parallelized version\nof the original algorithm. The time complexity is essentially the same,\nso while it may run faster, it will not scale on its own for 10k node graphs and beyond.\nBecause it splits the graph across threads, it will produce nonsense results\nif the number of nodes is less than 2-3 times the number of threads.\n- `-l 3d`: same as `fr` but additionally using the z axis to layout in 3D.\n\nUse the [`-t` command line parameter](#usage) to change the number of threads\nused for layouting, 4 by default.\nSingle threaded algorithms will always only use one of them.\n\nDue to a bug, graphs are not locked to the center of the screen\nand may jump around during layouting if they're too small.\nIf there's nothing on the screen, try zooming out or re-layouting.\n\n#### Interaction\n\nThe following keyboard shortcuts are available:\n- `r`: restart layouting from scratch\n- `p`: stop layouting, or restart from current state\n- `Esc`: reset position on screen\n\nNodes may be dragged around with the mouse.\nMoving nodes does not fix their position to a constant position,\nand if layouting is currently underway it will influence the layout as a whole.\nNode positions are fixed via [tags](#graph-manipulation) instead.\n\nRestarting it is cheap; try it if the layout doesn't look good.\nIntermediate or final results can be saved to file,\nthen used as an initial state for another round of layouting.\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/small.png\"/\u003e\u003c/p\u003e\n\n\n#### Loading from and saving to file\n\nA pre-existing layout file may be loaded with the [`-f` command line parameter](#usage),\nirrespective of the selected layout algorithm.\nThe file format is binary and specific to strangepg.\nCurrently it's assumed that the layout file contains the exact same number\nof segments (S records) and in the __same order of appearance__\n(in either S or L records) as the originating GFA.\n\nThe current layout may be exported or imported at runtime\nwith the `exportlayout(\"file\")` and `importlayout(\"file\")` functions\n(see [Graph manipulation](#graph-manipulation)).\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/import.png\"/\u003e\u003c/p\u003e\n\n\n## Navigation\n\nMoving the graph around is done primarily with the mouse.\nThere are two styles of navigation, 2D and 3D, determined by the layout type.\n\n#### 2D mode\n\nIn 2D, the view (camera) can be moved vertically and horizontally (pan),\nor zoomed in and out (depth).\nThe maximal zoom level is right on top of the graph (ie. it cannot go behind it).\n\nControls:\n\n- Left click: select object (click on nothing to deselect).\nClick and hold to move a node around.\n- Shift (or Control) + left click on object: toggle selection for a single node\n- Right click (hold): pan the screen horizontally and/or vertically.\n- Left + right click (hold): zoom in by pulling in (drag mouse toward bottom right corner),\nor zoom out by pushing away (drag mouse toward upper left corner).\n- Scrollwheel: zoom in or out.\n- Control + right click (hold): zoom in or out.\n\nUse `Esc` to reset the view.\n\n#### 3D mode\n\nThe graph is locked to a center point, and the camera moves around it.\nSimply put, one rotates the graph around a center point as if it were a ball,\nand zooms in or out towards its center.\n\nControls:\n\n- Left click: select object (click on nothing to deselect).\nClick and hold to move a node around.\n- Shift (or Control) + left click on object: toggle selection for a single node\n- Right click (hold): rotate the graph around its center.\n- Left + right click (hold): zoom in by pulling in (drag mouse toward bottom right corner),\nor zoom out by pushing away (drag mouse toward upper left corner).\n- Scrollwheel: zoom in or out.\n- Control + right click (hold): zoom in or out.\n\nUse `Esc` to reset the view.\n\n\n#### Selection\n\nSelection is done either with the left mouse button, or through [commands](#graph-manipulation).\nClicking on a node selects it, deselecting everything else.\nClicking while holding the shift or control key toggles its selection,\nie. adds or removes it to the current selection.\nDragging a selection box selects all intersecting nodes\n(current implementation is [very limited](#known-bugs)).\nClicking on empty space deselects everything unless the shift or control key are held.\n\nNodes can be dragged around by clicking and holding the left mouse button.\nAn entire selection can be moved together also by holding the shift or control key\nwhile clicking and dragging in empty space.\n\n\n#### Keyboard shortcuts:\n\n- `Esc`: Reset view to initial position.\n- `a`: Toggle showing oriented nodes as arrows (oriented in read direction).\n- `p`: Pause/unpause layout (unpause = restart layout from current state).\n- `r`: Restart layouting from scratch.\n- `q`: Quit.\n- Arrow keys: move view by 1/3 of the screen up/down/left/right.\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/arrows.png\"/\u003e\u003c/p\u003e\n\nA status window currently labeled `Prompt`\npresents a text box to write [commands](#graph-manipulation) in,\nand shows selected and hovered over objects.\nCurrently, it only shows the name and length (nodes)\nor endpoints, orientation and overlap (edges),\nbut will be extended to show all of a node's tags.\n\nThe window can be moved around with the mouse,\ncollapsed by clicking the top right button,\nor resized by dragging the lower right corner.\nIt now also shows the last 3 status messages and command outputs,\nand has a collapsible message log widget for more.\nFeedback from [commands](#graph-manipulation) will appear here.\nError messages are drawn in red.\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/log.png\"/\u003e\u003c/p\u003e\n\n\n## Graph manipulation\n\nstrangepg embeds a simple graph manipulation language,\nwhich presents GFA tags as tables (associative arrays)\nand provides means to manipulate the graph and its\nproperties based on them.\nUsing it involves typing commands in the text prompt\nof the status window,\nor the terminal where strangepg was started.\n\nWhenever a node's tag is loaded from a GFA or CSV file or\non the prompt, the table with the same name is updated with\nthe new value.\nFor example, in GFA files the `LN` tag indicates the length of a\nnode's sequence.\nUpon loading the GFA file, each S line with a non-empty sequence\nand/or an `LN` tag will add an element to the `LN` table.\n`LN[name]` then stores the value for a node labeled `name` in the GFA.\nThis can be used for instance to change the color of a node\ndepending on some condition such as `LN[name] \u003c 1000`\n(more examples below).\n\nThe editing box is currently ugly and inconvenient due to limitations\nof the UI framework used, but this will be fixed soon.\nIt has supports mouse highlighting and selection\nand has clipboard support, with shortcuts Ctrl-C for copy and Ctrl-V for paste.\nFor X11, only the primary clipboard is currently used.\n\nThe language is a fork of [_awk_](https://awk.dev),\nhacked up to evaluate commands interactively.\nAny awk code valid within a pattern or function (ie. inside braces)\nis also valid here.\nCurrently, it's somewhat limited and a bit hacky, but it works.\nUsers may not define new functions yet.\nIt will be improved later on.\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/dbg.png\"/\u003e\u003c/p\u003e\n\n#### Examples\n\nColor a node in red:\n```awk\nCL[\"s1\"] = red\n```\n\nColor nodes with labels matching a regular expression:\n```awk\nCL[i ~ /chr13/] = green\n```\n\nColor nodes with sequence length \u003e 50:\n```awk\nCL[LN[i] \u003e 50] = darkgreen\n```\n\nColor nodes which have a certain tag defined:\n```awk\nCL[i in CN] = purple\n```\n\nColor every other node:\n```awk\nCL[i % 2 == 1] = orange\n```\n\nRecolor nodes:\n```awk\nCL[CL[i] == purple] = blue\n```\n\nAutocolor nodes based on the number of edges:\n```awk\ngroupby(\"degree\")\n```\n\nAutocolor nodes based on SN tag, excluding anything that doesn't start with \"chr\":\n```awk\ngroupby(\"SN\", \"^chr\")\n```\n\nAutocolor nodes using one of the predefined color palettes:\n```awk\ngroupby(\"degree\", \"\", \"set3\")\t# following previous examples\ngroupby(\"SN\", \"^chr\", \"set3\")\n```\n\nLook up a node by name, zooming in and centering on it if it exists:\n```awk\nfindnode(\"s14\")\n```\n\nSave current layout to file:\n```awk\nexportlayout(\"filepath\")\n```\n\nLoad existing layout from file:\n```awk\nimportlayout(\"filepath\")\n```\n\nRead in [a CSV file](#loading-tags-from-csv-files):\n```awk\nreadcsv(\"filepath\")\n```\n\nSee [Example applications](#example-applications) for more compliated examples,\nand [strawk.md](strawk.md) for a more detailed overview of strawk itself.\n\n\n#### Quick function reference\n\n```awk\ndeselect()                 empty selection\nfindnode(name)             zoom onto and select a node\ngroupby(tag, cond, map)    autocoloring by tag values, optionally only if matching cond and/or with a named colormap\nrefresh()                  refresh screen\nselectall()                select all nodes (currently won't update screen)\nselectnode(name)           select node by name (currently won't update screen)\nquit()                     give up\n```\n\nLayouts:\n\n```awk\nexplode(Δ)                 add a random amount of jitter in [-Δ/2,+Δ/2] to the selected nodes, default Δ=8.0\n```\n\nCoarsening:\n\n```awk\ncollapse()                 collapse selection or everything if empty\nexpand()                   expand selection or everything if empty\n```\n\nFiles:\n\n```awk\nexportcoarse(path)         export coarsening table to file (experimental)\nexportgfa(path)            export gfa file (experimental)\nexportlayou(path)          export layout to file\nexportsvg(path)            export a render of the entire graph to an svg file (experimental)\nimportlayout(path)         import layout from file\nreadcsv(path)              read a csv file\nreadctab(path)             import coarsening table from file (experimental)\n```\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/explode.png\"/\u003e\u003c/p\u003e\n_explode() function._\n\nPaths are absolute or relative to the current working directory.\n\n\n## Loading tags from CSV files\n\nCSV files can be loaded at start up with the `-c` flag or at runtime\nto feed or modify tags for existing nodes.\nThe '-c' flag may be used multiple times to load more than one CSV file at startup.\n\nThe first column is always reserved for node labels, and all subsequent columns are tags values.\nThe first line must be a header specifying a tag name for each column.\n\nFor example:\n```\nNode,CN,CO,CL\nutig4-142,1,55231,purple\nutig4-143,0,53,red\n...\n```\n\nThe name of the first column does not matter.\nThe `CL` tag is used as a node's color and can thus also be set in this way.\n`Color` can also be used (in any casing).\nNode labels must refer to existing nodes from the input GFA file.\nAny tag (including new ones) except LN can be set in this way.\n\nSpaces within tag names are replaced by underscrores.\nA column name _Copy number_ would thus create the tag `Copy\\_number`.\n\nA CSV file may be loaded at runtime with the `readcsv(\"file.csv\")` command\n(see [Graph manipulation](#graph-manipulation)).\n\n**Loading multiple CSV files one after the other is allowed.**\nIn other words, variables such as color are not reset between files.\nCSV files thus needn't be merged together.\nIt cannot be undone however,\nbut once colors are known, selections can be made based on them.\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/basic.png\"/\u003e\u003c/p\u003e\n\n*Important:* tags are set to a specific type based on the first values encountered:\ninteger, floating point (both 64-bit), or string.\nSetting a floating point value on an integer type will implicity truncate it.\nConversions between strings and numeric types are currently disallowed.\nTo check for an _unset_ value (or NA), use the strawk `in` operator: `if(!(label in tag)) print label`.\n\n#### Format notes\n\nThe accepted format here is more stringent than usual.\nThe implementation is not localized, ie. commas are always field separators.\nThere are no escape sequences or special quoting rules, ie. quotes are not special characters.\nLine breaks within a field are disallowed.\nLines must be terminated with a new line (LF) character, ie. the return character (CR) is not handled.\nSpaces in the column names of header are allowed;\nextra spaces preceding or following each name are stripped.\nEach line must have the same number of fields as the header, but fields may be empty.\n\n#### On colors\n\nColors are represented as integers in RGBA32 format.\nSome names such as `red`, `darkblue` or `palegreen` are predefined (see [strawk document](strawk.md) for a list).\nIn strawk, the alpha component (transparency) is 0 by default.\nFor example, the color `orange` is set to `0xFF7F0000` (in RRGGBBAA format in hexadecimal).\nThe actual alpha value depends on the theme, but it can be overridden by setting a value different than 0.\nFor example:\n\n```awk\nred = 0xff00007f      # 50% opacity\nmycolor = 0x123456ff  # full opacity\n```\n\nColors in CSV files don't need to specify an alpha value.\nThey can be HTML colors like `#FF0000`,\nhexadecimal ones like `0xff0000`,\nand symbolic ones like `blue` or `purple`.\nHTML colors with an alpha value will keep it.\nOnce loaded in strawk, they will be represented in the above format.\n\nFor example, with the following CSV file:\n\n\tName,CL\n\ts1,blue\n\ts2,#1F78B4\n\ts3,#1F78B4FF\n\ts4,#1f78b4ff\n\ts5,0x1f78b4ff\n\ts6,0x1f78b400\n\nNodes `s1` to `s6` will all have the same color and transparency,\nexcept `s3` to `s5` are set to full opacity.\n\nThe same rules apply to GFA file tags.\n\nA special `translucent` color is provided for near-transparency.\nIt's used in `groupby()` to mask nodes that don't match a condition.\nIts default value is `0xeeeeee30`.\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/colors.png\"/\u003e\u003c/p\u003e\n\n\n#### Color palettes\n\nSeveral color palettes have been defined, based on Color Brewer.\nFor now they are limited to use with `groupby`.\nTheir values can be changed freely.\nUsers can define their own palettes.\nThey must simply be arrays of integers indexed from 0 to the number of colors - 1,\nin the same format as discussed above (with the alpha byte set to 0).\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/cmap0.png\"/\u003e\u003c/p\u003e\nDefault (`defgrp`).\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/cmap4.png\"/\u003e\u003c/p\u003e\n`set1`.\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/cmap3.png\"/\u003e\u003c/p\u003e\n`set2`.\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/cmap2.png\"/\u003e\u003c/p\u003e\n`set3`.\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/cmap1.png\"/\u003e\u003c/p\u003e\n`spectral`.\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/cmap5.png\"/\u003e\u003c/p\u003e\n`paired`.\n\n\n## Example applications\n\nOne of the goals of strangepg is to enable experimentation with layouting.\nCurrently, the default layouting algorithm honors a set of tags\nwhich set initial coordinates and/or fixes them (makes them unmovable).\n\n- **x0:f:xpos**\tset initial x coordinate in layout\n- **y0:f:ypos**\tset initial y coordinate in layout\n- **fx:f:xpos**\tforce immutable x coordinate\n- **fy:f:ypos**\tforce immutable y coordinate\n\nThey can be loaded from the GFA itself, from CSV or live by using the prompt.\n\nSee [strawk.md](strawk.md) for a more detailed overview.\n\n#### Conga line: linear layout in GFA segments order\n\n```awk\nfx[1] = 8 * node[i]\nfy[1] = 0\n```\n\n#### Random coordinates\n\n```awk\nfx[1] = 8 * 1024 * node[i]\nfy[1] = 8 * 1280 * rand()\n```\n\n#### Linear layout using bubble id tags from [gaftools](https://github.com/marschall-lab/gaftools)\n\n```awk\nmin = 999999\nmax = -999999\nfor(i in BO) if(BO[i] \u003c min) min = BO[i]; if(BO[i] \u003e max) max = BO[i]\nfx[CL[i] == orange] = 8 * (BO[i] - min - (max - min) / 2)\nfy[CL[i] == orange] = 0\nx0[CL[i] != orange] = 8 * (BO[i] - min - (max - min) / 2)\ny0[CL[i] != orange] = 2 - 4 * rand()\n```\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/bo.png\"/\u003e\u003c/p\u003e\n\n\n#### Coloring by path in rGFA files\n\nThe following uses the HPRC 1.0 minigraph CHM13 graph as an example.\nUse `groupby` to autogroup based on the values of the SN tag.\nThe second argument is a regular expression.\nOnly values matching it will be used, everything else is set to a `translucent` color.\nBy combining these, we can color only chromosome nodes.\nThe third argument is the name of a color palette.\nDo 4 rounds of coarsening first to reduce the size of the graph.\n\n```awk\nfor(i=1; i\u003c=4; i++) collapse()\ngroupby(\"SN\", \"^chr\", \"paired\")\n```\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/sn.png\"/\u003e\u003c/p\u003e\n\nWith one global `expand` operation:\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/sn2.png\"/\u003e\u003c/p\u003e\n\n\n#### Rapid visual inspection of long linear segments\n\nThe objective is to visually verify the absence of certain nodes within a region of interest.\nOther existing programs may make it difficult to accomplish due to a limited interface,\nor a layout producing too many overlaps, masking potential sites.\nstrangepg attempts to maintain some separation between nodes\nand offers a relatively simple solution with partial 3d layouting.\nThe layout is partially computed on a server with 64 cores,\nie. run once for a limited period of time.\nA csv file colors the region in yellow (#fbff00) and critical nodes in red (#ff0000).\nNodes are enlarged to make them easier to distinguish and all nodes not in the csv\nare colored in light gray.\nThe random colors and default node dimensions make it difficult to see what is happening,\nbut we can use a simple command to color all nodes not mentioned in the CSV file.\nWe'll append the command to the command line so as to not have to type it in the prompt;\nthis approach works well with scripts.\n\n```bash\nstrangepg \\\n        -s 8 8 \\\n        -M \\\n        -l 3d \\\n        -c ~/chr17_16823490-18384190_0.csv \\\n        -f chr17_16823490-18384190_10000.gfa \\\n        chr17_16823490-18384190_10000.gfa \\\n        'CL[CL[i] != 0xfbff0000 \u0026\u0026 CL[i] != 0xff000000] = 0xeeeeee10'\n```\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/yellow.png\"/\u003e\u003c/p\u003e\n\n\n## Known bugs\n\nMajor bugs:\n- Coarsening does not update strawk tables.\n- Layouting is slow and larger graphs show up as a ball at the center of the screen:\nthis is the initial state for any of the layouting algorithms,\nbut because it is shown in real time and the algorithms currently used being slow\n(improvements underway), the initial plot looks... underwhelming.\n- Graphs are not re-centered or locked to the center of the screen;\neither the algorithm should compensate for random movements beyond what the FR\nalgorithm does, or it should be translated to the center of the screen, or\nthe screen to the center of the graph.\n- Edges are ugly and are 1 pixel-wide lines, making them difficult to select.\n- Self-edges aren't drawn well. An `a+a+` edge will appear as a line inside the node,\nand a `a+a-` edge will be a dot at the end of the node (in read direction).\n- Edge objects and adjacencies in general can't really be manipulated through strawk\n- OpenGL ES: mouse picking code doesn't work and crashes with an assertion failure;\nnot sure what and how to fix.\n- Broken on WSL2 on some machines; the Windows native binary can still be used\ndirectly through the terminal emulator.\n- DirectX: mouse picking code is buggy and can crash the application near startup.\n- Fatal errors in strawk are not always handled gracefully and may result in broken state.\n\nLess major bugs:\n- Blinking nodes due to renderer's lack of reordering of nodes for correct alpha blending.\n- \"Spinning\" nodes due to an edge case in average angle computation.\n- The selection box is a kludge and is stupidly resource-heavy.\n- The selection box currently only works in one direction.\n- The renderer is fairly efficient, but it could be made an order of magnitude faster.\n- (pfr*) Layouting ignores nodes with no adjacencies; would be better to\nplace them on better fixed locations as well.\n- The text boxes suck, a lot. Nuklear doesn't handle edit boxes much.\n- ... and many more!\n\n\n## Used and bundled alien software\n\nData structures:\n- [khashl](https://github.com/attractivechaos/khashl),\nmodified to use readers-writer locks for concurrent access\n- [chan](https://github.com/tylertreat/chan)\n\nLinux graphics:\n- sokol_gfx, sokol_app, sokol_nuklear and glue code from [sokol](https://github.com/floooh/sokol)\n- [HandmadeMath](https://github.com/StrangeZak/Handmade-Math)\n- [Nuklear](https://github.com/Immediate-Mode-UI/Nuklear)\n\nUsed but not bundled:\n- GNU Bison or Plan9 yacc(1) for strawk\n\nstrawk is based on [onetrueawk](https://github.com/onetrueawk/awk).\n\n\u003cp align=\"center\"\u003e\u003cimg src=\".pics/space.png\"/\u003e\u003c/p\u003e\n\n_Soon, deathmatching in graph space_\n\n\n## References\n\n[1] Fruchterman, Thomas M. J.; Reingold, Edward M. (1991), \"Graph Drawing by Force-Directed Placement\", Software: Practice and Experience, 21 (11), Wiley: 1129–1164, doi:10.1002/spe.4380211102, S2CID 31468174\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqwx9%2Fstrangepg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fqwx9%2Fstrangepg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqwx9%2Fstrangepg/lists"}