{"id":23270306,"url":"https://github.com/amari-calipso/sorting-visualizer","last_synced_at":"2025-08-21T03:31:49.801Z","repository":{"id":142149545,"uuid":"447679111","full_name":"amari-calipso/sorting-visualizer","owner":"amari-calipso","description":"A sorting visualizer written in opal","archived":false,"fork":false,"pushed_at":"2025-05-18T18:38:25.000Z","size":860,"stargazers_count":6,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-18T19:34:56.820Z","etag":null,"topics":["array-manipulations","array-visualizer","cython","python","python3","sorting","sorting-algorithms","sorting-visualization"],"latest_commit_sha":null,"homepage":"","language":"Opal","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/amari-calipso.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":"2022-01-13T16:53:09.000Z","updated_at":"2025-05-18T18:38:29.000Z","dependencies_parsed_at":"2023-12-06T20:26:39.706Z","dependency_job_id":"be8713c4-5d47-4ce3-9c88-79a726a052d0","html_url":"https://github.com/amari-calipso/sorting-visualizer","commit_stats":null,"previous_names":["amari-calipso/sorting-visualizer"],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/amari-calipso/sorting-visualizer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amari-calipso%2Fsorting-visualizer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amari-calipso%2Fsorting-visualizer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amari-calipso%2Fsorting-visualizer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amari-calipso%2Fsorting-visualizer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/amari-calipso","download_url":"https://codeload.github.com/amari-calipso/sorting-visualizer/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amari-calipso%2Fsorting-visualizer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271420468,"owners_count":24756568,"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","status":"online","status_checked_at":"2025-08-21T02:00:08.990Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["array-manipulations","array-visualizer","cython","python","python3","sorting","sorting-algorithms","sorting-visualization"],"created_at":"2024-12-19T18:49:29.654Z","updated_at":"2025-08-21T03:31:49.794Z","avatar_url":"https://github.com/amari-calipso.png","language":"Opal","funding_links":[],"categories":[],"sub_categories":[],"readme":"﻿# Sorting Visualizer\n## NOTE: This project is no longer maintained, check out https://github.com/amari-calipso/UniV\n\n A sorting algorithms visualizer written in opal\n\nto run from source, open or compile `SortingVisualizer.opal` using the opal compiler.\n\nto build a release, use `opal release build.iproj` or `opal release build_dev.iproj` depending on which version you want to build.\n\nhere you can find a video about the program: https://youtu.be/iZjOP4Htz3c\n\n# Installation\nTo properly run the visualizer from source, you will need to install the Python modules listed in `requirements.txt`.\n\nTo use render mode, ffmpeg needs to be properly installed on your system.\n\n# Usage\nThe visualizer consists of three main menus:\n- Run sort: Lets you pick all settings to run a specific sort and visualize it;\n- Run all sorts: Lets you pick a distribution, shuffle, and visual style to run every sort on. This is the mode that's used to create videos such as [the example](https://youtu.be/iZjOP4Htz3c);\n- Threads: \n\t- Threads are sequences of actions that are defined through the thread builder, useful to make videos about a certain topic or algorithm. The \"Threads\" menu has two submenus:\n\t\t- Run threads: Runs a thread that's been previously created;\n\t\t- Thread builder: Enables the user to create threads;\n\nWhile an algorithm is running, the \"S\" key on your keyboard can be pressed to skip it.\n\n# Settings\n### Show text\nIf set to `False`, the visualizer will hide the text in the top left corner.\n### Show auxiliary array\nIf set to `False`, auxiliary arrays will not be visualized.\n### Show internal information\nIf set to `True`, additional information about the visualizer's state will be visualized in the top left text.\n### Render mode\nIf set to `True`, the visualizer will generate videos instead of visualizing algorithms in real-time. A preview of the video will be visualized on the screen while it's being made, at a lower framerate.\n### Lazy auxiliary visualization\nThe visualizer checks if the auxiliary array changed in size, or its maximum element changed, in specific scenarios, so that the visual can re-compute its data accordingly. If lazy auxiliary visualization is set to `True`, these checks are disabled, that is, the visualizer will assume the maximum element of the auxiliary array and its length are constant.\n### Lazy rendering\nReal-time visualization will try to use `fast` or `selective` variants of the given visual style for performance reasons in favorable scenarios, while render mode always uses standard variants, which are higher quality, but slower in those same scenarios. If lazy rendering is set to `True`, the visualizer will try to use `fast` or `selective` variants of visual styles for render mode too. This does not result in quality loss in certain cases, and can be used for quick videos.\n### Render bitrate (kbps)\nSets the output video bitrate (in kbps) for videos generated through render mode.\n### Render profile\nAllows the user to select one of the different encoding profiles to be used with ffmpeg in render mode. Such profiles are found in the `profiles` folder, and can be added and customized dynamically. Note that some of these profiles are platform or hardware dependent, so they're not guaranteed to work. In case an incompatible profile or invalid options have been provided through the selected profile, or something went wrong during the rendering process, the visualizer will report that ffmpeg exited with a nonzero return code.\n\n# Creating Python extensions\nTo do Python development to add modules for the visualizer, it's sufficient do download a release version and add your modules in the `external` folder. Development releases (marked as `dev`) are available and provide Python definitions for the program's API.\n\nWhen adding modules to the visualizer dynamically (through the `external` folder), you can use the Python definitions like this:\n```py\nfrom typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n\tfrom SortingVisualizer import *\n```\n\nThis way, your IDE will be able to typecheck the program and give you proper hints, while not executing the import when the code is actually ran.\n\nIf you're working directly with the source code, you can create the Python definitions yourself. To do this, it's sufficient to compile `SortingVisualizer.opal` in Python mode, like this:\n```\nopal pycompile SortingVisualizer.opal\n```\n\nNote that all visual styles and sound systems added through the `external` folder have to be marked as `@SortingVisualizer.external` for them to be recognized. For example:\n```py\n@SortingVisualizer.external\nclass MyVisual(Visual):\n\t...\n\n@SortingVisualizer.external\nclass MySound(Sound):\n\t...\n```\n\nOther types of extensions don't require this. \n\nIf you are writing code that will be embedded in the compiled visualizer (that is, not through the `external` folder), add these lines on top of your Python code:\n```py\n#opal$if False\nfrom SortingVisualizer import *\n#opal$end\n```\n\nThese will import the visualizer normally when you're doing development, since Python will see the `#opal` lines as comments, but ignore the import when compiling the whole project, since opal will treat those lines as precompiler instructions.\n\n# The API\n## Array operations\nThe array provided to the algorithms is filled with instances of the `Value` class. A `Value` contains a numeric value that actually gets sorted; an index, which is used for visualization and tracking of the value inside the array; a stability index, which is used for stability checking; an `aux` flag, that marks whether the `Value` is contained in the main array, or an `aux`iliary one. An instance of `Value` acts as any sortable data type, but it will automatically track elapsed time and display highlights for the current operation. The `Value` class provides the following methods:\n- `copy() -\u003e Value`: creates a copy of the `Value` without tracking time, statistics or highlighting;\n- `read() -\u003e Value`: like `copy` but it tracks time and statistics and highlights the `Value`'s index;\n- `noMark() -\u003e Value`: creates a copy of the `Value` without the index field, causing it not to get highlighted;\n- `getInt() -\u003e int`: returns the integer value of the `Value` without tracking time, statistics or highlighting;\n- `readInt() -\u003e int`: like `getInt` but it tracks time and statistics and highlights the `Value`'s index;\n- `readDigit(digitIdx: int, base: int) -\u003e int`: returns the given `Value`'s digit in the given base;\n- `readNoMark() -\u003e Value, int`: like `read`, but the returned value becomes \"invisible\" (that is, it doesn't get highlighted anymore). The `Value`'s index is returned so it can be restored later;\n- `write(other: Value | int)`: writes a `Value` to that `Value`'s position;\n- `writeRestoreIdx(other: Value | int, idx: int)`: like `write`, but it allows to restore an index. Used in conjunction with `readNoMark`;\n- `swap(other: Value)`: swaps with another `Value`.\n## Manually working with statistics\nTo manually increment, decrement, or edit statistics, you can access:\n- `sortingVisualizer.reads`;\n- `sortingVisualizer.comparisons`;\n- `sortingVisualizer.writes`;\n- `sortingVisualizer.swaps`.\n\nComparisons and reads are tied together, like swaps and writes. That is, if you add one swap, two writes will be added. \nThe visualizer also provides a method to time operations manually:\n- `sortingVisualizer.timer(sTime: float)`\n\nIt's used in conjuction with `default_timer()` like this:\n```\nnew float sTime = default_timer();\n# perform an operation here\nsortingVisualizer.timer(sTime);\n```\n## Manual writes\nFor array operations that don't work properly with the `Value` class, the visualizer provides two methods that automatically keep track of statistics and time:\n- `sortingVisualizer.write(array: list, i: int, val)`;\n- `sortingVisualizer.swap(array: list, a: int, b: int)`.\n## Manual highlights\nThe visualizer provides twelve methods for manual highlighting:\n- `sortingVisualizer.highlight(index: int, aux: list | None = None)`: highlights the given index;\n- `sortingVisualizer.multiHighlight(indices: list[int], aux: list | None = None)`: highlights a list of indices.\n- `sortingVisualizer.highlightAdvanced(index: HighlightInfo)`: highlights a `HighlightInfo` object;\n- `sortingVisualizer.multiHighlightAdvanced(indices: list[HighlightInfo])`: highlights a list of `HighlightInfo` objects;\n- `sortingVisualizer.queueHighlight(index: int, aux: list | None = None)`: adds the given index to the list of highlights that will be visualized with the next update;\n- `sortingVisualizer.queueMultiHighlight(indices: list[int], aux: list | None = None)`: like `queueHighlight`, but accepts a list of indices;\n- `sortingVisualizer.queueHighlightAdvanced(index: HighlightInfo)`: like `queueHighlight`, but uses a `HighlightInfo` object;\n- `sortingVisualizer.queueMultiHighlightAdvanced(indices: list[HighlightInfo])`: like `queueHighlightAdvanced`, but accepts a list of `HighlightInfo` objects;\n- `sortingVisualizer.markArray(id: Any, index: int, aux: list | None = None, color: tuple[int, int, int] | None = None)`: marks the array persistently until the end of the current algorithm. `id` can be any hashable object;\n- `sortingVisualizer.markArrayAdvanced(id: Any, index: HighlightInfo)`: like `markArray`, but uses a `HighlightInfo` object;\n- `sortingVisualizer.clearMark(id: Any)`: clears a mark precedently set through `markArray`, given its `id`. Throws a `VisualizerException` if the `id` of the given mark does not exist;\n- `sortingVisualizer.clearAllMarks()`: clears all marks set through `markArray`.\n\nAn `HighlightInfo` object contains more information for each highlight. Internally, the visualizer also generates those when calling the non-advanced variants of highlights. They are composed like this:\n`record HighlightInfo(index: int, aux: list[Value] | None = None, color: tuple[int, int, int] | None = None, silent: bool = False);`\n- `index`: contains the array index to be highlighted;\n- `aux`: stores a pointer to the auxiliary array where the highlight came from. If `None`, the highlight came from the main array;\n- `color`: the color that the highlight will have. If `None`, the color will be set to the default highlight color for the current visual style;\n- `silent`: whether the highlight should not produce sound. Useful for color coding.\n\nFor dynamic color coding, the visualizer provides a `sortingVisualizer.getColor(n: int) -\u003e tuple[int, int, int]` method, which assigns a color dynamically to a number, as a color id.\n\nQueued highlights are stored in a list (`sortingVisualizer.highlights`) that can be edited manually for advanced operations. In a multithreaded context, it should be edited while the relative lock (`sortingVisualizer.highlightsLock`) is acquired. This is done automatically in the `queue` methods.\n\n## Working with auxiliary arrays\nTo create a new array, the visualizer provides  `sortingVisualizer.createValueArray(length: int) -\u003e list[Value]`, which is pre-filled with already configured `Value`s. This also automatically shows the array in the visualizer. To remove an array from visualization, you can use `sortingVisualizer.removeAux(array: list)`. In case the `createValueArray` function is not used to create an array, but you still want to visualize it, you can use `sortingVisualizer.addAux(array: list)` and, if it's not an array of values, you can provide adaptation functions using `sortingVisualizer.setAdaptAux(fn, idxFn = None)`: \n- `fn(arrays: list[list]) -\u003e list[Value]`: set this function to properly convert all the auxiliary arrays in a list of `Value`s that the visualizer can work with;\n- `idxFn(idx: int, aux: list) -\u003e int`: this function can be set to adapt the highlighted indices to the resulting `list[Value]` for visualization purposes.\n\nYou can mark arrays as not containing elements from the original array by using `sortingVisualizer.setNonOrigAux(*arrays)`, this will allow for better visualizations. Note that this method automatically marks the algorithm as [using dynamic aux](#adding-new-shuffles) since this requires dynamic computations.\n\nDeleting an array, or making it go out of scope, while the array is being visualized, will automatically remove the array from the visualization thanks to the dedicated garbage collector.\n\nYou can also disable highlights from a given array using the `sortingVisualizer.setInvisibleArray(array: list[Value])` method.\n## Using rotations and pivot selections provided by the visualizer\nTo fetch a specific rotation or pivot selection algorithm, `sortingVisualizer.getPivotSelection(id: Optional[int] = None, name: Optional[str] = None)` and `sortingVisualizer.getRotation(id: Optional[int] = None, name: Optional[str] = None)` can be used. You can either pass the name of the algorithm to the function, like this:\n```\nnew auto myRotation = sortingVisualizer.getRotation(name = \"Gries-Mills\").indexedFn;\n```\n... or you can pass the ID of the algorithm of choice, mostly useful in combination with a user selection, for example:\n```\nnew auto myPivotSelection = sortingVisualizer.getPivotSelection(\n\tid = sortingVisualizer.getUserSelection(\n\t\t[p.name for p in sortingVisualizer.pivotSelections],\n\t\t\"Select a pivot selection algorithm: \"\n\t)\n);\n```\n\n### Rotations\nRotations provide two modes: indexed, and lengths. Indexed mode uses these types of arguments:\n```\nmyIndexedRotation(start, middle, end);\n```\nWhile lengths mode uses these:\n```\nmyLengthsRotation(start, lengthOfFirstSegment, lengthOfSecondSegment);\n```\n\n`sortingVisualizer.getRotation()` returns a `Rotation` object, which provides both `indexedFn`, for the indexed version of the function, and `lengthFn` for the lengths version of the function.\n\n### Pivot Selections\nPivot Selection algorithms on the other hand, provide just one function that takes as input the start and end of the segment in which the pivot has to be selected, and return the index of the selected pivot.\n\n`sortingVisualizer.getPivotSelection()` returns the function directly.\n## Other utilities\nThe visualization speed can be changed through `sortingVisualizer.setSpeed(value: float)` and reset to 1 via `sortingVisualizer.resetSpeed()`. The speed can be fetched through `sortingVisualizer.speed` for temporary speed editing.\n\nDelays can be set by using `sortingVisualizer.delay(timeMs: float)` before any highlighted operation.\n\nCustom titles can be set through `sortingVisualizer.setCurrentlyRunning(name: str, category: Optional[str] = None)`. The category is best left untouched to avoid confusion.\n\nThe visualizer also provides methods for user input, namely:\n- `sortingVisualizer.getUserInput(message: str = \"\", default: str = \"\", type_: int) -\u003e type_`: asks the user a text input that gets converted to `type_`. `default` sets the default value;\n- `sortingVisualizer.getUserSelection(content: list[str], message: str = \"\") -\u003e int`: asks the user to select between a list of items and returns the selection index.\n\nAnd a method for warnings and errors, often used for invalid inputs:\n- `sortingVisualizer.userWarn(message: str)`.\n\nWhen the process of asking the user needs to be skipped, like in a custom thread, an \"autoValue\" can be pushed into a queue through the `sortingVisualizer.pushAutoValue(value)` method. To remove the next value, `sortingVisualizer.popAutoValue()` can be used. `sortingVisualizer.resetAutoValues()` clears the queue.\n## Adding new shuffles\nAdding a new shuffle is extremely simple! You just need to add your `.opal` or `.py` file inside the `shuffles` folder, and provide a run function, composed like this:\n```\n@Shuffle(\"Shuffle Name\");\nnew function myShuffle(array) {\n    # your code here\n}\n```\nor, in Python:\n```py\n@Shuffle(\"Shuffle Name\")\ndef myShuffle(array):\n    ... # your code here\n```\nAn optional boolean argument called `usesDynamicAux` can be set if the shuffle uses an auxiliary array which is not static in size or maximum element, or is composed of items that don't belong in the main array. It is `False` by default.\n## Adding new sorts\nLike shuffles, adding sorts is very simple.  `.opal` or `.py` files need to be added to the `sorts` folder, and they have to provide a run function:\n```\n@Sort(\n    \"Sort Category\",\n    \"Sort Name\",\n    \"Sort Name in menu selection\"\n);\nnew function mySort(array) {\n    # your code here\n}\n```\nLike in shuffles, the sort class provides a `usesDynamicAux` argument for the same purpose. The sort class also provides an `enabled` argument, that can be set to `False` for sorts that aren't ready for use. Those sorts will only be added to the sorts list if `DEBUG_MODE` is set to `True`\n## Adding new pivot selections\nPivot selections are algorithms used to select a pivot in partitioning sorts that require one. The visualizer provides a set of pivot selections for those algorithms to use, and the user can pick the one they prefer to experiment with. The process to adding one is very similar to adding a shuffle. The file needs to be added in the `pivotSelection` folder, and provide a run function:\n```\n@PivotSelection(\"Pivot Selection Name\");\nnew function myPivotSelection(array, start, end) -\u003e int {\n\t# [start, end) is the interval in which the selection should pick a pivot\n\t# the code should return the index of the selected pivot\n    # your code here\n}\n```\n## Adding new rotation algorithms \nThe process to adding a rotation algorithm is very similar to shuffles and pivot selections. The file needs to be added in the `rotations` folder and provide a run function:\n```\n# using RotationMode.INDEXED (which is default, it doesn't need to be passed)\n# creates the indexed variant of the function. The Rotation class will automatically\n# generate the lengths function\n@Rotation(\"Rotation Name\", RotationMode.INDEXED);\nnew function myRotation(array, start, middle, end) {\n\t# your code here\n}\n```\nor\n```\n# using RotationMode.LENGTHS creates the lengths variant of the function. \n# The Rotation class will automatically generate the indexed function\n@Rotation(\"Rotation Name\", RotationMode.LENGTHS);\nnew function myRotation(array, start, lenA, lenB) {\n\t# your code here\n}\n```\n## Adding new distributions\nAdding distributions is similar to adding shuffles and pivot selections. Files need to be added to the `distributions` folder. Creating arrays doesn't use the `Value` API, since the `Value`s aren't placed in the array at that time yet.\n```\n@Distribution(\"Distribution Name\");\nnew function myDistribution(array, length) {\n    # your code here\n}\n```\n## Working with threads\nThe visualizer usually operates in a sequential manner, so, to properly visualize parallel sorts, it's sufficient to call the algorithm's main function in `sortingVisualizer.runParallel(fn: Callable, *args, **kwargs)`, so that the visualizer can create a separate sort thread and run the visualization code on the main thread (since pygame has to run on the main thread), as well as properly handle highlighting. To create a thread inside of such an algorithm, `sortingVisualizer.createThread(fn: Callable, *args, **kwargs)` should be used to avoid program freezing and crashing.\n\n## Adding visual styles\nTo add a visual style, a class needs to be created and inherit from the `Visual` class. That way, visuals are automatically added. Said file needs to be added in the `visuals` folder. Example:\n```\nnew class MyVisual: Visual {\n\tnew method __init__() {\n\t\tsuper.__init__(\n\t\t\t\"Visual Name\",\n\t\t\thighlightColor,\n\t\t\trefreshMode,\n\t\t\toutOfText\n\t\t);\n\t}\n}\n```\n- `highlightColor`: a tuple containing 3 values (0, 255) in the RGB format. By default, it's set to (255, 0, 0);\n- `refreshMode`: can either be `RefreshMode.LINES` for line-like visuals that intersect with the text or `RefreshMode.NOREFRESH` for visuals that don't need forced indices reloading. By default, it's set to `RefreshMode.NOREFRESH`. Note that this is only relevant for visuals that implement `selectiveDraw`;\n- `outOfText`: a boolean that indicates whether the visual draws over text. If it doesn't (True), the visualizer will draw a black rectangle under the text, to refresh it. By default, it's set to `False`. This also only relevant for visuals that implement `selectiveDraw`.\n\nThe `Visual` class contains two abstract methods: \n- `draw(array: list[Value], indices: dict[int, Optional[tuple[int, int, int]]])`: draws the main array. `indices` contains the list of highlighted indices, each mapped to a color. If the mapped color is `None` the visual should draw those indices like they're not highlighted;\n- `drawAux(array: list[Value], indices: dict[int, Optional[tuple[int, int, int]]])`: like `draw`, but draws the aux array.\n\nThe class also provides seven methods that get called in specific scenarios and can be overridden. By default, they do nothing:\n- `init()`: gets called when the graphic system is re-initialized (usually when the resolution is changed). Useful to change data that relies on the resolution.\n- `prepare()`: precomputes data for the visual style;\n- `onAuxOn(length)`: gets called when aux is turned on or constants are to recompute. Useful to prepare data;\n- `onAuxOff()`: gets called when aux mode is turned off. Useful to restore old values.\n- `fastDraw(array: list[Value], indices: dict[int, Optional[tuple[int, int, int]]])`: like `draw`, but it can contain a lower quality version of the visual style which is less expensive to compute. By default, it just calls `draw`.\n- `fastDrawAux(array: list[Value], indices: dict[int, Optional[tuple[int, int, int]]])`: like `fastDraw`, but draws the aux array. By default, it just calls `drawAux`.\n- `selectiveDraw(array: list[Value], indices: dict[int, Optional[tuple[int, int, int]]])`: like `draw`, but it assumes only the highlighted indices are changed, working in a selective manner.\n\nThe `graphicsUtils.opal` file contains some presets for common visual styles.\n## Adding sound systems\nTo add a sound system, a class needs to be created and inherit from the `Sound` class. The file needs to be added in the `sounds` folder. Example:\n```\nnew class MySound: Sound {\n\tnew method __init__() {\n\t\tsuper.__init__(\"Sound name\");\n\t}\n}\n```\nThe `Sound` class contains an abstract method:\n- `play(value: int | float, max_: int | float, sample: numpy.array) -\u003e numpy.array`: generates the sound sample to be played based on the array value. The original sample should be left untouched.\n\nThe class also provides a method:\n- `prepare()`: it gets called when the visualizer has to prepare the sound system. Usually used to request or load settings if it needs any, or precompute data. By default, it does nothing.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famari-calipso%2Fsorting-visualizer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Famari-calipso%2Fsorting-visualizer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famari-calipso%2Fsorting-visualizer/lists"}