ParSub API Reference
This document describes the public Python API of ParSub, organized by module. For the command line and the REST API see the User Guide.
Main Package
parsub
__version__
The package version string, e.g. "0.2.1" (also shown by parsub --version).
analyze_latex(latex_source, output_dir="./output", source_name=None) -> AnalysisResult
Parse, analyze and generate code for a LaTeX string. Writes generated_computation.py and
analysis.json into output_dir. See AnalysisResult.
analyze_latex_file(latex_file, output_dir="./output") -> str
Same for a file; returns the path of the generated Python script.
from parsub import analyze_latex_file
code_file = analyze_latex_file("paper.tex", "./results")
run_generated_code(code_path, output_dir=None, timeout=600, capture_output=True) -> subprocess.CompletedProcess
Run a generated script in a separate Python process. Results are written to output_dir
(default: the script’s directory). Raises FileNotFoundError for a missing script and
subprocess.TimeoutExpired when timeout seconds are exceeded.
Pipeline Module
parsub.core.pipeline
AnalysisResult
Returned by analyze_latex:
parsed: the parser result (seeparse_latex_source)tasks: list of task dictionaries (seeanalyze_expressions)code_path,analysis_path,output_dir: paths of the written fileswarnings: list of messages (e.g. no expressions found)expressions: shortcut forparsed["expressions"]summary(): JSON-friendly overview (counts, goals, methods, parameters, paths, warnings)
analyze_latex(...), analyze_latex_file(...), run_generated_code(..., task_timeout=None)
The implementations behind the top-level functions. task_timeout sets the per-task time limit
of the generated script.
read_run_summary(output_dir) -> dict | None
Load data/summary.json written by a generated script.
Parser Module
parsub.parser.latex_parser
parse_latex_source(latex_source: str) -> Dict[str, Any]
Parse LaTeX source and extract mathematical expressions and metadata.
Returns a dictionary containing:
expressions: list of expression dictionaries (below)goals: research goals found in the prose (“we aim to …”, “the goal is to …”)methods: methods found in the prose (“we use …”, “by applying …”)parameters: every free symbol withname,frequency,type,suggested_rangeanddefaultassignments: values stated in the document, e.g.{"g": 9.81}constants: symbols given a non-real constant value, e.g.{"i": I}fori = \sqrt{-1}raw_latex: the original inputtext: the prose with formulas replaced by placeholdersstatistics:math_segments,expressions,convertedparse_error: only present if parsing failed
Expression dictionary:
raw_latex: the formula as writtenlatex: the cleaned formula that was convertedsympy_expr: SymPy object (sympy.Eqfor equations) orNoneif it could not be convertedsympy_str:str(sympy_expr)orNonekind:"equation","expression","assignment"(g = 9.81,a_1 = a) orNonevariables: names of the free symbolsconstants: numeric constants used (pi,E,I)display:Truefor display mathenvironment:"inline","display"or the environment name ("equation","align*", …)label: the\label{...}of the equation, if anycontext: prose preceding the formulaconditions/constraints: side conditions and the bounds derived from them, e.g.{"z": {"min": 0.0}}description: reserved for a textual description (currentlyNone)
Example:
from parsub.parser.latex_parser import parse_latex_source
result = parse_latex_source("$E = mc^2$")
print(result["expressions"][0]["sympy_expr"]) # Eq(E, c**2*m)
LaTeXParser
Parser class. LaTeXParser(context_chars=400).parse(latex_source) returns the same dictionary as
parse_latex_source.
MathExpression
Dataclass behind the expression dictionaries (to_dict() produces them).
parsub.parser.latex_to_sympy
Helpers used by the parser:
latex_to_sympy(latex) -> sympy object | None– strict conversion of a single formulaclean_latex(latex) -> str– remove labels, spacing and font macrossplit_conditions(latex) -> (formula, conditions)– split off\,\,\, (\Re(z)>0)style conditionsparse_constraints(conditions) -> dict– bounds such as{"z": {"min": 0.0}}is_assignment(expr),assignment_value(expr)– recogniseg = 9.81constant_value(expr)– recognisei = \sqrt{-1}
Special-function notation (hypergeometric, Pochhammer, orthogonal polynomials, Bessel functions, indexed functions and primes for derivatives) is described in the User Guide.
Analyzer Module
parsub.analyzer.expression_analyzer
analyze_expressions(expressions, context=None) -> List[Dict[str, Any]]
Analyze expressions and return JSON-serialisable task dictionaries.
Args:
expressions: expression dictionaries from the parser (onlysympy_expris required;context,constraints,kind,label,latexandgoal_typeare used when present)context: optionalgoals,methods,parameters,assignmentsandconstants
Function definitions found among the expressions are substituted into the other expressions,
symbol definitions provide values for fixed parameters, and repeated definitions of the same
function produce verify tasks that compare them.
Task dictionary:
expression: what is computed (str); for a definitiony = f(x)this isf(x)srepr: exact SymPy representation used by the generated codelatex: LaTeX ofexpressionvariables: free variablesgoal_type:evaluate,plot,solve,optimize,integrate,differentiate,series,verifyorsymbolicindependent_variables: variables that are sweptfixed_parameters:{name: value}for the other variablesparameters: per variabletype,range,defaultandrolesuggested_sampling:method,pointsandranges({name: (min, max)})expected_output_type:scalar,array,functionorsymbolicoptions: goal-specific options (directionfor optimize,solve_for, seriesorder/point)label: left-hand side of a definition, if anyequation:lhs/rhs(srepr and str) forsolveandverifysource_latex,source_label: where the task came fromdescription: human-readable summary
Example:
from parsub.analyzer.expression_analyzer import analyze_expressions
tasks = analyze_expressions(parsed["expressions"], {
"goals": parsed["goals"],
"methods": parsed["methods"],
"assignments": parsed["assignments"],
})
ExpressionAnalyzer
ExpressionAnalyzer().analyze_expressions(expressions, context) returns ComputationTask
objects instead of dictionaries (task.to_dict() converts them).
Code Generation Module
parsub.generator.code_generator
generate_code_from_tasks(tasks, output_dir="./output", source_name=None) -> str
Generate Python code from task dictionaries, save it as generated_computation.py and return its path.
CodeGenerator
CodeGenerator(output_dir="./output")– createsoutput_dir,plots/anddata/generate_evaluation_code(tasks, source_name=None) -> str– the complete script as a stringsave_code(code, filename="generated_computation.py") -> str– save it and return the path
parsub.generator.runtime
The helper library that is embedded in every generated script (and importable directly):
lambdify_expr(expr, variables, fixed=None)– vectorised numeric function; falls back to point-by-point SymPy evaluation for integrals and sums (.pointwisetells which is used)evaluate_expression(expr, variables, values_dict) -> floatsave_plot(fig, filename, ctx=...),save_data(data, filename, ctx=...)–.csv,.tsv,.xlsxor.jsonevaluate_task,plot_task,solve_task,optimize_task,integrate_task,differentiate_task,series_task,verify_task,symbolic_task– one per goal typerun_tasks(tasks, argv=None, default_output_dir=None) -> int– command-line runnertime_limit(seconds),attempt(func, seconds)– time limits (Unix)
Shared Knowledge
parsub.core.parameters
PARAMETER_HINTS:name -> (type, (min, max), default)for common symbolsinfer_parameter_type(name),infer_parameter_range(name),default_value(name),describe_parameter(name, frequency); subscripted and variant names (v_0,vartheta) use the entry of their base name.
CLI Module
parsub.cli.main
The Typer application app behind the parsub command (main() is the console-script entry
point). See the User Guide.
REST API Module
parsub.api.main
app: the FastAPI application (uvicorn parsub.api.main:app)run(host=None, port=None): entry point of theparsub-apicommand- Environment variables:
PARSUB_OUTPUT_ROOT(default./output),PARSUB_API_HOST(default127.0.0.1),PARSUB_API_PORT(default8000)
See the User Guide for the endpoints.
Dependencies
sympy>= 1.12 andantlr4-python3-runtime4.11: symbolic mathematics and LaTeX parsingpylatexenc>= 2.10: LaTeX tokenisationnumpy>= 1.24,scipy>= 1.10: numerical computationmatplotlib>= 3.7: plottingpandas>= 2.0,openpyxl>= 3.1: data files (CSV/TSV/Excel)typer>= 0.9,rich>= 12: command line interfacefastapi>= 0.100,uvicorn>= 0.23,python-multipart: REST API
Error Handling
- Graceful degradation: a formula that cannot be converted is reported, not guessed; a task
that fails or times out is recorded in
data/summary.jsonwhile the others continue. - Informative errors: the CLI prints clear messages and returns exit code 1; the REST API
returns 400/403/404/413/504 with a
detailmessage. - Validation: inputs are validated at the CLI and REST API boundaries.
Extending ParSub
Adding a goal type (e.g. fourier_transform)
- Add keywords to
GOAL_KEYWORDS(andGOAL_PRIORITY) inexpression_analyzer.py. - Add a
fourier_task(ctx, task_id, expr, ...)function togenerator/runtime.py. - Add a branch for the goal in
CodeGenerator._generate_task_code. - Add tests.
Adding an output format
Extend save_data in generator/runtime.py (the format is chosen by file extension).
Custom LaTeX constructs
Extend clean_latex / _postprocess in parser/latex_to_sympy.py.
Changelog
See the changelog.