Latexify.jl

repository·master·Indexed 20 days ago

https://github.com/korsbo/latexify.jl

A Julia package that converts Julia objects—including expressions, strings, numbers, complex types, Arrays, Dicts, and DataFrames—into LaTeX-formatted strings. It provides built-in support for the SciML ecosystem, specifically for visualizing mathematical models from DifferentialEquations.jl and Catalyst.jl reaction networks. Key features include the @latexrecipe macro for custom types, various LaTeX environment configurations (align, equation, array, tabular, mdtable), and the ability to render LaTeX strings to PDF, PNG, or SVG.

Tokens
8.4K
Snippets
46
Records
51
Agent score
68%

What's inside Latexify.jl

  1. Define arithmetic operations with the 'operation' keyword

    master

    If your custom type represents a specific arithmetic operation (like subtraction or multiplication), you can use the operation keyword within an @latexrecipe to inform latexify of its nature. This allows latexify to apply correct mathematical parenthesis rules when the type is used within larger expressions.

    To do this, use the := operator to ensure the operation is fixed: operation := :<operator> (where <operator> is a symbol like :-, :+, etc.).

    Example: If you have a type MyDifference representing x - y, defining the recipe with operation := :- ensures that @latexify $(MyDifference(2,3))*4 results in \left( 3 - 2 \right) \cdot 4 instead of the incorrect 3 - 2 \cdot 4.

    struct MyDifference
    x
    y
    end
    
    @latexrecipe function f(m::MyDifference)
        operation := :-
        return :($(m.y) - $(m.x))
    end
  2. How to define custom recipes with @latexrecipe

    master

    To extend Latexify to work with your own custom types, use the @latexrecipe macro. This allows you to define how a specific type should be converted into a LaTeX expression.

    using Latexify
    
    struct Ket{T}
        x::T
    end
    
    @latexrecipe function f(x::Ket)
        return Expr(:latexifymerge, "\\left|", x.x, "\\right>")
    end
    
    # Usage
    latexify(:($(Ket(:a)) + $(Ket(:b))))
  3. Configure keyword argument defaults in @latexrecipe

    master

    Inside an @latexrecipe function, you can control how latexify keyword arguments behave using two special operators:

    1. kwarg --> value: Sets a default value for a keyword argument. This value can be overridden if the user specifies that keyword argument in their call to latexify.
    2. kwarg := value: Sets a fixed value for a keyword argument. This value cannot be overridden by the user.

    Example usage:

    @latexrecipe function f(x::MyType)
        env --> :array      # User can change this
        fmt := "%.2f"     # User cannot change this
        return x.vector
    end
  4. How Latexify.jl converts expressions to LaTeX

    master

    Latexify.jl uses a recursive algorithm to traverse Julia expression trees (Expr type) to generate LaTeX strings. The process relies on two core internal methods:

    1. latexraw(ex::Expr): This method recurses through the expression tree. It identifies the structure of the expression by looking at its arguments (ex.args).
    2. latexoperation(ex::Expr, prevOp::AbstractArray): When the recursion reaches an expression that contains only symbols or strings (no further nested expressions), it calls latexoperation. This method identifies the mathematical operation and converts that specific node into a formatted LaTeX string (e.g., converting / to \frac{...}{...}).

    The recursive results are bubbled back up the tree until the entire expression is transformed into a single LaTeX string.

    ex = :(x + y/z)
    # The process: 
    # 1. latexraw(ex) sees :(x + (y/z))
    # 2. latexraw recurses into (y/z)
    # 3. latexoperation converts (y/z) to "\\frac{y}{z}"
    # 4. latexraw returns "x + \\frac{y}{z}"
    print(latexraw(ex)) # "x + \frac{y}{z}"
  5. Latexify Catalyst.jl ReactionNetwork models

    master

    You can convert ReactionNetwork models generated by Catalyst.jl into LaTeX equations using latexify().

    By default, latexify will attempt to render the chemical reaction notation. You can specify the mathematical form of the output using the form keyword argument:

    • form=:ode: Generates the Ordinary Differential Equations (ODEs) representing the system.
    • form=:sde: Generates the Stochastic Differential Equations (SDEs) representing the chemical Langevin equations (Note: SDE generation is currently reported as broken in the current version).

    To use this, ensure both Catalyst and Latexify are loaded.

    using Catalyst
    using Latexify
    
    # Define a reaction network
    @reaction_network begin
      hill2(y, v_x, k_x), 0 --> x
      p_y, 0 --> y
      (d_x, d_y), (x, y) --> 0
      (r_b, r_u), x ↔ y
    end
    
    # Generate ODEs
    latexify(rn; form=:ode)
    
    # Generate SDEs
    latexify(rn; form=:sde)
  6. Use the `latexify` wrapper function

    master

    The latexify function is a high-level wrapper that attempts to infer the most suitable LaTeX output mode for a given input.

    • Rich Rendering: If your environment (like a Jupyter notebook or VS Code) supports the text/latex MIME type, latexify will render the equation visually.
    • Copy-Paste Mode: To get a raw LaTeX string suitable for pasting into a .tex document, use println(latexify(expr)) or latexify(expr) |> println instead of just displaying it.
    using Latexify
    
    ex = :(x/y)
    latexify(ex) # Renders visually if supported
    
    # To get the raw LaTeX string for copy-pasting:
    println(latexify(ex))
  7. Extend Latexify.jl using @latexrecipe

    master

    The @latexrecipe macro allows you to extend latexify to support custom types or types from other packages. It defines how an argument type should be pre-processed before being passed to the standard latexify function.

    Key Requirements:

    • Type Signature: The function passed to the macro must have a specific type signature (e.g., f(x::MyType)). The function name itself is unimportant.
    • Explicit Return: You must use an explicit return statement. The returned value must be a type that latexify already supports (e.g., Array, Tuple, Number, Symbol, or String). You cannot rely on Julia's implicit return of the last expression.
    • Scope: Recipes defined within a module work automatically without needing to be exported.

    Warning: Do not use @latexrecipe to redefine how an already supported type is interpreted, as this can break functionality for other packages.

    using Latexify
    
    struct MyType 
       vector::Vector
    end
    
    @latexrecipe function f(x::MyType; reverse=false)
        vec = x.vector
        if reverse
            vec = vec[end:-1:1]
        end
    
        # Set default keyword arguments (can be overridden by user)
        env --> :array
        transpose --> true
    
        # Set fixed keyword arguments (cannot be overridden by user)
        fmt := "%.2f"
    
        return vec
    end
    
    mytype = MyType([1, 2, 3])
    latexify(mytype; reverse=true)
  8. Visualize ParameterizedFunction parameters

    master

    To map parameter values to their symbolic names, pass the parameter values as a second argument to latexify.

    There are two primary ways to display this:

    1. List format: latexify(ode.params, param) renders a list of equations like $k_{y} = 3.4$.
    2. Array format: latexify([ode.params, param]; env=:array, transpose=true) renders the parameters and values in a LaTeX array/matrix format.
    param = [3.4, 5.2, 1e-2]
    
    # Option 1: List of assignments
    latexify(ode.params, param)
    
    # Option 2: Matrix/Array representation
    latexify([ode.params, param]; env=:array, transpose=true)
  9. Use Latexify.jl to produce LaTeX strings

    master

    Latexify.jl converts various Julia objects into $\LaTeX$ formatted strings. The primary function latexify() automatically selects an appropriate environment based on the input type, but you can override this using the env keyword argument.

    Supported Input Types:

    • Expressions, Strings, Symbols
    • Numbers (including rational and complex)
    • Missing
    • SymEngine.jl symbolic expressions
    • DataFrames.jl DataFrames
    • Arrays (including mixed types)
    • ParameterizedFunctions and ReactionNetworks from DifferentialEquations.jl
    using Latexify
    
    # Basic usage
    str = "x/(2*k_1+x^2)"
    latexify(str)
    
    # Using an array
    m = [2//3 "e^(-c*t)" 1+3im; :(x/(x+k_1)) "gamma(n)" :(log10(x))]
    latexify(m)
  10. Convert equations to LaTeX align environments with `latexalign`

    master

    The latexalign function converts input expressions into $\LaTeX$ align environments.

    One common usage pattern is to pass two vectors to the function: one containing the left-hand-side (LHS) expressions and another containing the right-hand-side (RHS) expressions. This results in a multi-line aligned equation block.

    In Jupyter notebooks, use display(latexalign(lhs, rhs)) to render the output visually.

    lhs = ["dx/dt", "dy/dt"]
    rhs = ["y^2 - x", "x/y - y"]
    print(latexalign(lhs, rhs))
  11. Embed latexifications in Markdown text

    master

    To embed math results directly within Markdown text in a notebook, use Markdown.parse.

    Note: Do not use the md""" literal for this purpose, as the dollar signs used for math mode will clash with Julia's string interpolation syntax. Instead, use Markdown.parse and interpolate the latexify results directly into the string.

    When using Markdown.parse, you may need to escape special characters like backslashes, though Latexify typically minimizes this need. For manual control over the environment, you can use env=:raw combined with manual dollar signs.

    Markdown.parse("""
    ## Results
    
    With the previously calculated 
    $(@latexdefine x), we can use
    $(@latexify x = v*t) to calculate
    $(@latexrun v = x/10), giving a final
    velocity of $(latexify(v)).
    
    If we want more manual control, we can
    combine manual dollar signs with
    `env=:raw`: \$ \hat{v} =
    $(latexify(v, env=:raw));\, \mathrm{m}/\mathrm{s} $
    """)