The main component of the color helper file is the RGB class. Various modules (e.g. Plotly and Matplotlib) use different conventions for representing red, green and blue color intensities. The RGB class accepts as input and provides as output (via associated methods) the following possible formats:
A 3-tuple of floats between 0 and 1 such as (0.6, 0.4, 1.0) (corresponds to the method asTupleFloat)
A 3-tuple of integers between 0 and 255 such as (153, 102, 255) (corresponds to the method asTupleInt)
A string representing a 3-tuple of integers between 0 and 255 such as "rgb(153,102,255)" (corresponds to the method asStringTuple)
A string representing a 6 digit hexadecimal number such as "#7F66FF" (corresponds to the method asStringHex)
The color helper file also contains two additional components which I have found to be helpful. The first is a pair of dictionaries containing all colormaps of Matplotlib (i.e. ALL_MATPLOTLIB_COLORMAPS) and all color scales of Plotly sorted by type (i.e. ALL_PLOTLY_COLOR_SCALES_BY_TYPE); keys of the dictionaries are sequence names and values are lists of RGB objects. The reason these dictionaries exist is a matter of personal convenience as I grew tired of having to search documentation for the existing color sequences in these modules. The second additional component is the customSpectrum function which takes as input a value between 0 and 1 and outputs an RGB object. The list DEFAULT_SPECTRUM is passed to this function by default and contains a ROYGBIV-like sequence of colors (see below); however, the user can specify any list of RGB objects they wish interpolated via the optional rgb_spectrum argument.
The file latex_helper.py is a simple script which uses Matplotlib to render LaTeX equations stored in txt files. There isn't too much to say here beyond the fact that the main purpose of this script is to allow me to render the equation images used on this website.
Suppose we have the data points (x1,y1) through (xn,yn) such that x1 < x2 < … < xn. Define the polynomials f1(x) through fn-1(x) such that (1) fi(xi) = yi and (2) fi(xi+1) = yi+1 for each i in the set {1,...,n-1}. Such a mathematical construction is called a "spline" and there are of course infinitely many ways to connect finitely many points using piecewise polynomials. However, two common methods are linear splines and natural cubic splines.
First, the linear spline is the simpler of these two versions as it takes the form fi(x) = ai(x - xi) + bi for each polynomial. The above Conditions (1) and (2) are sufficient for allowing us to solve for our coefficients ai and bi:
Next, the natural cubic spline has significantly more complexity because our polynomials are of the form fi(x) = ai(x - xi)3 + bi(x - xi)2 + ci(x - xi) + di. Without any extra constraints we would have too many degrees of freedom for our spline to be uniquely defined. As such, we have the following additional requirements of (3) fi'(xi+1) = fi+1'(xi+1) to make slopes match at defining points, (4) fi''(xi+1) = fi+1''(xi+1) to make concavities match at defining points, and (5) the "natural" choice of making f1''(x1) and fn-1''(xn) both being equal to 0. This system of 4n - 4 equations and unknowns is not too tricky to solve but there are a few key steps for making it simpler to solve. The first is to note that di = yi for each i simply because of Condition (1). The second is to define Δxi = xi+1 - xi and Δyi = yi+1 - yi for each i in the set {1,...,n-1}. The third and final step is to imagine a hypothetical nth cubic polynomial which, according to Condition (5), would have quadratic term bn = 0.
With this setup work completed, it turns out to be easiest to compute the quadratic coefficients b1,...,bn by solving a linear system of equations. It is tricky to cleanly write the matrices of this system for arbitrary values of n; however, the following example of setting n = 5 should be sufficient for demonstrating the general pattern used in larger systems:
From here, the following equations allow one to solve for the cubic and linear coefficients respectively:
The linear and natural cubic splines shown above are currently implemented in spline_helper.py. However, in the future it would be easy to implement additional spline options because both LinearSpline and NaturalCubicSpline are sub-classes of the abstract Spline class contained in that Python file. For now, take a look at the following figure generated using these two classes!
The main goal of sqlite3_helper.py is to create a wrapper around SQLite3 which allows one to use SQL databases similarly to how one might use a Pandas dataframes or a log file. Although perhaps not the typical use for a SQL database, I have found that it is convenient to store progressively-generated data sets in a standalone file rather than in short-term memory; such a file can then be read by data visualization software to create a live view of the data as it is generated. While this functionality could be implemented by periodically writing relevant dataframes to their associated csv files, I have found a variety of benefits to keeping all information in a single db file.
There are many functions contained in sqlite3_helper.py so here is a high-level summary of these functions and their arguments:
Functions for adding and deleting tables in a db file
addTable(db_path, table_name, column_names, column_types, replace_flag = True)
deleteTable(db_path, table_name)
Functions for reading from a db file
getExistingTables(db_path) -> list
getColumnNames(db_path, table_name) -> list
getColumnTypes(db_path, table_name) -> list
getRowCount(db_path, table_name) -> int
readTable(db_path, table_name) -> dict
readColumn(db_path, table_name, column_name) -> list
readRow(db_path, table_name, row_index) -> list
readEntry(db_path, table_name, column_name, row_index) -> Any
Functions for writing to a db file
appendColumn(db_path, table_name, column_name, column_type)
appendRow(db_path, table_name)
deleteColumn(db_path, table_name, column_name)
deleteRow(db_path, table_name, row_index)
replaceColumn(db_path, table_name, column_name, new_column)
replaceRow(db_path, table_name, row_index, new_row)
replaceEntry(db_path, table_name, column_name, row_index, new_entry)
swapRows(db_path, table_name, row_index_1, row_index_2)
The contents of the type helper script are generally the lowest level functions of the Presently Level repositories. Type hints are certainly helpful in Python but they are not as robust more formal type declarations used in other languages. Personally, I have typically used simple assert statements to check object types but this has proved repetitive over time; how many times must I verify that an object is numeric, or that an object is a list of strings? The functions of type_helper.py are simply collections of assert statements that serve as a shortcut for this low-level operation.