texlive[74868] Master: lua-regression (6apr25)

commits+karl at tug.org commits+karl at tug.org
Mon Apr 7 21:47:17 CEST 2025


Revision: 74868
          https://tug.org/svn/texlive?view=revision&revision=74868
Author:   karl
Date:     2025-04-07 21:47:17 +0200 (Mon, 07 Apr 2025)
Log Message:
-----------
lua-regression (6apr25)

Modified Paths:
--------------
    trunk/Master/tlpkg/bin/tlpkg-ctan-check
    trunk/Master/tlpkg/libexec/ctan2tds
    trunk/Master/tlpkg/tlpsrc/collection-mathscience.tlpsrc

Added Paths:
-----------
    trunk/Master/texmf-dist/doc/lualatex/lua-regression/
    trunk/Master/texmf-dist/doc/lualatex/lua-regression/README.md
    trunk/Master/texmf-dist/doc/lualatex/lua-regression/example/
    trunk/Master/texmf-dist/doc/lualatex/lua-regression/example/lua-regression-example.tex
    trunk/Master/texmf-dist/doc/lualatex/lua-regression/example/mpg.csv
    trunk/Master/texmf-dist/doc/lualatex/lua-regression/lua-regression-doc.pdf
    trunk/Master/texmf-dist/doc/lualatex/lua-regression/lua-regression-doc.tex
    trunk/Master/texmf-dist/tex/lualatex/lua-regression/
    trunk/Master/texmf-dist/tex/lualatex/lua-regression/lua-regression.lua
    trunk/Master/texmf-dist/tex/lualatex/lua-regression/lua-regression.sty
    trunk/Master/tlpkg/tlpsrc/lua-regression.tlpsrc

Added: trunk/Master/texmf-dist/doc/lualatex/lua-regression/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/lualatex/lua-regression/README.md	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/lualatex/lua-regression/README.md	2025-04-07 19:47:17 UTC (rev 74868)
@@ -0,0 +1,41 @@
+# LuaLaTeX Regression
+
+A system for performing regression testing on CSV format data files in LaTeX, written purely in Lua for use with LuaLaTeX.
+Includes the ability to fit polynomials of multiple orders to data, and plot the results using PGFPlots.
+Offers some additional features such as the ability to generate confidence intervals and perform $R^2$ tests on the data.
+
+## Features
+- Fit polynomials of multiple orders to data
+- Generate confidence intervals
+- Perform $R^2$ tests on the data
+- Plot the results using PGFPlots
+- Support for CSV format data files
+- Written purely in Lua for use with LuaLaTeX
+- Control significant figures in the output
+- Add and remove equation and $R^2$ from the legend.
+- Outputs equations and $R^2$ values to LaTeX commands so they can be called in the document.
+
+## Installation
+
+This package can be installed with a local LaTeX distribution (e.g. TeX Live, MikTeX). (Once approved, it will be available on CTAN.)
+
+Otherwise, you can clone the repository or download from 
+[releases](https://github.com/HaivuUK/lua-regression/releases/latest)
+and place the `tex` folder in your `texmf` local LaTeX directory.
+
+## Documentation
+
+Relevant documentation is included with each release.
+
+## Authors
+
+This package is authored and maintained by George Allison
+
+## Bug Reporting
+
+If you find a bug, please report it to the issue tracker on [https://github.com/HaivuUK/lua-regression](https://github.com/HaivuUK/lua-regression). 
+Include a description of the bug, the version of LuaLaTeX you are using, and any relevant code or data files.
+
+## License
+
+This project is licensed under the LPPL (LaTeX Project Public License), version 1.3c or later.
\ No newline at end of file


Property changes on: trunk/Master/texmf-dist/doc/lualatex/lua-regression/README.md
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/lualatex/lua-regression/example/lua-regression-example.tex
===================================================================
--- trunk/Master/texmf-dist/doc/lualatex/lua-regression/example/lua-regression-example.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/lualatex/lua-regression/example/lua-regression-example.tex	2025-04-07 19:47:17 UTC (rev 74868)
@@ -0,0 +1,103 @@
+%! Author = George
+%! Date = 07/04/2025
+%! Compiler = lualatex
+
+\documentclass[tikz,crop=true]{standalone}
+
+\usepackage{pgfplots}
+\usepackage{pgfplotstable}
+\usepackage{luacode}
+\definecolor{p1}{HTML}{332288}
+\definecolor{p2}{HTML}{0077BB} %*
+\definecolor{p3}{HTML}{88CCEE}
+\definecolor{p4}{HTML}{44AA99}
+\definecolor{p5}{HTML}{117733}
+\definecolor{p6}{HTML}{999933}
+\definecolor{p7}{HTML}{DDCC77}
+\definecolor{p8}{HTML}{EE7733} %*
+\definecolor{p9}{HTML}{CC6677}
+\definecolor{p10}{HTML}{CC3311} %*
+\definecolor{p11}{HTML}{882255}
+\definecolor{p12}{HTML}{AA4499}
+\definecolor{p13}{HTML}{EE3377} %*
+\pgfplotsset{compat=1.18}
+\usepackage[T1]{fontenc}
+\renewcommand{\familydefault}{\sfdefault}
+\usepackage{arevmath}
+\DeclareMathSizes{10}{9}{7}{5}
+\DeclareMathSizes{12}{10}{7}{5}
+\usepgfplotslibrary{fillbetween}
+
+\usepackage{lua-regression}
+
+\begin{document}
+
+	\begin{tikzpicture}
+		\begin{axis}[
+			height=6.45cm,
+			width=\textwidth,
+			domain=0:300,
+			samples=1000,
+			xmin=25,
+			xmax=240,
+			xlabel=horsepower,
+			ytick={},
+			xtick={},
+			ymax=6000,
+			ymin=1250,
+			ylabel=weight,
+			grid=both,
+			legend columns = 2,
+			legend style={cells={align=left},at={(0.45,-0.22)},anchor=north},
+			legend cell align=left,
+			major grid style={line width=.2pt,draw=gray!20},
+			every axis/.append style={axis line style={gray!80, line width=0.75pt}, tick style={gray!95}}
+			]
+
+			\addlegendimage{p4, mark=*, thick}
+			\addlegendimage{p8, thick}
+
+			\pgfplotstableread[col sep=comma]{mpg.csv}\datatable
+
+			\addplot [p4,mark=*,fill opacity=0.5] table [only marks,col sep=comma,x=horsepower,y=weight] {\datatable};
+
+			\luaregression[xcol = 4, ycol = 5, plot = true, eq = true, r2 = true, order = 1, ci = true]{mpg.csv}
+
+		\end{axis}
+	\end{tikzpicture}
+
+	\begin{tikzpicture}
+		\begin{axis}[
+			height=6.45cm,
+			width=\textwidth,
+			domain=0:300,
+			samples=1000,
+			xmin=25,
+			xmax=240,
+			xlabel=horsepower,
+			ytick={},
+			xtick={},
+			ymax=6000,
+			ymin=1250,
+			ylabel=weight,
+			grid=both,
+			legend columns = 2,
+			legend style={cells={align=left},at={(0.45,-0.22)},anchor=north},
+			legend cell align=left,
+			major grid style={line width=.2pt,draw=gray!20},
+			every axis/.append style={axis line style={gray!80, line width=0.75pt}, tick style={gray!95}}
+			]
+
+			\addlegendimage{p4, mark=*, thick}
+			\addlegendimage{p8, thick}
+
+			\pgfplotstableread[col sep=comma]{mpg.csv}\datatable
+
+			\addplot [p4,mark=*,fill opacity=0.5] table [only marks,col sep=comma,x=horsepower,y=weight] {\datatable};
+
+			\luaregression[xcol = 4, ycol = 5, plot = true, eq = true, r2 = true, order = 2, ci = true]{mpg.csv}
+
+		\end{axis}
+	\end{tikzpicture}
+
+\end{document}
\ No newline at end of file


Property changes on: trunk/Master/texmf-dist/doc/lualatex/lua-regression/example/lua-regression-example.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/lualatex/lua-regression/example/mpg.csv
===================================================================
--- trunk/Master/texmf-dist/doc/lualatex/lua-regression/example/mpg.csv	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/lualatex/lua-regression/example/mpg.csv	2025-04-07 19:47:17 UTC (rev 74868)
@@ -0,0 +1,399 @@
+mpg,cylinders,displacement,horsepower,weight,acceleration,model_year,origin,name
+18.0,8,307.0,130.0,3504,12.0,70,usa,chevrolet chevelle malibu
+15.0,8,350.0,165.0,3693,11.5,70,usa,buick skylark 320
+18.0,8,318.0,150.0,3436,11.0,70,usa,plymouth satellite
+16.0,8,304.0,150.0,3433,12.0,70,usa,amc rebel sst
+17.0,8,302.0,140.0,3449,10.5,70,usa,ford torino
+15.0,8,429.0,198.0,4341,10.0,70,usa,ford galaxie 500
+14.0,8,454.0,220.0,4354,9.0,70,usa,chevrolet impala
+14.0,8,440.0,215.0,4312,8.5,70,usa,plymouth fury iii
+14.0,8,455.0,225.0,4425,10.0,70,usa,pontiac catalina
+15.0,8,390.0,190.0,3850,8.5,70,usa,amc ambassador dpl
+15.0,8,383.0,170.0,3563,10.0,70,usa,dodge challenger se
+14.0,8,340.0,160.0,3609,8.0,70,usa,plymouth 'cuda 340
+15.0,8,400.0,150.0,3761,9.5,70,usa,chevrolet monte carlo
+14.0,8,455.0,225.0,3086,10.0,70,usa,buick estate wagon (sw)
+24.0,4,113.0,95.0,2372,15.0,70,japan,toyota corona mark ii
+22.0,6,198.0,95.0,2833,15.5,70,usa,plymouth duster
+18.0,6,199.0,97.0,2774,15.5,70,usa,amc hornet
+21.0,6,200.0,85.0,2587,16.0,70,usa,ford maverick
+27.0,4,97.0,88.0,2130,14.5,70,japan,datsun pl510
+26.0,4,97.0,46.0,1835,20.5,70,europe,volkswagen 1131 deluxe sedan
+25.0,4,110.0,87.0,2672,17.5,70,europe,peugeot 504
+24.0,4,107.0,90.0,2430,14.5,70,europe,audi 100 ls
+25.0,4,104.0,95.0,2375,17.5,70,europe,saab 99e
+26.0,4,121.0,113.0,2234,12.5,70,europe,bmw 2002
+21.0,6,199.0,90.0,2648,15.0,70,usa,amc gremlin
+10.0,8,360.0,215.0,4615,14.0,70,usa,ford f250
+10.0,8,307.0,200.0,4376,15.0,70,usa,chevy c20
+11.0,8,318.0,210.0,4382,13.5,70,usa,dodge d200
+9.0,8,304.0,193.0,4732,18.5,70,usa,hi 1200d
+27.0,4,97.0,88.0,2130,14.5,71,japan,datsun pl510
+28.0,4,140.0,90.0,2264,15.5,71,usa,chevrolet vega 2300
+25.0,4,113.0,95.0,2228,14.0,71,japan,toyota corona
+25.0,4,98.0,,2046,19.0,71,usa,ford pinto
+19.0,6,232.0,100.0,2634,13.0,71,usa,amc gremlin
+16.0,6,225.0,105.0,3439,15.5,71,usa,plymouth satellite custom
+17.0,6,250.0,100.0,3329,15.5,71,usa,chevrolet chevelle malibu
+19.0,6,250.0,88.0,3302,15.5,71,usa,ford torino 500
+18.0,6,232.0,100.0,3288,15.5,71,usa,amc matador
+14.0,8,350.0,165.0,4209,12.0,71,usa,chevrolet impala
+14.0,8,400.0,175.0,4464,11.5,71,usa,pontiac catalina brougham
+14.0,8,351.0,153.0,4154,13.5,71,usa,ford galaxie 500
+14.0,8,318.0,150.0,4096,13.0,71,usa,plymouth fury iii
+12.0,8,383.0,180.0,4955,11.5,71,usa,dodge monaco (sw)
+13.0,8,400.0,170.0,4746,12.0,71,usa,ford country squire (sw)
+13.0,8,400.0,175.0,5140,12.0,71,usa,pontiac safari (sw)
+18.0,6,258.0,110.0,2962,13.5,71,usa,amc hornet sportabout (sw)
+22.0,4,140.0,72.0,2408,19.0,71,usa,chevrolet vega (sw)
+19.0,6,250.0,100.0,3282,15.0,71,usa,pontiac firebird
+18.0,6,250.0,88.0,3139,14.5,71,usa,ford mustang
+23.0,4,122.0,86.0,2220,14.0,71,usa,mercury capri 2000
+28.0,4,116.0,90.0,2123,14.0,71,europe,opel 1900
+30.0,4,79.0,70.0,2074,19.5,71,europe,peugeot 304
+30.0,4,88.0,76.0,2065,14.5,71,europe,fiat 124b
+31.0,4,71.0,65.0,1773,19.0,71,japan,toyota corolla 1200
+35.0,4,72.0,69.0,1613,18.0,71,japan,datsun 1200
+27.0,4,97.0,60.0,1834,19.0,71,europe,volkswagen model 111
+26.0,4,91.0,70.0,1955,20.5,71,usa,plymouth cricket
+24.0,4,113.0,95.0,2278,15.5,72,japan,toyota corona hardtop
+25.0,4,97.5,80.0,2126,17.0,72,usa,dodge colt hardtop
+23.0,4,97.0,54.0,2254,23.5,72,europe,volkswagen type 3
+20.0,4,140.0,90.0,2408,19.5,72,usa,chevrolet vega
+21.0,4,122.0,86.0,2226,16.5,72,usa,ford pinto runabout
+13.0,8,350.0,165.0,4274,12.0,72,usa,chevrolet impala
+14.0,8,400.0,175.0,4385,12.0,72,usa,pontiac catalina
+15.0,8,318.0,150.0,4135,13.5,72,usa,plymouth fury iii
+14.0,8,351.0,153.0,4129,13.0,72,usa,ford galaxie 500
+17.0,8,304.0,150.0,3672,11.5,72,usa,amc ambassador sst
+11.0,8,429.0,208.0,4633,11.0,72,usa,mercury marquis
+13.0,8,350.0,155.0,4502,13.5,72,usa,buick lesabre custom
+12.0,8,350.0,160.0,4456,13.5,72,usa,oldsmobile delta 88 royale
+13.0,8,400.0,190.0,4422,12.5,72,usa,chrysler newport royal
+19.0,3,70.0,97.0,2330,13.5,72,japan,mazda rx2 coupe
+15.0,8,304.0,150.0,3892,12.5,72,usa,amc matador (sw)
+13.0,8,307.0,130.0,4098,14.0,72,usa,chevrolet chevelle concours (sw)
+13.0,8,302.0,140.0,4294,16.0,72,usa,ford gran torino (sw)
+14.0,8,318.0,150.0,4077,14.0,72,usa,plymouth satellite custom (sw)
+18.0,4,121.0,112.0,2933,14.5,72,europe,volvo 145e (sw)
+22.0,4,121.0,76.0,2511,18.0,72,europe,volkswagen 411 (sw)
+21.0,4,120.0,87.0,2979,19.5,72,europe,peugeot 504 (sw)
+26.0,4,96.0,69.0,2189,18.0,72,europe,renault 12 (sw)
+22.0,4,122.0,86.0,2395,16.0,72,usa,ford pinto (sw)
+28.0,4,97.0,92.0,2288,17.0,72,japan,datsun 510 (sw)
+23.0,4,120.0,97.0,2506,14.5,72,japan,toyouta corona mark ii (sw)
+28.0,4,98.0,80.0,2164,15.0,72,usa,dodge colt (sw)
+27.0,4,97.0,88.0,2100,16.5,72,japan,toyota corolla 1600 (sw)
+13.0,8,350.0,175.0,4100,13.0,73,usa,buick century 350
+14.0,8,304.0,150.0,3672,11.5,73,usa,amc matador
+13.0,8,350.0,145.0,3988,13.0,73,usa,chevrolet malibu
+14.0,8,302.0,137.0,4042,14.5,73,usa,ford gran torino
+15.0,8,318.0,150.0,3777,12.5,73,usa,dodge coronet custom
+12.0,8,429.0,198.0,4952,11.5,73,usa,mercury marquis brougham
+13.0,8,400.0,150.0,4464,12.0,73,usa,chevrolet caprice classic
+13.0,8,351.0,158.0,4363,13.0,73,usa,ford ltd
+14.0,8,318.0,150.0,4237,14.5,73,usa,plymouth fury gran sedan
+13.0,8,440.0,215.0,4735,11.0,73,usa,chrysler new yorker brougham
+12.0,8,455.0,225.0,4951,11.0,73,usa,buick electra 225 custom
+13.0,8,360.0,175.0,3821,11.0,73,usa,amc ambassador brougham
+18.0,6,225.0,105.0,3121,16.5,73,usa,plymouth valiant
+16.0,6,250.0,100.0,3278,18.0,73,usa,chevrolet nova custom
+18.0,6,232.0,100.0,2945,16.0,73,usa,amc hornet
+18.0,6,250.0,88.0,3021,16.5,73,usa,ford maverick
+23.0,6,198.0,95.0,2904,16.0,73,usa,plymouth duster
+26.0,4,97.0,46.0,1950,21.0,73,europe,volkswagen super beetle
+11.0,8,400.0,150.0,4997,14.0,73,usa,chevrolet impala
+12.0,8,400.0,167.0,4906,12.5,73,usa,ford country
+13.0,8,360.0,170.0,4654,13.0,73,usa,plymouth custom suburb
+12.0,8,350.0,180.0,4499,12.5,73,usa,oldsmobile vista cruiser
+18.0,6,232.0,100.0,2789,15.0,73,usa,amc gremlin
+20.0,4,97.0,88.0,2279,19.0,73,japan,toyota carina
+21.0,4,140.0,72.0,2401,19.5,73,usa,chevrolet vega
+22.0,4,108.0,94.0,2379,16.5,73,japan,datsun 610
+18.0,3,70.0,90.0,2124,13.5,73,japan,maxda rx3
+19.0,4,122.0,85.0,2310,18.5,73,usa,ford pinto
+21.0,6,155.0,107.0,2472,14.0,73,usa,mercury capri v6
+26.0,4,98.0,90.0,2265,15.5,73,europe,fiat 124 sport coupe
+15.0,8,350.0,145.0,4082,13.0,73,usa,chevrolet monte carlo s
+16.0,8,400.0,230.0,4278,9.5,73,usa,pontiac grand prix
+29.0,4,68.0,49.0,1867,19.5,73,europe,fiat 128
+24.0,4,116.0,75.0,2158,15.5,73,europe,opel manta
+20.0,4,114.0,91.0,2582,14.0,73,europe,audi 100ls
+19.0,4,121.0,112.0,2868,15.5,73,europe,volvo 144ea
+15.0,8,318.0,150.0,3399,11.0,73,usa,dodge dart custom
+24.0,4,121.0,110.0,2660,14.0,73,europe,saab 99le
+20.0,6,156.0,122.0,2807,13.5,73,japan,toyota mark ii
+11.0,8,350.0,180.0,3664,11.0,73,usa,oldsmobile omega
+20.0,6,198.0,95.0,3102,16.5,74,usa,plymouth duster
+21.0,6,200.0,,2875,17.0,74,usa,ford maverick
+19.0,6,232.0,100.0,2901,16.0,74,usa,amc hornet
+15.0,6,250.0,100.0,3336,17.0,74,usa,chevrolet nova
+31.0,4,79.0,67.0,1950,19.0,74,japan,datsun b210
+26.0,4,122.0,80.0,2451,16.5,74,usa,ford pinto
+32.0,4,71.0,65.0,1836,21.0,74,japan,toyota corolla 1200
+25.0,4,140.0,75.0,2542,17.0,74,usa,chevrolet vega
+16.0,6,250.0,100.0,3781,17.0,74,usa,chevrolet chevelle malibu classic
+16.0,6,258.0,110.0,3632,18.0,74,usa,amc matador
+18.0,6,225.0,105.0,3613,16.5,74,usa,plymouth satellite sebring
+16.0,8,302.0,140.0,4141,14.0,74,usa,ford gran torino
+13.0,8,350.0,150.0,4699,14.5,74,usa,buick century luxus (sw)
+14.0,8,318.0,150.0,4457,13.5,74,usa,dodge coronet custom (sw)
+14.0,8,302.0,140.0,4638,16.0,74,usa,ford gran torino (sw)
+14.0,8,304.0,150.0,4257,15.5,74,usa,amc matador (sw)
+29.0,4,98.0,83.0,2219,16.5,74,europe,audi fox
+26.0,4,79.0,67.0,1963,15.5,74,europe,volkswagen dasher
+26.0,4,97.0,78.0,2300,14.5,74,europe,opel manta
+31.0,4,76.0,52.0,1649,16.5,74,japan,toyota corona
+32.0,4,83.0,61.0,2003,19.0,74,japan,datsun 710
+28.0,4,90.0,75.0,2125,14.5,74,usa,dodge colt
+24.0,4,90.0,75.0,2108,15.5,74,europe,fiat 128
+26.0,4,116.0,75.0,2246,14.0,74,europe,fiat 124 tc
+24.0,4,120.0,97.0,2489,15.0,74,japan,honda civic
+26.0,4,108.0,93.0,2391,15.5,74,japan,subaru
+31.0,4,79.0,67.0,2000,16.0,74,europe,fiat x1.9
+19.0,6,225.0,95.0,3264,16.0,75,usa,plymouth valiant custom
+18.0,6,250.0,105.0,3459,16.0,75,usa,chevrolet nova
+15.0,6,250.0,72.0,3432,21.0,75,usa,mercury monarch
+15.0,6,250.0,72.0,3158,19.5,75,usa,ford maverick
+16.0,8,400.0,170.0,4668,11.5,75,usa,pontiac catalina
+15.0,8,350.0,145.0,4440,14.0,75,usa,chevrolet bel air
+16.0,8,318.0,150.0,4498,14.5,75,usa,plymouth grand fury
+14.0,8,351.0,148.0,4657,13.5,75,usa,ford ltd
+17.0,6,231.0,110.0,3907,21.0,75,usa,buick century
+16.0,6,250.0,105.0,3897,18.5,75,usa,chevroelt chevelle malibu
+15.0,6,258.0,110.0,3730,19.0,75,usa,amc matador
+18.0,6,225.0,95.0,3785,19.0,75,usa,plymouth fury
+21.0,6,231.0,110.0,3039,15.0,75,usa,buick skyhawk
+20.0,8,262.0,110.0,3221,13.5,75,usa,chevrolet monza 2+2
+13.0,8,302.0,129.0,3169,12.0,75,usa,ford mustang ii
+29.0,4,97.0,75.0,2171,16.0,75,japan,toyota corolla
+23.0,4,140.0,83.0,2639,17.0,75,usa,ford pinto
+20.0,6,232.0,100.0,2914,16.0,75,usa,amc gremlin
+23.0,4,140.0,78.0,2592,18.5,75,usa,pontiac astro
+24.0,4,134.0,96.0,2702,13.5,75,japan,toyota corona
+25.0,4,90.0,71.0,2223,16.5,75,europe,volkswagen dasher
+24.0,4,119.0,97.0,2545,17.0,75,japan,datsun 710
+18.0,6,171.0,97.0,2984,14.5,75,usa,ford pinto
+29.0,4,90.0,70.0,1937,14.0,75,europe,volkswagen rabbit
+19.0,6,232.0,90.0,3211,17.0,75,usa,amc pacer
+23.0,4,115.0,95.0,2694,15.0,75,europe,audi 100ls
+23.0,4,120.0,88.0,2957,17.0,75,europe,peugeot 504
+22.0,4,121.0,98.0,2945,14.5,75,europe,volvo 244dl
+25.0,4,121.0,115.0,2671,13.5,75,europe,saab 99le
+33.0,4,91.0,53.0,1795,17.5,75,japan,honda civic cvcc
+28.0,4,107.0,86.0,2464,15.5,76,europe,fiat 131
+25.0,4,116.0,81.0,2220,16.9,76,europe,opel 1900
+25.0,4,140.0,92.0,2572,14.9,76,usa,capri ii
+26.0,4,98.0,79.0,2255,17.7,76,usa,dodge colt
+27.0,4,101.0,83.0,2202,15.3,76,europe,renault 12tl
+17.5,8,305.0,140.0,4215,13.0,76,usa,chevrolet chevelle malibu classic
+16.0,8,318.0,150.0,4190,13.0,76,usa,dodge coronet brougham
+15.5,8,304.0,120.0,3962,13.9,76,usa,amc matador
+14.5,8,351.0,152.0,4215,12.8,76,usa,ford gran torino
+22.0,6,225.0,100.0,3233,15.4,76,usa,plymouth valiant
+22.0,6,250.0,105.0,3353,14.5,76,usa,chevrolet nova
+24.0,6,200.0,81.0,3012,17.6,76,usa,ford maverick
+22.5,6,232.0,90.0,3085,17.6,76,usa,amc hornet
+29.0,4,85.0,52.0,2035,22.2,76,usa,chevrolet chevette
+24.5,4,98.0,60.0,2164,22.1,76,usa,chevrolet woody
+29.0,4,90.0,70.0,1937,14.2,76,europe,vw rabbit
+33.0,4,91.0,53.0,1795,17.4,76,japan,honda civic
+20.0,6,225.0,100.0,3651,17.7,76,usa,dodge aspen se
+18.0,6,250.0,78.0,3574,21.0,76,usa,ford granada ghia
+18.5,6,250.0,110.0,3645,16.2,76,usa,pontiac ventura sj
+17.5,6,258.0,95.0,3193,17.8,76,usa,amc pacer d/l
+29.5,4,97.0,71.0,1825,12.2,76,europe,volkswagen rabbit
+32.0,4,85.0,70.0,1990,17.0,76,japan,datsun b-210
+28.0,4,97.0,75.0,2155,16.4,76,japan,toyota corolla
+26.5,4,140.0,72.0,2565,13.6,76,usa,ford pinto
+20.0,4,130.0,102.0,3150,15.7,76,europe,volvo 245
+13.0,8,318.0,150.0,3940,13.2,76,usa,plymouth volare premier v8
+19.0,4,120.0,88.0,3270,21.9,76,europe,peugeot 504
+19.0,6,156.0,108.0,2930,15.5,76,japan,toyota mark ii
+16.5,6,168.0,120.0,3820,16.7,76,europe,mercedes-benz 280s
+16.5,8,350.0,180.0,4380,12.1,76,usa,cadillac seville
+13.0,8,350.0,145.0,4055,12.0,76,usa,chevy c10
+13.0,8,302.0,130.0,3870,15.0,76,usa,ford f108
+13.0,8,318.0,150.0,3755,14.0,76,usa,dodge d100
+31.5,4,98.0,68.0,2045,18.5,77,japan,honda accord cvcc
+30.0,4,111.0,80.0,2155,14.8,77,usa,buick opel isuzu deluxe
+36.0,4,79.0,58.0,1825,18.6,77,europe,renault 5 gtl
+25.5,4,122.0,96.0,2300,15.5,77,usa,plymouth arrow gs
+33.5,4,85.0,70.0,1945,16.8,77,japan,datsun f-10 hatchback
+17.5,8,305.0,145.0,3880,12.5,77,usa,chevrolet caprice classic
+17.0,8,260.0,110.0,4060,19.0,77,usa,oldsmobile cutlass supreme
+15.5,8,318.0,145.0,4140,13.7,77,usa,dodge monaco brougham
+15.0,8,302.0,130.0,4295,14.9,77,usa,mercury cougar brougham
+17.5,6,250.0,110.0,3520,16.4,77,usa,chevrolet concours
+20.5,6,231.0,105.0,3425,16.9,77,usa,buick skylark
+19.0,6,225.0,100.0,3630,17.7,77,usa,plymouth volare custom
+18.5,6,250.0,98.0,3525,19.0,77,usa,ford granada
+16.0,8,400.0,180.0,4220,11.1,77,usa,pontiac grand prix lj
+15.5,8,350.0,170.0,4165,11.4,77,usa,chevrolet monte carlo landau
+15.5,8,400.0,190.0,4325,12.2,77,usa,chrysler cordoba
+16.0,8,351.0,149.0,4335,14.5,77,usa,ford thunderbird
+29.0,4,97.0,78.0,1940,14.5,77,europe,volkswagen rabbit custom
+24.5,4,151.0,88.0,2740,16.0,77,usa,pontiac sunbird coupe
+26.0,4,97.0,75.0,2265,18.2,77,japan,toyota corolla liftback
+25.5,4,140.0,89.0,2755,15.8,77,usa,ford mustang ii 2+2
+30.5,4,98.0,63.0,2051,17.0,77,usa,chevrolet chevette
+33.5,4,98.0,83.0,2075,15.9,77,usa,dodge colt m/m
+30.0,4,97.0,67.0,1985,16.4,77,japan,subaru dl
+30.5,4,97.0,78.0,2190,14.1,77,europe,volkswagen dasher
+22.0,6,146.0,97.0,2815,14.5,77,japan,datsun 810
+21.5,4,121.0,110.0,2600,12.8,77,europe,bmw 320i
+21.5,3,80.0,110.0,2720,13.5,77,japan,mazda rx-4
+43.1,4,90.0,48.0,1985,21.5,78,europe,volkswagen rabbit custom diesel
+36.1,4,98.0,66.0,1800,14.4,78,usa,ford fiesta
+32.8,4,78.0,52.0,1985,19.4,78,japan,mazda glc deluxe
+39.4,4,85.0,70.0,2070,18.6,78,japan,datsun b210 gx
+36.1,4,91.0,60.0,1800,16.4,78,japan,honda civic cvcc
+19.9,8,260.0,110.0,3365,15.5,78,usa,oldsmobile cutlass salon brougham
+19.4,8,318.0,140.0,3735,13.2,78,usa,dodge diplomat
+20.2,8,302.0,139.0,3570,12.8,78,usa,mercury monarch ghia
+19.2,6,231.0,105.0,3535,19.2,78,usa,pontiac phoenix lj
+20.5,6,200.0,95.0,3155,18.2,78,usa,chevrolet malibu
+20.2,6,200.0,85.0,2965,15.8,78,usa,ford fairmont (auto)
+25.1,4,140.0,88.0,2720,15.4,78,usa,ford fairmont (man)
+20.5,6,225.0,100.0,3430,17.2,78,usa,plymouth volare
+19.4,6,232.0,90.0,3210,17.2,78,usa,amc concord
+20.6,6,231.0,105.0,3380,15.8,78,usa,buick century special
+20.8,6,200.0,85.0,3070,16.7,78,usa,mercury zephyr
+18.6,6,225.0,110.0,3620,18.7,78,usa,dodge aspen
+18.1,6,258.0,120.0,3410,15.1,78,usa,amc concord d/l
+19.2,8,305.0,145.0,3425,13.2,78,usa,chevrolet monte carlo landau
+17.7,6,231.0,165.0,3445,13.4,78,usa,buick regal sport coupe (turbo)
+18.1,8,302.0,139.0,3205,11.2,78,usa,ford futura
+17.5,8,318.0,140.0,4080,13.7,78,usa,dodge magnum xe
+30.0,4,98.0,68.0,2155,16.5,78,usa,chevrolet chevette
+27.5,4,134.0,95.0,2560,14.2,78,japan,toyota corona
+27.2,4,119.0,97.0,2300,14.7,78,japan,datsun 510
+30.9,4,105.0,75.0,2230,14.5,78,usa,dodge omni
+21.1,4,134.0,95.0,2515,14.8,78,japan,toyota celica gt liftback
+23.2,4,156.0,105.0,2745,16.7,78,usa,plymouth sapporo
+23.8,4,151.0,85.0,2855,17.6,78,usa,oldsmobile starfire sx
+23.9,4,119.0,97.0,2405,14.9,78,japan,datsun 200-sx
+20.3,5,131.0,103.0,2830,15.9,78,europe,audi 5000
+17.0,6,163.0,125.0,3140,13.6,78,europe,volvo 264gl
+21.6,4,121.0,115.0,2795,15.7,78,europe,saab 99gle
+16.2,6,163.0,133.0,3410,15.8,78,europe,peugeot 604sl
+31.5,4,89.0,71.0,1990,14.9,78,europe,volkswagen scirocco
+29.5,4,98.0,68.0,2135,16.6,78,japan,honda accord lx
+21.5,6,231.0,115.0,3245,15.4,79,usa,pontiac lemans v6
+19.8,6,200.0,85.0,2990,18.2,79,usa,mercury zephyr 6
+22.3,4,140.0,88.0,2890,17.3,79,usa,ford fairmont 4
+20.2,6,232.0,90.0,3265,18.2,79,usa,amc concord dl 6
+20.6,6,225.0,110.0,3360,16.6,79,usa,dodge aspen 6
+17.0,8,305.0,130.0,3840,15.4,79,usa,chevrolet caprice classic
+17.6,8,302.0,129.0,3725,13.4,79,usa,ford ltd landau
+16.5,8,351.0,138.0,3955,13.2,79,usa,mercury grand marquis
+18.2,8,318.0,135.0,3830,15.2,79,usa,dodge st. regis
+16.9,8,350.0,155.0,4360,14.9,79,usa,buick estate wagon (sw)
+15.5,8,351.0,142.0,4054,14.3,79,usa,ford country squire (sw)
+19.2,8,267.0,125.0,3605,15.0,79,usa,chevrolet malibu classic (sw)
+18.5,8,360.0,150.0,3940,13.0,79,usa,chrysler lebaron town @ country (sw)
+31.9,4,89.0,71.0,1925,14.0,79,europe,vw rabbit custom
+34.1,4,86.0,65.0,1975,15.2,79,japan,maxda glc deluxe
+35.7,4,98.0,80.0,1915,14.4,79,usa,dodge colt hatchback custom
+27.4,4,121.0,80.0,2670,15.0,79,usa,amc spirit dl
+25.4,5,183.0,77.0,3530,20.1,79,europe,mercedes benz 300d
+23.0,8,350.0,125.0,3900,17.4,79,usa,cadillac eldorado
+27.2,4,141.0,71.0,3190,24.8,79,europe,peugeot 504
+23.9,8,260.0,90.0,3420,22.2,79,usa,oldsmobile cutlass salon brougham
+34.2,4,105.0,70.0,2200,13.2,79,usa,plymouth horizon
+34.5,4,105.0,70.0,2150,14.9,79,usa,plymouth horizon tc3
+31.8,4,85.0,65.0,2020,19.2,79,japan,datsun 210
+37.3,4,91.0,69.0,2130,14.7,79,europe,fiat strada custom
+28.4,4,151.0,90.0,2670,16.0,79,usa,buick skylark limited
+28.8,6,173.0,115.0,2595,11.3,79,usa,chevrolet citation
+26.8,6,173.0,115.0,2700,12.9,79,usa,oldsmobile omega brougham
+33.5,4,151.0,90.0,2556,13.2,79,usa,pontiac phoenix
+41.5,4,98.0,76.0,2144,14.7,80,europe,vw rabbit
+38.1,4,89.0,60.0,1968,18.8,80,japan,toyota corolla tercel
+32.1,4,98.0,70.0,2120,15.5,80,usa,chevrolet chevette
+37.2,4,86.0,65.0,2019,16.4,80,japan,datsun 310
+28.0,4,151.0,90.0,2678,16.5,80,usa,chevrolet citation
+26.4,4,140.0,88.0,2870,18.1,80,usa,ford fairmont
+24.3,4,151.0,90.0,3003,20.1,80,usa,amc concord
+19.1,6,225.0,90.0,3381,18.7,80,usa,dodge aspen
+34.3,4,97.0,78.0,2188,15.8,80,europe,audi 4000
+29.8,4,134.0,90.0,2711,15.5,80,japan,toyota corona liftback
+31.3,4,120.0,75.0,2542,17.5,80,japan,mazda 626
+37.0,4,119.0,92.0,2434,15.0,80,japan,datsun 510 hatchback
+32.2,4,108.0,75.0,2265,15.2,80,japan,toyota corolla
+46.6,4,86.0,65.0,2110,17.9,80,japan,mazda glc
+27.9,4,156.0,105.0,2800,14.4,80,usa,dodge colt
+40.8,4,85.0,65.0,2110,19.2,80,japan,datsun 210
+44.3,4,90.0,48.0,2085,21.7,80,europe,vw rabbit c (diesel)
+43.4,4,90.0,48.0,2335,23.7,80,europe,vw dasher (diesel)
+36.4,5,121.0,67.0,2950,19.9,80,europe,audi 5000s (diesel)
+30.0,4,146.0,67.0,3250,21.8,80,europe,mercedes-benz 240d
+44.6,4,91.0,67.0,1850,13.8,80,japan,honda civic 1500 gl
+40.9,4,85.0,,1835,17.3,80,europe,renault lecar deluxe
+33.8,4,97.0,67.0,2145,18.0,80,japan,subaru dl
+29.8,4,89.0,62.0,1845,15.3,80,europe,vokswagen rabbit
+32.7,6,168.0,132.0,2910,11.4,80,japan,datsun 280-zx
+23.7,3,70.0,100.0,2420,12.5,80,japan,mazda rx-7 gs
+35.0,4,122.0,88.0,2500,15.1,80,europe,triumph tr7 coupe
+23.6,4,140.0,,2905,14.3,80,usa,ford mustang cobra
+32.4,4,107.0,72.0,2290,17.0,80,japan,honda accord
+27.2,4,135.0,84.0,2490,15.7,81,usa,plymouth reliant
+26.6,4,151.0,84.0,2635,16.4,81,usa,buick skylark
+25.8,4,156.0,92.0,2620,14.4,81,usa,dodge aries wagon (sw)
+23.5,6,173.0,110.0,2725,12.6,81,usa,chevrolet citation
+30.0,4,135.0,84.0,2385,12.9,81,usa,plymouth reliant
+39.1,4,79.0,58.0,1755,16.9,81,japan,toyota starlet
+39.0,4,86.0,64.0,1875,16.4,81,usa,plymouth champ
+35.1,4,81.0,60.0,1760,16.1,81,japan,honda civic 1300
+32.3,4,97.0,67.0,2065,17.8,81,japan,subaru
+37.0,4,85.0,65.0,1975,19.4,81,japan,datsun 210 mpg
+37.7,4,89.0,62.0,2050,17.3,81,japan,toyota tercel
+34.1,4,91.0,68.0,1985,16.0,81,japan,mazda glc 4
+34.7,4,105.0,63.0,2215,14.9,81,usa,plymouth horizon 4
+34.4,4,98.0,65.0,2045,16.2,81,usa,ford escort 4w
+29.9,4,98.0,65.0,2380,20.7,81,usa,ford escort 2h
+33.0,4,105.0,74.0,2190,14.2,81,europe,volkswagen jetta
+34.5,4,100.0,,2320,15.8,81,europe,renault 18i
+33.7,4,107.0,75.0,2210,14.4,81,japan,honda prelude
+32.4,4,108.0,75.0,2350,16.8,81,japan,toyota corolla
+32.9,4,119.0,100.0,2615,14.8,81,japan,datsun 200sx
+31.6,4,120.0,74.0,2635,18.3,81,japan,mazda 626
+28.1,4,141.0,80.0,3230,20.4,81,europe,peugeot 505s turbo diesel
+30.7,6,145.0,76.0,3160,19.6,81,europe,volvo diesel
+25.4,6,168.0,116.0,2900,12.6,81,japan,toyota cressida
+24.2,6,146.0,120.0,2930,13.8,81,japan,datsun 810 maxima
+22.4,6,231.0,110.0,3415,15.8,81,usa,buick century
+26.6,8,350.0,105.0,3725,19.0,81,usa,oldsmobile cutlass ls
+20.2,6,200.0,88.0,3060,17.1,81,usa,ford granada gl
+17.6,6,225.0,85.0,3465,16.6,81,usa,chrysler lebaron salon
+28.0,4,112.0,88.0,2605,19.6,82,usa,chevrolet cavalier
+27.0,4,112.0,88.0,2640,18.6,82,usa,chevrolet cavalier wagon
+34.0,4,112.0,88.0,2395,18.0,82,usa,chevrolet cavalier 2-door
+31.0,4,112.0,85.0,2575,16.2,82,usa,pontiac j2000 se hatchback
+29.0,4,135.0,84.0,2525,16.0,82,usa,dodge aries se
+27.0,4,151.0,90.0,2735,18.0,82,usa,pontiac phoenix
+24.0,4,140.0,92.0,2865,16.4,82,usa,ford fairmont futura
+23.0,4,151.0,,3035,20.5,82,usa,amc concord dl
+36.0,4,105.0,74.0,1980,15.3,82,europe,volkswagen rabbit l
+37.0,4,91.0,68.0,2025,18.2,82,japan,mazda glc custom l
+31.0,4,91.0,68.0,1970,17.6,82,japan,mazda glc custom
+38.0,4,105.0,63.0,2125,14.7,82,usa,plymouth horizon miser
+36.0,4,98.0,70.0,2125,17.3,82,usa,mercury lynx l
+36.0,4,120.0,88.0,2160,14.5,82,japan,nissan stanza xe
+36.0,4,107.0,75.0,2205,14.5,82,japan,honda accord
+34.0,4,108.0,70.0,2245,16.9,82,japan,toyota corolla
+38.0,4,91.0,67.0,1965,15.0,82,japan,honda civic
+32.0,4,91.0,67.0,1965,15.7,82,japan,honda civic (auto)
+38.0,4,91.0,67.0,1995,16.2,82,japan,datsun 310 gx
+25.0,6,181.0,110.0,2945,16.4,82,usa,buick century limited
+38.0,6,262.0,85.0,3015,17.0,82,usa,oldsmobile cutlass ciera (diesel)
+26.0,4,156.0,92.0,2585,14.5,82,usa,chrysler lebaron medallion
+22.0,6,232.0,112.0,2835,14.7,82,usa,ford granada l
+32.0,4,144.0,96.0,2665,13.9,82,japan,toyota celica gt
+36.0,4,135.0,84.0,2370,13.0,82,usa,dodge charger 2.2
+27.0,4,151.0,90.0,2950,17.3,82,usa,chevrolet camaro
+27.0,4,140.0,86.0,2790,15.6,82,usa,ford mustang gl
+44.0,4,97.0,52.0,2130,24.6,82,europe,vw pickup
+32.0,4,135.0,84.0,2295,11.6,82,usa,dodge rampage
+28.0,4,120.0,79.0,2625,18.6,82,usa,ford ranger
+31.0,4,119.0,82.0,2720,19.4,82,usa,chevy s-10


Property changes on: trunk/Master/texmf-dist/doc/lualatex/lua-regression/example/mpg.csv
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/lualatex/lua-regression/lua-regression-doc.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/lualatex/lua-regression/lua-regression-doc.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/lualatex/lua-regression/lua-regression-doc.pdf	2025-04-06 23:42:02 UTC (rev 74867)
+++ trunk/Master/texmf-dist/doc/lualatex/lua-regression/lua-regression-doc.pdf	2025-04-07 19:47:17 UTC (rev 74868)

Property changes on: trunk/Master/texmf-dist/doc/lualatex/lua-regression/lua-regression-doc.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/lualatex/lua-regression/lua-regression-doc.tex
===================================================================
--- trunk/Master/texmf-dist/doc/lualatex/lua-regression/lua-regression-doc.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/lualatex/lua-regression/lua-regression-doc.tex	2025-04-07 19:47:17 UTC (rev 74868)
@@ -0,0 +1,440 @@
+%! Author = George
+%! Date = 06/04/2025
+%! Compiler = lualatex
+
+
+% Preamble
+\documentclass[11pt]{article}
+
+% Packages
+\usepackage{standalone}
+\usepackage{amsmath}
+\usepackage{amssymb}
+
+\usepackage[margin=2.5cm]{geometry}
+
+\usepackage{pgfplots}
+\usepackage{pgfplotstable}
+\pgfplotsset{compat=1.18}
+\usepgfplotslibrary{fillbetween}
+
+\usepackage{tabularray}
+\usepackage{multicol}
+\usepackage{minted}
+\usepackage[hidelinks]{hyperref}
+\usepackage{zref-clever}
+\usepackage{tcolorbox}
+
+\usepackage{lua-regression}
+
+% Colours
+\definecolor{p1}{HTML}{332288}
+\definecolor{p2}{HTML}{0077BB}
+\definecolor{p3}{HTML}{88CCEE}
+\definecolor{p4}{HTML}{44AA99}
+\definecolor{p5}{HTML}{117733}
+\definecolor{p6}{HTML}{999933}
+\definecolor{p7}{HTML}{DDCC77}
+\definecolor{p8}{HTML}{EE7733}
+\definecolor{p9}{HTML}{CC6677}
+\definecolor{p10}{HTML}{CC3311}
+\definecolor{p11}{HTML}{882255}
+\definecolor{p12}{HTML}{AA4499}
+\definecolor{p13}{HTML}{EE3377}
+
+\usepackage[backend=biber,style=numeric]{biblatex}
+
+% Document
+\begin{document}
+    \title{The {\ttfamily lua-regression} package}
+    \author{George Allison\thanks{\href{mailto:GHAllison1 at sheffield.ac.uk}{\ttfamily mailto:GHAllison1 at sheffield.ac.uk}}}
+    \date{v1.0.0\\ \today}
+
+    \maketitle
+
+    \begin{abstract}
+        The {\ttfamily lua-regression} package is a Lua\LaTeX package that provides a simple interface for performing polynomial regression on data sets.
+        It allows users to specify the order of the polynomial regression, the columns of the data set to use, and whether to plot the results.
+        The package also includes options for confidence intervals and error bands.
+
+        \vspace{1em}
+        \noindent
+        \textbf{Keywords:} LuaLaTeX, regression, plotting, data analysis
+    \end{abstract}
+
+    \tableofcontents
+
+    \pagebreak
+
+    \section{What is {\ttfamily lua-regression}?}
+
+    The {\ttfamily lua-regression} package is a Lua\LaTeX package that provides a simple interface for performing polynomial regression on data sets within \LaTeX. For example:
+
+    \begin{minted}[autogobble]{latex}
+        \luaregression[plot=true, order=2, xcol=1, ycol=2]{data.csv}
+    \end{minted}
+
+    \noindent
+    The above code will perform a polynomial regression of order 2 on the data in the file {\ttfamily data.csv}, using the first column as the x-values and the second column as the y-values.
+    The plot result will only work in a tikzpicture enviroment.
+
+
+    \subsection{About}
+
+    The main functions of the {\ttfamily lua-regression} package are written purely in Lua and integrated into \LaTeX via Lua\LaTeX.
+    This code was written to provide a \LaTeX consistent interface for performing polynomial regression on data sets, without the need for external software or libraries.
+    The package uses the Lua programming language to perform the regression calculations, and it can be easily integrated into existing \LaTeX documents using the Lua\LaTeX engine.
+    Currently, if you wish to perform a regression on a data set, you must use an external program to preform the regression and then import the results or pgf file into \LaTeX.
+    This requires extra steps and can be unnecessarily complicated to maintain styling.
+
+    The {\ttfamily lua-regression} package aims to simplify this process by providing a simple interface for performing polynomial regression directly within \LaTeX.
+    The target audience for this package is primarily, students, researchers, and academics who are already working in \LaTeX and need to perform polynomial regression on data sets as part of their work.
+    The package is designed to be easy to use and flexible, allowing users to specify the order of the polynomial regression, the columns of the data set to use, and whether to plot the results.
+    The package also includes options for confidence intervals and error bands, making it a powerful tool for data analysis and visualization that creates plots similar to those produced by the Python library {\ttfamily Seaborn}.
+
+    Using Lua allows for a clearer and more efficient implementation of the regression calculations, as well as better integration with \LaTeX thanks to Lua\LaTeX.
+    It further benefits from not requiring any external dependencies, or the need to use {\ttfamily --shell-escape} to run.
+
+    \subsection{Features}
+
+    Currently, the {\ttfamily lua-regression} package supports the following features:
+    \begin{itemize}
+        \item Polynomial regression of any order.
+        \item Plotting of the regression results using PGFPlots.
+        \item Confidence intervals and error bands using the bootstrap method.
+        \item Simple interface for specifying data sets and options.
+        \item No external dependencies or {\ttfamily shell-escape} required.
+        \item Support for CSV format data files.
+        \item Perform $R^2$ tests on the data.
+        \item Support for significant figures.
+        \item Add and remove equation and $R^2$ from the legend.
+        \item Outputs equations and $R^2$ values to LaTeX commands so they can be called in the document.
+    \end{itemize}
+
+    \subsection{Acknowledgements}
+
+    Rob S., for constant encouragement and moral support.
+
+    Max K., for providing feedback on the package and its features.
+
+    \section{Installation}
+
+    \subsection{Requirements}
+    
+    The {\ttfamily lua-regression} package requires compilation with Lua\LaTeX. It has been tested on Lua 5.2 and higher.
+    Further some additional packages are required:
+
+    \begin{multicols}{4}
+        {\ttfamily
+            \begin{itemize}
+                \item pfgkeys
+                \item luacode
+                \item pgfplots
+                \item tikz
+            \end{itemize}
+        }
+    \end{multicols}
+
+    The packages {\ttfamily pgfplots} and {\ttfamily tikz} are not strictly required for running the package.
+    However, they are needed for drawing the generated equations or confidence intervals on the plot.
+
+    \subsection{Install {\ttfamily lua-regression}}
+
+    The package manager for your local TeX distribution should install the package fine.
+    However, the package can also be downloaded independently and placed in your local texmf directory.
+    Once you have a copy of {\ttfamily lua-regression} installed, include the following in your preamble:
+
+    \begin{minted}[autogobble]{latex}
+        \usepackage{lua-regression}
+    \end{minted}
+
+    \subsection{Todo}
+
+    There are probably bugs and use cases that I have not thought of.
+    This code was originally written for my own use, and I have not tested it on all possible data sets.
+    Thus, it only includes the features I needed at the time of writing.
+    Future enhancements to {\ttfamily lua-regression} may include:
+
+    \begin{itemize}
+        \item Support for other regression types (e.g., exponential, etc.).
+        \item Improved error handling and debugging options.
+        \item More advanced plotting options and customization.
+        \item Support for other data formats (e.g., JSON, XML, etc.).
+        \item Robust regression methods.
+        \item Support for plotting multiple regression lines with one command.
+        \item Restructuring the code to be more modular and easier to maintain.
+    \end{itemize}
+
+    \section{Usage}
+
+    \subsection{Calling the Package}
+
+    The {\ttfamily lua-regression} package is called using the following command:
+
+    \begin{minted}[autogobble]{latex}
+        \luaregression[options]{data.csv}
+    \end{minted}
+
+    \noindent
+    The options for {\ttfamily lua-regression} are seen in \zcref{tab:options}.
+
+    \noindent
+    \begin{table}
+
+        \centering
+        \begin{tblr}{
+            width=\textwidth,
+            hline{1,2,Z}={1pt, solid},
+            colspec = {Q[l,m] X[l,m] X[l,m]},
+            row{1} = {font=\bfseries}
+        }
+        Option & Description & Type \\
+        xcol & The column index for the x-values & integer (default: 1) \\
+        ycol & The column index for the y-values & integer (default: 2) \\
+        ci & Whether to include confidence intervals & boolean (default: false) \\
+        z-threshold & The Z-score threshold for confidence intervals & number (default: null) \\
+        sig-figures & The number of significant figures to display & integer (default: 4) \\
+        order & The order of the polynomial regression & integer (default: 1) \\
+        plot & Whether to plot the results & boolean (default: false) \\
+        pgf-options & Additional PGF options for plotting & string (default: mark=none,smooth) \\
+        eq & Whether to show the equation in the plot legend & boolean (default: false) \\
+        r2 & Whether to show the R² value in the plot legend & boolean (default: false) \\
+        debug & Whether to enable debug mode & boolean (default: false) \\
+        bootstrap & The number of bootstrap samples for confidence intervals & integer (default: 1000) \\
+        cicolor & The color for the confidence interval fill & string (default: blue) \\
+        cifillopacity & The opacity for the confidence interval fill & number (default: 0.2) \\
+        \end{tblr}
+
+        \caption{Options for the {\ttfamily lua-regression} package.}
+        \zlabel{tab:options}
+
+    \end{table}
+
+    \noindent
+    Additionally, specific values from the package can be called in the document using the following commands:
+
+    \begin{minted}[autogobble, breaklines, breakanywhere]{latex}
+        \polyR - The R squared value of the regression.
+        \polyeq - The polynomial equation of the regression in a format pgfplots can interpret.
+        \printeq - The polynomial equation of the regression in a visually nice format.
+        \qlwr - The points for the lower confidence interval.
+        \qupr - The points for the upper confidence interval.
+    \end{minted}
+
+    \noindent
+    These can be called in the document at any point after the {\ttfamily lua-regression} command.
+
+    \section{Example}
+
+    The following example demonstrates how to use the {\ttfamily lua-regression} package to perform polynomial regressions on a data set and plot the results.
+    The data set used in this example is a CSV file for the seaborn-data GitHub repository, which contains information about the miles per gallon (MPG) of various cars.
+
+    \noindent
+    \href{https://github.com/mwaskom/seaborn-data}{Seaborn-data Github repository}
+
+    \begin{minted}[autogobble, breaklines, breakanywhere]{latex}
+        \luaregression[xcol = 4, ycol = 5, order = 1]{example/mpg.csv}
+
+        The equation for the linear regression for the MPG data set is $\printeq$ and the $R^2$ value is $\polyR$.
+    \end{minted}
+
+    \luaregression[xcol = 4, ycol = 5, order = 1]{example/mpg.csv}
+
+    \noindent
+    The equation for the linear regression for the MPG data set is $\printeq$ and the $R^2$ value is $\polyR$.
+
+    \pagebreak
+
+    \subsection{A linear regression of order 1}
+
+    The following code performs a polynomial regression of order 1 on the MPG data set, using the first column as the x-values and the second column as the y-values.
+    Seen in \zcref{fig:example-1}.
+
+    \begin{minted}[autogobble, breaklines, breakanywhere]{latex}
+        \begin{tikzpicture}
+            \begin{axis}[
+                height=6.45cm,
+                width=\textwidth,
+                domain=0:300,
+                samples=1000,
+                xmin=25,
+                xmax=240,
+                xlabel=horsepower,
+                ytick={},
+                xtick={},
+                ymax=6000,
+                ymin=1250,
+                ylabel=weight,
+                grid=both,
+                legend columns = 2,
+                legend style={cells={align=left},at={(0.45,-0.22)},anchor=north},
+                legend cell align=left,
+                major grid style={line width=.2pt,draw=gray!20},
+                every axis/.append style={axis line style={gray!80, line width=0.75pt}, tick style={gray!95}}
+            ]
+
+            \addlegendimage{p4, mark=*, thick}
+            \addlegendimage{p8, thick}
+
+            \pgfplotstableread[col sep=comma]{example/mpg.csv}\datatable
+
+            \addplot [p4,mark=*,fill opacity=0.75, draw opacity=0] table [only marks,col sep=comma,x=horsepower,y=weight]{\datatable};
+
+            \luaregression[xcol = 4, ycol = 5, plot = true, eq = true, r2 = true, order = 1, ci = true]{example/mpg.csv}
+
+            \end{axis}
+        \end{tikzpicture}
+    \end{minted}
+
+    \pagebreak
+
+    \begin{figure}[h]
+        \begin{tikzpicture}
+            \begin{axis}[
+                height=.5\textheight,
+                width=\textwidth,
+                domain=0:300,
+                samples=1000,
+                xmin=25,
+                xmax=240,
+                xlabel=horsepower,
+                ytick={},
+                xtick={},
+                ymax=6000,
+                ymin=1250,
+                ylabel=weight,
+                grid=both,
+                legend columns = 2,
+                legend style={cells={align=left},at={(0.45,-0.22)},anchor=north},
+                legend cell align=left,
+                major grid style={line width=.2pt,draw=gray!20},
+                every axis/.append style={axis line style={gray!80, line width=0.75pt}, tick style={gray!95}}
+            ]
+
+            \addlegendimage{p4, mark=*, thick}
+            \addlegendimage{p8, thick}
+
+            \pgfplotstableread[col sep=comma]{example/mpg.csv}\datatable
+
+            \addplot [p4,mark=*,fill opacity=0.75, draw opacity=0] table [only marks,col sep=comma,x=horsepower,y=weight]{\datatable};
+
+            \luaregression[xcol = 4, ycol = 5, plot = true, eq = true, r2 = true, order = 1, ci = true]{example/mpg.csv}
+
+            \end{axis}
+        \end{tikzpicture}
+
+        \caption{Polynomial regression of order 1 on the MPG data set. The plot shows the data points, the fitted polynomial regression line, and the confidence intervals.}
+        \zlabel{fig:example-1}
+    \end{figure}
+
+    \pagebreak
+
+    \subsection{A polynomial regression of order 2}
+
+    The following example demonstrates how to use the {\ttfamily lua-regression} package to perform polynomial regression of order 2 on the same data set.
+    Seen in \zcref{fig:example-2}.
+
+    \begin{minted}[autogobble, breaklines, breakanywhere]{latex}
+        \begin{tikzpicture}
+            \begin{axis}[
+                height=6.45cm,
+                width=\textwidth,
+                domain=0:300,
+                samples=1000,
+                xmin=25,
+                xmax=240,
+                xlabel=horsepower,
+                ytick={},
+                xtick={},
+                ymax=6000,
+                ymin=1250,
+                ylabel=weight,
+                grid=both,
+                legend columns = 2,
+                legend style={cells={align=left},at={(0.45,-0.22)},anchor=north},
+                legend cell align=left,
+                major grid style={line width=.2pt,draw=gray!20},
+                every axis/.append style={axis line style={gray!80, line width=0.75pt}, tick style={gray!95}}
+            ]
+
+            \addlegendimage{p4, mark=*, thick}
+            \addlegendimage{p8, thick}
+
+            \pgfplotstableread[col sep=comma]{example/mpg.csv}\datatable
+
+            \addplot [p4,mark=*,fill opacity=0.75, draw opacity=0] table [only marks,col sep=comma,x=horsepower,y=weight]{\datatable};
+
+            \luaregression[xcol = 4, ycol = 5, plot = true, eq = true, r2 = true, order = 2, ci = true]{example/mpg.csv}
+
+            \end{axis}
+        \end{tikzpicture}
+    \end{minted}
+
+    \pagebreak
+
+    \begin{figure}[h]
+        \begin{tikzpicture}
+            \begin{axis}[
+                height=.5\textheight,
+                width=\textwidth,
+                domain=0:300,
+                samples=1000,
+                xmin=25,
+                xmax=240,
+                xlabel=horsepower,
+                ytick={},
+                xtick={},
+                ymax=6000,
+                ymin=1250,
+                ylabel=weight,
+                grid=both,
+                legend columns = 2,
+                legend style={cells={align=left},at={(0.45,-0.22)},anchor=north},
+                legend cell align=left,
+                major grid style={line width=.2pt,draw=gray!20},
+                every axis/.append style={axis line style={gray!80, line width=0.75pt}, tick style={gray!95}}
+            ]
+
+            \addlegendimage{p4, mark=*, thick}
+            \addlegendimage{p8, thick}
+
+            \pgfplotstableread[col sep=comma]{example/mpg.csv}\datatable
+
+            \addplot [p4,mark=*,fill opacity=0.75, draw opacity=0] table [only marks,col sep=comma,x=horsepower,y=weight]{\datatable};
+
+            \luaregression[xcol = 4, ycol = 5, plot = true, eq = true, r2 = true, order = 2, ci = true]{example/mpg.csv}
+
+            \end{axis}
+        \end{tikzpicture}
+
+        \caption{Polynomial regression of order 2 on the MPG data set. The plot shows the data points, the fitted polynomial regression line, and the confidence intervals.}
+        \zlabel{fig:example-2}
+    \end{figure}
+
+    \pagebreak
+
+    \section{Changelog}
+
+    \subsection*{v1.0.0}
+
+    \begin{itemize}
+        \item Initial release of the {\ttfamily lua-regression} package.
+        \item Basic polynomial regression functionality.
+        \item Plotting support using PGFPlots.
+        \item Confidence intervals and error bands using the bootstrap method.
+        \item Simple interface for specifying data sets and options.
+        \item No external dependencies or {\ttfamily shell-escape} required.
+        \item Support for CSV format data files.
+        \item Perform $R^2$ tests on the data.
+        \item Support for significant figures.
+        \item Add and remove equation and $R^2$ from the legend.
+        \item Outputs equations and $R^2$ values to LaTeX commands so they can be called in the document.
+    \end{itemize}
+
+    \pagebreak
+
+    \section{Code}
+
+    \inputminted[autogobble, breaklines, breakanywhere, firstline=22, linenos]{latex}{../tex/lua-regression.sty}
+
+\end{document}
\ No newline at end of file


Property changes on: trunk/Master/texmf-dist/doc/lualatex/lua-regression/lua-regression-doc.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/lualatex/lua-regression/lua-regression.lua
===================================================================
--- trunk/Master/texmf-dist/tex/lualatex/lua-regression/lua-regression.lua	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/lualatex/lua-regression/lua-regression.lua	2025-04-07 19:47:17 UTC (rev 74868)
@@ -0,0 +1,605 @@
+-- Copyright (c) 2025 George Allison
+--
+-- This work may be distributed and/or modified under the
+-- conditions of the LaTeX Project Public License, either version 1.3
+-- of this license or any later version.
+-- The latest version of this license is in
+--   http://www.latex-project.org/lppl.txt
+-- and version 1.3 or later is part of all distributions of LaTeX
+-- version 2005/12/01 or later.
+--
+-- This work has the LPPL maintenance status `maintained'.
+--
+-- The Current Maintainer of this work is George Allison.
+--
+-- This work consists of the files lua-regression.sty and lua-regression.lua
+--
+-- This software is provided 'as is', without warranty of any kind,
+-- either expressed or implied, including, but not limited to, the
+-- implied warranties of merchantability and fitness for a
+-- particular purpose.
+
+-- Improved split function that handles empty fields in CSV
+function split(str, delim)
+    local result = {}
+    -- Handle edge case of empty string
+    if str == "" then return result end
+    
+    -- Handle trailing delimiter with a final empty field
+    if str:sub(-1) == delim then
+        str = str .. " "  -- Add a space to create a final empty field
+    end
+    
+    -- Special case for blank cells - two delimiters in a row
+    str = str:gsub(delim..delim, delim.." "..delim)  -- Replace ,, with , ,
+    
+    -- Split the string using Lua pattern matching
+    local pattern = string.format("([^%s]*)", delim)
+    for field in str:gmatch(pattern) do
+        table.insert(result, field)
+    end
+    
+    return result
+end
+
+-- Function to find the index of a column in the header
+function find_column_index(header, column_name)
+	for i, name in ipairs(header) do
+		if name == column_name then
+			return i
+		end
+	end
+	return nil -- Column name not found
+end
+
+-- Normalize data to improve numerical stability for polynomial regression
+function normalize_data(data)
+    local x_min, x_max = math.huge, -math.huge
+    for _, point in ipairs(data) do
+        x_min = math.min(x_min, point[1])
+        x_max = math.max(x_max, point[1])
+    end
+    
+    local x_range = x_max - x_min
+    local normalized = {}
+    for _, point in ipairs(data) do
+        -- Normalize to [0,1] range
+        local x_norm = (point[1] - x_min) / x_range
+        table.insert(normalized, {x_norm, point[2]})
+    end
+    
+    return normalized, x_min, x_range
+end
+
+-- Function to read a CSV file and store the data in a table
+function read_csv_to_table(file_path, xcol, ycol, options)
+    local data = {}
+    local file = io.open(file_path, "r")
+    if not file then
+        if options and options["debug"] then
+            log_error("\\textbf{Error:} Unable to open file " .. file_path)
+        end
+        return nil
+    end
+
+    -- Read first line (header) and remove BOM if present
+    local header_line = file:read("*l") or ""
+    header_line = header_line:gsub("^\239\187\191", "") -- Remove UTF-8 BOM
+    header_line = header_line:gsub("^%s*(.-)%s*$", "%1") -- Trim
+    local header = split(header_line, ',')
+
+    -- Debug: Print headers
+    if options and options["debug"] then
+        log_error("\\textbf{Debug:} Headers: " .. table.concat(header, ", ") .. "\\\\")
+    end
+
+    -- If xcol / ycol are names, convert them to column indices
+    if type(xcol) == "string" then
+        local idx = find_column_index(header, xcol)
+        if not idx then
+            if options and options["debug"] then
+                log_error("\\textbf{Error:} Column '" .. xcol .. "' not found in header")
+            end
+            file:close()
+            return nil
+        end
+        xcol = idx
+    end
+
+    if type(ycol) == "string" then
+        local idx = find_column_index(header, ycol)
+        if not idx then
+            if options and options["debug"] then
+                log_error("\\textbf{Error:} Column '" .. ycol .. "' not found in header.")
+            end
+            file:close()
+            return nil
+        end
+        ycol = idx
+    end
+
+    -- Read the data lines
+    local line_number = 1
+    local skipped_lines = 0
+    while true do
+        local line = file:read("*l")
+        if not line then break end
+
+        line = line:gsub("^%s*(.-)%s*$", "%1") -- Trim
+        if line ~= "" then
+            local values = split(line, ',')
+
+            -- Check if we have enough columns
+            if #values < math.max(xcol, ycol) then
+                if options and options["debug"] then
+                    log_error("\\textbf{Warning:} Line " .. line_number + 1 .. " has too few columns.\\\\")
+                end
+                skipped_lines = skipped_lines + 1
+            elseif values[xcol] == "" or values[ycol] == "" then
+                if options and options["debug"] then
+                    log_error("\\textbf{Warning:} Empty cell at line " .. line_number + 1 .. " (column " .. xcol .. " or " .. ycol .. ")\\\\")
+                end
+                skipped_lines = skipped_lines + 1
+            else
+                local x_val = tonumber(values[xcol])
+                local y_val = tonumber(values[ycol])
+                if x_val and y_val then
+                    table.insert(data, {x_val, y_val})
+                else
+                    if options and options["debug"] then
+                        log_error("\\textbf{Warning:} Invalid data at line " .. line_number + 1 .. " (" .. values[xcol] .. ", " .. values[ycol] .. ")\\\\")
+                    end
+                    skipped_lines = skipped_lines + 1
+                end
+            end
+        end
+        line_number = line_number + 1
+    end
+
+    file:close()
+
+    if #data == 0 then
+        if options and options["debug"] then
+            log_error("\\textbf{Error:} No valid data points found in file.")
+        end
+        return nil
+    end
+
+    if options and options["debug"] then
+        log_error("\\textbf{Info:} Read " .. #data .. " data points, skipped " .. skipped_lines .. " lines.\\\\")
+    end
+
+    return data
+end
+
+-- Approximate significant figures
+function sigFig(value, digits)
+    if not digits or digits < 1 then return value end
+    local fmt = string.format("%%.%dg", digits)
+    return tonumber(string.format(fmt, value))
+end
+
+-- Polynomial regression with improved numerical stability
+function polynomial_regression(data, order)
+    local n = #data
+    if n < order + 1 then 
+        log_error("\\textbf{Error:} Not enough data points for order " .. order .. " polynomial.\\\\")
+        return nil 
+    end
+    
+    -- Normalize data for better numerical stability
+    local norm_data, x_min, x_range = normalize_data(data)
+    
+    -- Build design matrix X and vector Y
+    local X = {}
+    local Y = {}
+    for i = 1, n do
+        local row = {}
+        local x = norm_data[i][1]
+        for p = order, 0, -1 do
+            table.insert(row, x^p)
+        end
+        X[i] = row
+        Y[i] = { norm_data[i][2] }
+    end
+
+    -- Use Kahan summation for matrix products to reduce floating-point errors
+    local function kahan_sum(values)
+        local sum = 0.0
+        local c = 0.0
+        for _, v in ipairs(values) do
+            local y = v - c
+            local t = sum + y
+            c = (t - sum) - y
+            sum = t
+        end
+        return sum
+    end
+
+    -- Compute X^T * X with improved precision
+    local xt = {}
+    for i = 1, order+1 do
+        xt[i] = {}
+        for j = 1, n do
+            xt[i][j] = X[j][i]
+        end
+    end
+
+    local xtx = {}
+    for i = 1, order+1 do
+        xtx[i] = {}
+        for j = 1, order+1 do
+            local products = {}
+            for k = 1, n do
+                table.insert(products, xt[i][k] * X[k][j])
+            end
+            xtx[i][j] = kahan_sum(products)
+        end
+    end
+
+    local xty = {}
+    for i = 1, order+1 do
+        local products = {}
+        for k = 1, n do
+            table.insert(products, xt[i][k] * Y[k][1])
+        end
+        xty[i] = { kahan_sum(products) }
+    end
+
+    -- Improved matrix inversion with partial pivoting
+    local function improved_invert_matrix(m)
+        local n = #m
+        -- Create augmented matrix [A|I]
+        local aug = {}
+        for i = 1, n do
+            aug[i] = {}
+            for j = 1, 2*n do
+                if j <= n then
+                    aug[i][j] = m[i][j]
+                else
+                    aug[i][j] = (i == j-n) and 1 or 0
+                end
+            end
+        end
+        
+        -- Gaussian elimination with partial pivoting
+        for i = 1, n do
+            -- Find pivot
+            local max_row = i
+            local max_val = math.abs(aug[i][i])
+            for k = i+1, n do
+                if math.abs(aug[k][i]) > max_val then
+                    max_row = k
+                    max_val = math.abs(aug[k][i])
+                end
+            end
+            
+            -- Check for singular matrix
+            if max_val < 1e-14 then return nil end
+            
+            -- Swap rows if needed
+            if max_row ~= i then
+                aug[i], aug[max_row] = aug[max_row], aug[i]
+            end
+            
+            -- Scale row
+            local pivot = aug[i][i]
+            for j = i, 2*n do
+                aug[i][j] = aug[i][j] / pivot
+            end
+            
+            -- Eliminate
+            for k = 1, n do
+                if k ~= i then
+                    local factor = aug[k][i]
+                    for j = i, 2*n do
+                        aug[k][j] = aug[k][j] - factor * aug[i][j]
+                    end
+                end
+            end
+        end
+        
+        -- Extract inverse
+        local inv = {}
+        for i = 1, n do
+            inv[i] = {}
+            for j = 1, n do
+                inv[i][j] = aug[i][j+n]
+            end
+        end
+        return inv
+    end
+
+    -- Use improved matrix inversion
+    local xtx_inv = improved_invert_matrix(xtx)
+    if not xtx_inv then 
+        log_error("\\textbf{Error:} Matrix is ill-conditioned for order " .. order .. ".\\\\")
+        return nil 
+    end
+
+    -- Solve for coefficients
+    local norm_coeff = {}
+    for i = 1, order+1 do
+        local sum = 0
+        for j = 1, order+1 do
+            sum = sum + xtx_inv[i][j] * xty[j][1]
+        end
+        norm_coeff[i] = sum
+    end
+    
+    -- Transform coefficients back to original scale
+    local coeff = denormalize_coefficients(norm_coeff, x_min, x_range)
+    return coeff
+end
+
+-- Transform normalized coefficients back to original scale
+function denormalize_coefficients(norm_coeff, x_min, x_range)
+    local order = #norm_coeff - 1
+    local coeff = {}
+    
+    -- Start with a copy of normalized coefficients
+    for i=1, order+1 do
+        coeff[i] = 0
+    end
+    
+    -- For each normalized coefficient
+    for i=1, order+1 do
+        local power = order + 1 - i
+        
+        -- Apply binomial expansion to convert back
+        for j=0, power do
+            local bin_coeff = binomial(power, j)
+            local idx = order + 1 - j
+            coeff[idx] = coeff[idx] + norm_coeff[i] * bin_coeff * math.pow(-x_min/x_range, power-j) * math.pow(1/x_range, j)
+        end
+    end
+    
+    return coeff
+end
+
+-- Calculate binomial coefficient (n choose k)
+function binomial(n, k)
+    if k < 0 or k > n then return 0 end
+    if k == 0 or k == n then return 1 end
+    
+    local result = 1
+    for i = 1, k do
+        result = result * (n - (i - 1)) / i
+    end
+    return result
+end
+
+-- Function to generate the polynomial equation string for pgfplots
+function generate_polynomial_equation(coefficients)
+    local terms = {}
+    for i, coeff in ipairs(coefficients) do
+        local power = #coefficients - i -- Reverse the order to start with the highest power
+        if power == 0 then
+            table.insert(terms, string.format("%.9f", coeff)) -- Constant term
+        elseif power == 1 then
+            table.insert(terms, string.format("%.9f * x", coeff)) -- Linear term
+        else
+            table.insert(terms, string.format("%.9f * x^%d", coeff, power)) -- Higher-order terms
+        end
+    end
+
+    -- Concatenate terms into a single string formatted for pgfplots
+    return string.format("{%s}", table.concat(terms, " + "))
+end
+
+-- Function to generate the linear equation string for pgfplots legend
+function format_equation_plot(coefficients)
+    local terms = {}
+    for i, coeff in ipairs(coefficients) do
+        local power = #coefficients - i -- Start with the highest power
+        if coeff ~= 0 then -- Skip zero coefficients
+            if power == 0 then
+                table.insert(terms, string.format("%.4f", coeff)) -- Constant term
+            elseif power == 1 then
+                table.insert(terms, string.format("%.4fx", coeff)) -- Linear term
+            else
+                table.insert(terms, string.format("%.4fx^%d", coeff, power)) -- Higher-order terms
+            end
+        end
+    end
+
+    -- Concatenate terms into a single string formatted for pgfplots
+    local equation = table.concat(terms, " + ")
+
+    -- Replace "+ -" with "-" for negative terms
+    equation = equation:gsub("%+ %-", "- ")
+
+    return string.format("{%s}", equation)
+end
+
+-- Computes R²
+function calculate_r_squared(data, predict_func)
+    local n = #data
+    if n < 2 then return 0 end
+    local sum_y = 0
+    for _, point in ipairs(data) do
+        sum_y = sum_y + point[2]
+    end
+    local mean_y = sum_y / n
+    local ss_tot = 0
+    local ss_res = 0
+    for _, point in ipairs(data) do
+        local y_obs = point[2]
+        local y_pred = predict_func(point[1])
+        ss_res = ss_res + (y_obs - y_pred)^2
+        ss_tot = ss_tot + (y_obs - mean_y)^2
+    end
+    return 1 - (ss_res / ss_tot)
+end
+
+-- Approximate significant figures
+function sigFig(value, digits)
+    if not digits or digits < 1 then return value end
+    local fmt = string.format("%%.%dg", digits)
+    return tonumber(string.format(fmt, value))
+end
+
+-- Example outlier filter using Z-scores
+function filter_outliers(data, threshold)
+    if not threshold then return data end
+
+    -- Calculate mean and std
+    local n = #data
+    local sum_x, sum_y = 0, 0
+    for _, pt in ipairs(data) do
+        sum_x = sum_x + pt[1]
+        sum_y = sum_y + pt[2]
+    end
+    local mean_x = sum_x / n
+    local mean_y = sum_y / n
+
+    local variance_x, variance_y = 0, 0
+    for _, pt in ipairs(data) do
+        variance_x = variance_x + (pt[1] - mean_x)^2
+        variance_y = variance_y + (pt[2] - mean_y)^2
+    end
+    local std_x = math.sqrt(variance_x / (n - 1))
+    local std_y = math.sqrt(variance_y / (n - 1))
+
+    local filtered = {}
+    for _, pt in ipairs(data) do
+        local zx = math.abs(pt[1] - mean_x) / std_x
+        local zy = math.abs(pt[2] - mean_y) / std_y
+        if zx < threshold and zy < threshold then
+            table.insert(filtered, pt)
+        end
+    end
+    return filtered
+end
+
+-- Log an error message to the LaTeX log file
+function log_error(message)
+    texio.write("log", "Lua Error: " .. message .. "\n")
+end
+
+-- Resamples data, does polynomial regression, and computes lower/upper bands
+function generate_confidence_band(data, order, n_bootstrap, conf_level)
+    -- Sort original data by x
+    table.sort(data, function(a, b) return a[1] < b[1] end)
+    local xs = {}
+    for i, pt in ipairs(data) do
+        xs[i] = pt[1]
+    end
+
+    local alpha = (1 - conf_level)/2
+    n_bootstrap = n_bootstrap or 1000
+
+    -- For storing predicted values from each bootstrap
+    local predictions = {}
+    for i = 1, #data do
+        predictions[i] = {}
+    end
+
+    -- Draw bootstrap samples and compute fits
+    for b = 1, n_bootstrap do
+        -- Sample with replacement
+        local sample = {}
+        for _ = 1, #data do
+            local idx = math.random(#data)
+            table.insert(sample, {data[idx][1], data[idx][2]})
+        end
+
+        local coeff = polynomial_regression(sample, order)
+        if coeff then
+            for i, xval in ipairs(xs) do
+                local pred = 0
+                for cidx, cval in ipairs(coeff) do
+                    local power = (#coeff - cidx)
+                    pred = pred + cval * (xval ^ power)
+                end
+                table.insert(predictions[i], pred)
+            end
+        end
+    end
+
+    -- For each x, sort predictions and pick lower/upper percentiles
+    local lower_band, upper_band = {}, {}
+    for i, preds in ipairs(predictions) do
+        table.sort(preds)
+        local lower_idx = math.floor(#preds * alpha + 0.5)
+        local upper_idx = math.floor(#preds * (1 - alpha) + 0.5)
+        lower_idx = math.max(lower_idx, 1)
+        upper_idx = math.min(upper_idx, #preds)
+        table.insert(lower_band, {xs[i], preds[lower_idx] or preds[1]})
+        table.insert(upper_band, {xs[i], preds[upper_idx] or preds[#preds]})
+    end
+
+    -- Format for pgfplots
+    local function coords(array)
+        local parts = {}
+        for _, pt in ipairs(array) do
+            parts[#parts+1] = string.format("(%f,%f)", pt[1], pt[2])
+        end
+        return table.concat(parts, " ")
+    end
+
+    return coords(lower_band), coords(upper_band)
+end
+
+-- Function to process data and handle any level of polynomial regression
+function process_data_with_options(file_path, options)
+    local xcol = options["xcol"]
+    local ycol = options["ycol"]
+    local z_threshold = options["z_threshold"]
+    local sig_figures = options["sig_figures"]
+    local order = options["order"] or 1 -- Default to linear regression
+
+    -- Read data from the CSV file
+    local data = read_csv_to_table(file_path, xcol, ycol, options)
+    if not data then
+        print("Error: Unable to read data from file.")
+        return
+    end
+
+    -- Apply Z-score filtering only if z_threshold is set
+    local filtered_data = data
+    if z_threshold then
+        filtered_data = filter_outliers(data, z_threshold)
+    end
+
+    -- Perform polynomial regression
+    local coefficients = polynomial_regression(filtered_data, order)
+    if not coefficients then
+        print("Error: Unable to calculate polynomial regression.")
+        return
+    end
+
+    -- Generate confidence bands if the option is enabled
+    local lower_band, upper_band = "", ""
+    if options["ci"] then
+        local n_bootstrap = options["bootstrap_samples"] or 1000
+        local conf_level = 0.95
+        lower_band, upper_band = generate_confidence_band(filtered_data, order, n_bootstrap, conf_level)
+        tex.sprint("\\def\\qlwr{" .. lower_band .. "}")
+        tex.sprint("\\def\\qupr{" .. upper_band .. "}")
+    end
+
+    -- Generate polynomial equation for plotting
+    local poly_eq = generate_polynomial_equation(coefficients)
+    local print_eq = format_equation_plot(coefficients)
+    print("Generated Polynomial Equation: " .. poly_eq) -- Debug print
+
+    -- Calculate R-squared for the polynomial regression
+    local predict_function = function(x)
+        local y_pred = 0
+        for i, coeff in ipairs(coefficients) do
+            local power = #coefficients - i
+            y_pred = y_pred + coeff * x^power
+        end
+        return y_pred
+    end
+    
+    local poly_r = calculate_r_squared(filtered_data, predict_function)
+    poly_r = sigFig(poly_r, sig_figures)
+    print("Calculated R-squared: " .. poly_r) -- Debug print
+
+    -- Set LaTeX macros
+    token.set_macro("polyR", poly_r)
+    tex.sprint("\\def\\polyeq{" .. poly_eq .. "}")
+    tex.sprint("\\def\\printeq{" .. print_eq .. "}")
+end
\ No newline at end of file


Property changes on: trunk/Master/texmf-dist/tex/lualatex/lua-regression/lua-regression.lua
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/lualatex/lua-regression/lua-regression.sty
===================================================================
--- trunk/Master/texmf-dist/tex/lualatex/lua-regression/lua-regression.sty	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/lualatex/lua-regression/lua-regression.sty	2025-04-07 19:47:17 UTC (rev 74868)
@@ -0,0 +1,127 @@
+% Copyright (c) 2025 George Allison
+%
+% This work may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3
+% of this license or any later version.
+% The latest version of this license is in
+%   http://www.latex-project.org/lppl.txt
+% and version 1.3 or later is part of all distributions of LaTeX
+% version 2005/12/01 or later.
+%
+% This work has the LPPL maintenance status `maintained'.
+%
+% The Current Maintainer of this work is George Allison.
+%
+% This work consists of the files lua-regression.sty and lua-regression.lua
+%
+% This software is provided 'as is', without warranty of any kind,
+% either expressed or implied, including, but not limited to, the
+% implied warranties of merchantability and fitness for a
+% particular purpose.
+
+\ProvidesPackage{lua-regression}[2025/04/06 1.0.0  Lua Regression Plotting project]
+
+\ifluatex
+  \RequirePackage{luacode}
+\else
+  {\PackageError{lua-regression}
+  {Not running under LuaLaTeX}
+  {This package requires LuaLaTeX. Try compiling this document with\MessageBreak 'lualatex' instead of 'latex'. This is a fatal error; I'm aborting now.}%
+  }\stop
+\fi
+
+% Required packages
+\RequirePackage{pgfkeys}
+\RequirePackage{pgfplots}
+\usepgfplotslibrary{fillbetween}
+
+% Define the key-value options
+% Define the key-value options
+\pgfkeys{
+    /luaregression/.is family, /luaregression,
+    default/.style = {
+        xcol=1,            % Default x-column index
+        ycol=2,            % Default y-column index
+        ci=false,  % Default: no error band
+        z-threshold=null,  % Default Z-score threshold
+        sig-figures=4,     % Default significant figures
+        order=1,          % Default polynomial order
+        plot=false,        % Default plotting behavior
+        pgf-options={mark=none,smooth}, % Default PGF options
+        eq=false, % Toggle for showing the equation
+        r2=false,       % Toggle for showing R²
+        debug=false,    % Debug toggle for csv
+        bootstrap=1000, % Number of bootstrap samples for confidence intervals
+        cicolor=blue,        % CI fill color
+        cifillopacity=0.2,  % CI fill opacity
+    },
+    xcol/.estore in = \luaregressionxcol,
+    ycol/.estore in = \luaregressionycol,
+    ci/.estore in = \luaregressionci,
+    z-threshold/.estore in = \luaregressionzthreshold,
+    sig-figures/.estore in = \luaregressionsigfigures,
+    order/.estore in = \luaregressionorder,
+    plot/.estore in = \luaregressionplot,
+    pgf-options/.estore in = \luaregressionpgfoptions,
+    eq/.estore in = \luaregressionshowequation,
+    r2/.estore in = \luaregressionshowrsquare,
+    debug/.estore in = \luaregressiondebug,
+    bootstrap/.estore in = \luaregressionbootstrapsamples,
+    cicolor/.estore in = \luaregressioncicolor,
+    cifillopacity/.estore in = \luaregressioncifillopacity,
+}
+
+% Define the macro
+\newcommand{\luaregression}[2][]{%
+    \pgfkeys{/luaregression, default, #1}% Parse the options
+    \directlua{
+        require("lua-regression")
+        process_data_with_options(
+            "#2",
+            {
+                ["xcol"] = tonumber("\luaregressionxcol"),
+                ["ycol"] = tonumber("\luaregressionycol"),
+                ["z_threshold"] = tonumber("\luaregressionzthreshold"),
+                ["sig_figures"] = tonumber("\luaregressionsigfigures"),
+                ["ci"] = ("\luaregressionci" == "true"),
+                ["order"] = tonumber("\luaregressionorder"),
+                ["debug"] = ("\luaregressiondebug" == "true"),
+                ["bootstrap_samples"] = tonumber("\luaregressionbootstrapsamples"),
+            }
+        )
+    }%
+    \ifthenelse{\equal{\luaregressionplot}{true}}{%
+        \ifx\addplot\undefined
+            \PackageError{lua-regression}{'plot=true' requires a tikzpicture environment and pgfplots}%
+            {Use '\\begin{tikzpicture} ... \\end{tikzpicture}' with '\\usepackage{pgfplots}'.}%
+        \fi
+        \expandafter\addplot\expandafter[\luaregressionpgfoptions] {\polyeq};%
+        % Construct the legend entry dynamically
+        \begingroup
+        \def\legendentry{}%
+        \ifthenelse{\equal{\luaregressionshowequation}{true}}{%
+            \edef\legendentry{$y = \printeq$}%
+        }{}%
+        \ifthenelse{\equal{\luaregressionshowrsquare}{true}}{%
+            \ifx\legendentry\empty
+                \edef\legendentry{$R^2 = \polyR$}%
+            \else
+                \edef\legendentry{\legendentry\\$R^2 = \polyR$}%
+            \fi
+        }{}%
+        \ifx\legendentry\empty
+        \else
+            \expandafter\addlegendentry\expandafter{\legendentry}%
+        \fi
+        \endgroup
+        % Plot confidence band if ci=true
+        \ifthenelse{\equal{\luaregressionci}{true}}{%
+        \addplot[name path=qlwrpath,draw=none] coordinates {\qlwr};
+        \addplot[name path=quprpath,draw=none] coordinates {\qupr};
+        \addplot[
+            fill=\luaregressioncicolor,
+            fill opacity=\luaregressioncifillopacity
+        ] fill between[of=quprpath and qlwrpath];
+        }{}%
+    }{}%
+}
\ No newline at end of file


Property changes on: trunk/Master/texmf-dist/tex/lualatex/lua-regression/lua-regression.sty
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/tlpkg/bin/tlpkg-ctan-check
===================================================================
--- trunk/Master/tlpkg/bin/tlpkg-ctan-check	2025-04-06 23:42:02 UTC (rev 74867)
+++ trunk/Master/tlpkg/bin/tlpkg-ctan-check	2025-04-07 19:47:17 UTC (rev 74868)
@@ -543,7 +543,7 @@
     ltxcmds ltxdockit ltxfileinfo ltxguidex ltximg
     ltxkeys ltxmisc ltxnew ltxtools
     lua-alt-getopt lua-check-hyphen lua-physical lua-placeholders
-    lua-tinyyaml lua-typo lua-uca lua-ul
+    lua-regression lua-tinyyaml lua-typo lua-uca lua-ul
     lua-uni-algos lua-visual-debug lua-widow-control luaaddplot
     luabibentry luabidi luacas luacensor luacode luacolor luacomplex
     luafindfont luagcd luahttp luahyphenrules

Modified: trunk/Master/tlpkg/libexec/ctan2tds
===================================================================
--- trunk/Master/tlpkg/libexec/ctan2tds	2025-04-06 23:42:02 UTC (rev 74867)
+++ trunk/Master/tlpkg/libexec/ctan2tds	2025-04-07 19:47:17 UTC (rev 74868)
@@ -1837,6 +1837,7 @@
  'lua-check-hyphen'	=> '&POST_rmsymlink',
  'lua-physical'		=> '&POSTlua_physical',
  'lua-placeholders'	=> '&POST_onelevel',
+ 'lua-regression'	=> '&POST_onelevel',
  'luaotfload'		=> '&POST_do_man',
  'luatexja'		=> '&POSTluatexja',
  'm-tx'			=> '&POSTmtx',

Modified: trunk/Master/tlpkg/tlpsrc/collection-mathscience.tlpsrc
===================================================================
--- trunk/Master/tlpkg/tlpsrc/collection-mathscience.tlpsrc	2025-04-06 23:42:02 UTC (rev 74867)
+++ trunk/Master/tlpkg/tlpsrc/collection-mathscience.tlpsrc	2025-04-07 19:47:17 UTC (rev 74868)
@@ -150,6 +150,7 @@
 depend lpform
 depend lplfitch
 depend lstbayes
+depend lua-regression
 depend luanumint
 depend math-operator
 depend mathcommand

Added: trunk/Master/tlpkg/tlpsrc/lua-regression.tlpsrc
===================================================================


More information about the tex-live-commits mailing list.