[Draft] Static Normals: A baseline predictive model
This post introduces a "Static Normals" probabilistic model to PlanZero which is the first to impose modelling assumptions on the NIR, and the first to make predictions about future NIR emissions. The predictions are trivial: all years are the same (static, rather than dynamic). This model is intended as a baseline against which more complex future models can be judged. Several appendices to this post introduce probabilistic modelling notation, Bayesian inference, the Pre-NIR-2025-m06 emissions prediction challenge, and describe changes to PlanZero's build system to support probabilistic models.
Overview
The long-term aim for PlanZero is to quantify the impact of strategies that may affect Canada's emissions. The impact of a strategy is the difference between what will probably happen if the strategy is implemented, versus what will probably happen if it isn't. Both of these are predictions. To estimate the impact of strategies, PlanZero needs research and models models that make credible predictions for emissions, both with and without various strategies, with usefully tight credible intervals, on various time horizons.
This post introduces PlanZero's first predictive probabilistic model. It is a simple baseline that assumes
- that provincial and territorial emissions per-sector and per-gas add up to national totals
- that provincial and territorial emissions are static and don't actually change over time; they have been constant historically, and will remain constant in the future
The visualization follows the style used in the previous post, which introduced the probabilistic NIR-2025. The visualization has been updated to show both a predictive model (the static normals model, conditioned on NIR-2025 data up to 2022) and the emissions that it should predict (the probabilistic NIR-2025's 2023 data, shown in terms of upper and lower credible interval and mean, thin solid and dotted black lines respectively).
This post also introduces predictions to the PlanZero site, in two ways. The first way is that visualizations of predictive probabilistic models show ranges of 95% credible emissions for future years. The second way is via the Predictions page, a new one on PlanZero. The predictions page provides an overview of kinds of prediction, and a ranking of models in terms of metrics that formalize how good they are at making those predictions. The previous post on the probabilistic NIR-2025 introduced a model evaluation metric for scoring predictions in terms of KL-divergence from the probabilistic interpretation of measured emissions. This post uses that metric to score the static normals model. The metric is used for both individual sector-gas combinations, as well as an overall weighted average across all sectors and gases. The static normals model scores an overall average divergence of 3.35. Future models might rank better by scoring closer to zero.
I believe this is the first step in an important research loop that can lead PlanZero to making the best possible predictions. The machine learning community has made great progress over recent decades by combining two incremental, mutually supportive research programs. The first one is a relatively slow accumulation of benchmark prediction challenges. The second one is a relatively faster exploration of the space of models, algorithms, and data to find ways of improving the state of the art in those challenges. At the same time, the more accurately PlanZero can predict emissions impacts, the more helpful PlanZero can be in evaluating the many strategies that have helpful but not enormous emissions impacts. This is why the PlanZero site is now structured to feature predictions and models that can reflect two mutually reinforcing research programs. I hope they will lead to as solid a foundation as possible for model-based planning of emission-reduction strategies. This rationale has been added to the About page.
Despite the simplicity of the static normals model, the predictions are qualitatively accurate for several sectors, and establish a numerical benchmark for quantitative scoring (i.e. divergences below about 1 are pretty good). The good fit for emissions sectors such as e.g. Enteric Fermentation, Municipal Solid Waste Landfills, Manure Management, and Railways suggests that little progress has been made in these areas, at least by 2023. Conversely, the poorness of fit in other sectors suggests that have been significant changes either for better or worse. We'll look at trends in a future post, that will introduce an autoregressive model as an alternative to the standard normals presented here. Before that post though, I'd like to insert two tidying-up posts. The Bovaer analysis should be adapted to operate on probabilistic models and the models page should be purged of "simulation-based models", which is a term I'd like to deprecate and remove from PlanZero. In a second tidy-up post, I'd like to to finally introduce the glossary page with confidence in my definition of what a "model" actually is in PlanZero.
Until next time,
- James Bergstra
Appendices
- Appendix 1: Probabilistic Modelling Notation
- Appendix 2: Model Description
- Appendix 3: Background in Bayesian Inference
- Appendix 4: Inference in the Standard Normals Model
- Appendix 5: Pre-NIR-2025-m04, a NIR Prediction Challenge
- Appendix 6: Update to PlanZero's Build System
Appendix 1: Probabilistic Modelling Notation
Some probability notation is conventional, in order to express probabilistic models. It builds on the introduction to probability in Appendix 1 of the Probabilistic NIR-2025 post. Probabilistic modelling is a huge topic. Basic concepts of probability are introduced across many years of primary and secondary schooling, and covered in greater detail at university levels. For more information and orientation, see e.g. wikipedia (Statistical Model, Graphical Models), many tutorials online that are specific to probabilistic programming software packages (e.g. Stan, PyMC, Pyro; PlanZero currently uses NumPyro) or a textbook such as Probabilistic Graphical Models (Koller and Friedman, 2009) for greater depth.
The following modelling notation used in this post to describe the Static Normals model and introduce Bayesian inference in Appendix 4: Inference in the Static Normals Model.
- means there's a number we don't know, we're calling it an , and this is the probability it is actually 0. is called an unknown variable in PlanZero, although many references refer to such a variable as a random variable.
- is, intuitively, the table mapping all the values might take to their probabilities. The probabilities add up to 1 to represent the fact that must take one of them. The table might be infinitely large (e.g. a probability for each integer). Although it can be an abuse of notation, I'll also sometimes write to refer to a function defining the density of probability mass when the possibilities for are a continuous domain of values, such as the real numbers.
- is shorthand for when it's clear from surrounding context we're talking about
- is a Normal distribution, which is non-negative function that sums (integrates) to 1. It is parameterized by two numbers: the mean, and the variance. It's conventional to write as the argument to the normal distribution because itself is qualitatively the "width" of the distribution and only positive-valued variances are valid. Normal distributions are widely used in probabilistic modelling. You can read more about them on wikipedia, and see its shape in the figure below. (Sometimes these are called Gaussians but I'm going to call them Normals to be consistent with the probabilistic programming library I'm using.)
- is a log-normal distribution, a distribution over positive-valued real numbers with a given mean and relative uncertainty. There's an example below illustrating one possible shape of log-normal distribution, with and . Note that unlike the regular normal, being negative doesn't make the distribution negative, it squeezes the distribution leftward toward 0. The parameter doesn't exactly modulate the width, as it does for the normal distribution, but it reflects relative uncertainty, and it does affect both the shape and the mean of the distribution.
- means (1) that is an unknown variable in some probabilistic model, and (2) that its probability distribution (or density) is the thing to the right of the "" symbol. In this example, is distributed according to a normal distribution with mean 0 and variance 1.
- features comma-separated terms. The equals-signs mean the terms are criteria. means the probability that unknown variable is 0 and unknown variable is 1.
- also features comma-separated terms, but the terms aren't predicates with equals-signs. This is the notation for the probability table (or function, as appropriate to the domains of and ) that maps every possible value of and every possible value of given that value of , to the probability of them both taking those respective values. This sort of probability distribution is called a joint distribution because it is a distribution over multiple unknown variables.
- uses the | symbol to mean the probability that if we make an additional assumption about , namely that it is 1. is called a conditional distribution because it defines a probability distribution for that is conditional on additional assumptions / criteria. A probabilistic model that includes and defines either explicitly or implicitly how they can be related by conditional distributions. Joint distributions such as can always be written as products involving conditionals , and sometimes, such as when deriving techniques for Bayesian inference, such rewriting is very helpful.
Appendix 2: Model Description
PlanZero's "Static Normals" model of the 2025 National Inventory Report (NIR-2025, or just NIR in this post) is that for each ...
- IPCC sector (I'll call these "sectors")
- greenhouse gas (sometimes just "gas")
- province and territory (I'll call these "regions")
- and year (from 1990 to 2023)
Finally, and most radically, the model is called "static normals" because it assumes that these quantities of emissions don't change over time. Instead, it assumes that the different estimates of emissions from year to year in the NIR are the results of completely random fluctuations, totally unforseeable and outside of anyone's control, which will continue indefinitely into the future following the same Normal distribution of annual emissions as has been observed historically. This is a unrealistic assumption because in many sectors, the reported emissions are defined in the NIR (following IPCC Guidelines) as being proportional to e.g., the number of cars, or trucks, or heads of cattle, which are highly correlated from year to year, and which follow long-term trends. Yet, there's no rule against using unrealistic assumptions in models. The consequences of making unrealistic assumptions in models are uncertainty and/or inaccuracy. We'll use this model to establish a baseline for uncertainty and inaccuracy in prediction, which can serve as a benchmark for future models aiming for greater certainty and accuracy on the basis of e.g. greater realism.
Formally, the Static Normals model is the following set of distributions over unknown quantities:
| Unknown Variable and Distribution | Description |
|---|---|
| A-priori, after emissions are scaled for each sector () and gas () so that 0 means 0 and 1 means the maximum absolute value of national emissions for that sector and gas over time (), the scaled emissions can be expected to be around . The Static Normals model approximates this with a normal distribution and calls the unknown, scaled time-invariant emissions amount for each sector, gas, region combination . This and other a-priori distributions are designed to be refined by inference as explained in Appendix 4: Inference. | |
| A-priori, the variance in regional emissions (looking across years) is not expected to be super-tiny, nor much larger than 1. | |
| A-priori, the variance national emissions (looking across years) is not expected to be super-tiny, nor much larger than 1. | |
| The model-estimated NIR emissions for each sector (), gas (), region (, province or territory), and annual time period (), are unknown variables () whose probability is normally distributed about mean with variance . Note that the distribution is the same for all annual time periods (giving the model its name "Static Normals"). | |
| The model-estimated national-total emissions for each sector (), gas (), and annual time period () are unknown variables () whose probability is centred at the sum of regional means, with separate national variance. The distribution is the same for all annual time periods. |
Appendix 3: Background in Bayesian Inference
Bayesian inference in probabilistic models is about redistributing probability for unknown variables in order to balance two competing objectives: (1) to remain probable according to the a-priori distributions, and yet (2) to explain observations. The Static Normals model described in Appendix 2: Model Description includes a-priori probability distributions over and that induce distributions over and , which are meant to estimate quantities in an NIR. Yet we can observe the NIR-2025, in terms of either raw data, or the distributions developed in PlanZero's NIR-2025 model (see Probabilistic NIR-2025 post for details). [Bayesian] Inference algorithms can answer the question: What are the conditional distributions over and given certain observable values for and ? This specific kind of conditional distribution, being a distribution conditioned on data, is called a posterior distribution. The unobserved variables in the model are called latent variables, and so a posterior distribution is a conditional distribution over the latent variables.
If only some of the observable data is used for conditioning, then the remaining data can be used to evaluate a model's predictions. For example, if we only condition on emissions data up to 2022, then variables related to year 2023 will be latent ones and inference will assign them posterior distributions. These posterior distributions can be interpreted as the model's predictions for 2023. Appendix 4: Pre-NIR-2026-m04, a NIR Prediction Challenge evaluates such predictions from the Static Normals model, using the method of inference discussed here in this Appendix.
Inference algorithms work on the basis of Bayes' Theorem. In standard probability notation, for any pair of unknown variables and , Bayes' theorem looks like:
Bayes' theorem shows how to relate a conditional distribution of the form to conditional distributions the other way around: and . Bayes' theorem is critical to inference in the Static Normals model because
- in order to make predictions, the Static Normals model was defined with the conditionals one way, namely
- to observe NIR data, we need the opposite conditional distribution
I don't know if it's possible to write down a formula for the posterior distribution . For some models, there are closed forms for some posterior distributions, but it's not always possible. What's often practical, is the use of Monte Carlo (random) estimators to compute samples of points from the desired distribution, based only on the conditional distributions used to define the model. Even with a Ph.D. in machine learning, I still find these algorithms amazing (read up on e.g. MCMC algorithms or stochastic variational inference if you're interested in how these algorithms work). This intersection of statistics, machine learning, and computer science is still the subject of active research, but the core capability of sampling from posterior distributions is relatively mature and for the purposes of this post we'll take it as given.
Probabilistic programming systems enable someone such as myself to define a probabilistic model by simply implementing a sampling process (such as the one in the left column of the table in Appendix-2 that defined the model) in a programming language, and then request inference in that model with simple standardized function calls. The implementation of these function calls involves relatively sophisticated software techniques (e.g. tracing and runtime program transformations in order to run backward over the computations that defined the model) but the output is simple: samples from . PlanZero uses the combination of Jax and NumPyro as a probabilistic programming system, and the NUTS MCMC algorithm in NumPyro for sampling from the posterior.
Appendix 4: Inference in the Static Normals Model
Running NumPyro's NUTS inference algorithm for the static model above, using the NIR-2025 emissions data up to 2022 for each sector and gas, and then re-sampling according to the original model for visualization, given the posterior , gives rise to the following figure, now available at the Static Normals model overview page. Inference for all models involved 250 warmup steps, followed by 500 samples with no thinning. Details of sampling can be found in nir_static_normals.py at time of writing.
Emissions are summarized by year, and in terms of total Mt per non-aggregate NIR sector. The black lines reflect reported historical emissions (the dotted line is the reported mean, the two thin solid lines are upper and lower 95% credible interval for the mean). The coloured elements reflect modelled emissions (the dotted line is the modelled mean, the shaded region is the model-estimated 95% credible interval for national emissions per sector). The colours in the figure correspond to high-level emissions categories:
- dark blue for energy used in stationary combustion (e.g. for public electricity, oil and gas extraction, etc.)
- light green for energy used in vehicles (e.g. light-duty, heavy-duty, off-road, marine, etc.)
- purple for fugitive sources(e.g. venting, flaring)
- wheat for agriculture-related emissions (e.g. soil, manure)
- pink for waste-related emissions (e.g. landfills)
- other colours for various industrial activities (mineral products, chemicals, metals)
Mouse-over the slider below to see the active date range and adjust it to focus on specific periods. Click on each panel for a deeper-dive into modelled emissions in that sector.
Qualitative Assessment of Quality of Fit
To my eye, inference worked well. The data usually lie within the middle of the 95% credible intervals, indicated as the coloured regions, as they should do about 95% of the time. The credible intervals are tight when the NIR-2025 data is relatively certain and steady over time, e.g. stationary combustion across petroleum refining industries, second row, rightmost panel. The credible intervals are wider when the data is less certain (e.g. municipal solid waste landfills, second row, middle column) and when there have been large variances over time (e.g. stationary combustion for public heat and electricity, top row, second from the left).
Based on a visual, qualitative analysis, I would say the static normals model is typically a poor fit to the data. Other models that recognize trends in this data over time could do a lot better. This will be investigated in future work using e.g. autoregressive models. Still, it's worth noting that the static normals model is not always a poor fit. The static normals model offers a qualitatively good fit in many sectors:
- Enteric Fermentation: emissions appear to be roughly constant for the most recent decade, and the static normals model lines up with that data pretty well.
- Municipal Solid Waste Landfills: emissions appear to be roughly constant for the entire history of NIR-2025 data from 1990 to 2023.
- Manure Management: manure management emissions appear to be highly correlated with enteric emissions, and also approximately a static normal for the last decade.
- Transport emissions from Railways: there's some fluctuation from year to year, but with relatively large uncertainty and no apparent trend, the static normals model is a good fit.
- Indirect emissions from Agricultural Soils: the NIR-2025 estimates a gradual upward trend since 1990, but with the large estimation uncertainty in the NIR, the constant normal model is a reasonably good fit.
- Municipal Wastewater Treatment and Discharge: as was the case with indirect emissions from agricultural soils, the NIR-2025 estimates a gradual upward trend since 1990, but with the large estimation uncertainty in the NIR, the constant normal model is a reasonably good fit.
- Industrial Wood Waste Landfills: there is probably a downward trend, but with the NIR estimation uncertainty, a static normal model isn't a bad fit here.
National Totals vs. Regional Subtotals
Surprisingly, at least to me, regional total emissions in NIR-2025 do not always sum up to the corresponding national total. If we define the sum of regions vs. national total discrepancy as the maximum difference over years, there are 11/486 with a discrepancy over 1Mt (there are 486 sector and GHG combinations). At the level of 100kt discrepancy, there are about twice as many combinations over the threshold, and at the level of 10kt discrepancy, twice as many again. I defined "Relative Discrepancy" as the discrepancy divided by the greater of itself and the root mean square of national totals, as a way to relate discrepancies to the scale of numbers in their sectors.
| IPCC Sector | GHG | Max Discrepancy (kt) | Relative Discrepancy |
|---|---|---|---|
| Petroleum Refining Industries | 2430.85 | 14.4% | |
| Commercial and Institutional | 1271.44 | 4.1% | |
| Cement Production | 2421.59 | 36.7% | |
| Lime Production | 1421.05 | 84.4% | |
| Ammonia Production | 3090.34 | 100.0% | |
| Nitric Acid Production | 1097.89 | 100.0% | |
| Petrochemical and Carbon Black Production | 4398.65 | 100.0% | |
| Non-Energy Products from Fuels and Solvent Use | 7395.02 | 67.7% | |
| Non-Energy Products from Fuels and Solvent Use | 1068.83 | 100.0% | |
| Forest Land | 1731.42 | 2.1% | |
| Harvested Wood Products | 53296.13 | 100.0% |
The consequence of such discrepancies is greater uncertainty in the posterior distribution when conditioning on data. For sector-gas combinations with larger discrepancies, the Bayesian inference procedure will rove more widely over possible values for and as there are multiple ways to sort-of-satisfy the objective of making the regional totals likely and sort-of-satisfy the objective of making the national total likely, but no single best way to make both objectives likely when the totals simply don't add up.
As an example, let's look at the results of inference for Harvested Wood Products' (HWP) emissions.
Appendix 5: Pre-NIR-2025-m04, a NIR Prediction Challenge
PlanZero aims to make credible predictions of the future out to year 2050 and beyond, because national emissions reductions will take at least that long. The mechanisms for establishing credibility are limited. One is intuitive appeal — a description of a predictive model will lend it some degree of credibility. Another is its track record — bearing in mind the structure of a model, and the nature of what it's predicting, its history of accuracy when informed by information available at the time, may lend it some degree of credibility as well. This appendix is about using the history of NIR emissions publications to produce a statistic that characterizes how well the static normals model predicts an aspect of future emissions.
The figure below illustrates the prediction of the latest year's data (year 2023) in NIR-2025, 4 months prior to publication. National Inventory Reports are typically published in mid-to-late April or early May. Dec 31 of the prior year is comfortably 4 months prior to publication, so the "Pre-NIR-2025-m04" prediction challenge uses 2024-12-31 as its prediction date (red dashed line in figure). NIR-2024 was available prior to the prediction date. It included emissions from years 1990-2022 (dark blue region), and was published about 16 months after the emissions period (publication delay shown in light-red region), which was earlier than (left of) the prediction date. The goal of the "Pre-NIR-2025-m04" prediction challenge is to anticipate the 2023 emissions (shown light blue) from NIR-2025 prior to its publication (publication delay shown in light-red region extends to the right of the prediction date). For this post, I cheat a little, and use the data from 1990-2022 from NIR-2025 as if it had come from NIR-2024. In future, looking at Pre-NIR-2026-m04 and beyond (GitHub Issue #61), this cheat won't be repeated.
Since the Static Normals model developed in this post was only conditioned on data up to 2022, inference in the model induces a posterior distribution over unknown variables and in the model, which can be interpreted as predictions of 2023 emissions (as well as every year beyond 2023, because the model is static). The table below lists the KL divergences between the NIR-2025 distributions for emissions year 2023 (as developed in in the Probabilistic NIR-2025 post) and the posterior distribution in the static normals model (which is the same for all years). Weighting these divergences proportionally to the absolute value of the 2023 per-sector-gas emissions is the "weighted KL-divergence" model evaluation metric developed in that post. The static normals model developed in this post scores a weighted KL-divergence of 3.35. Perfect prediction of all of the emission distributions would have scored 0.0. The table can be sorted by each column to see the best-predicted and worst-predicted sector-gas combinations.
Qualitative assessment in Appendix 4 noted seven sectors that seemed well-fit by the static normals model. Quantitatively, their per-gas KL-divergence scores are listed below. They are all relatively low. The best qualitative fit was municipal solid waste landfills, and that one scored the best quantitative match as well. These results provide evidence, I think, that the KL-divergence score measures approximately what the eye beholds, that these sectors (or sector-gas results) are the ones that are best-fit.
| Sector | KL-Divergence |
|---|---|
| Enteric Fermentation | 0.55 () |
| Municipal Solid Waste Landfills | 0.02 () |
| Manure Management | 0.26 (), 0.21 () |
| Railways | 1.31 (), 0.33 (), 0.25 () |
| Indirect from Agricultural Soils | 0.16 () |
| Municipal Waste Water Treatment and Discharge | 0.89 () |
| Industrial Wood Waste Landfills | 0.66 () |
The converse is also true: sector-gas combinations with scores less than about 1 appear to be the ones that are well-predicted. For example, emissions from settlements have risen and fallen, but the KL-divergence of the 2023 emission is a very-low 0.11 and indeed the 2023 emissions line up nearly perfectly with the historical mean and variance of the sector. Another example is emissions from "Non-Energy Products from Fuels and Solvent Use"; the KL-divergence score is a low 0.55 and again the static normals model appears to get lucky and make a prediction that lines up very well with the 2023 reported emissions. Other sector-gas combinations, which aren't listed above, typically don't look like the prediction of the static normals model for 2023, and have higher KL-divergence scores.
Engineering Update Regarding PlanZero's Build System
The software system for producing the PlanZero website was upgraded for this post, to achieve several engineering objectives:
- compute capacity: perform model inference on bigger, faster computers than my laptop
- build quality: upload a web server image to fly.io with pre-rendered pages so that the site loads faster
- reproducibility: an external build process ensures PlanZero's site builds are reproducible beyond my laptop
- author productivity: I can edit PlanZero code with the benefit of static analysis in a valid Dockerized test environment
- code quality: PlanZero's unit tests run automatically (and must pass) before pushing any changes to the website
- site quality: Reviewers can provide feedback on site previews before merging pull-requests, so the standard for what's shown on the main site can be higher.
Build, Test, and Deploy WorkFlow on GitHub
Inference in probabilistic models can be computationally expensive. Drawing 500 samples of and for each sector-gas combination can take several hours. I suspect this runtime can be reduced, but more advanced future models will require additional computation as well. It's not realistic to expect all of these posterior distributions to be computed near-instantly. The figure below outlines how GitHub Actions are now used to build PlanZero's site in a reproducible, automated manner. This content has been added to the PlanZero About page in a new section about software architecture.
flowchart TB
gh_build_and_test["Build and Test\n(Job)"]
gh_deploy_main["Deploy Main\n(Job)"]
gh_deploy_pr["Deploy Pull-Request\n(Job)"]
app_cache[("App Cache\n(Workflow Artifact)")]
inference_cache[("Model Inference Results\n(Cache Object)")]
inference_cache <-. "Per-model-version samples" .-> gh_build_and_test
gh_build_and_test --> gh_deploy_main
gh_build_and_test --> gh_deploy_pr
gh_build_and_test -. "Pre-rendered pages" .-> app_cache
app_cache .-> gh_deploy_main
app_cache .-> gh_deploy_pr
Model inference is computationally expensive, and the results don't change with every commit to the project. PlanZero uses an explicit and ad-hoc versioning system for models, in order to leverage GitHub's Dependency Cache capability in a controlled way. The cache design for the Static Normals model is that the entire model is cached on the basis of (a) a version number in the source code, (b) the name of the class, and (c) the cutoff date for data available for inference. Whenever the model code, or any dependency, or data assumption changes, the version number must be explicitly changed (raised), in order to change the cache key, which will then cause GitHub's workflow engine to recompute the inference of the model and save the results. Free-tier jobs are limited to 6 hours for open-source projects, so there's some incentive to ensure that the PlanZero site can be built from scratch, including all model inferences and tests, in that amount of time.
The Build and Test job (see diagram above) sometimes includes inference, but always runs unit tests, including a sweep through all of the pages hosted on the planzero website. In the process of rendering them as part of the unit test suite, these pages are cached to disk, and that whole cache of pages is stored as a Workflow Artifact. The set of pages isn't a large amount of data, and it's important to test frequently, so the tests run on every commit and the app cache is built every time the main branch or a pull-request branch changes.
The last jobs in the workflow download the pre-rendered pages and deploy the webserver and pre-built pages. PlanZero sites are hosted by Fly.io, which hosts the main planzero.ca site, as well as per-pull-request preview sites for work in progress. The set of active pull-requests is available on the project page on GitHub. PlanZero is not currently a purely static site, but I can imagine committing to making it purely static in future in order to e.g. improve initial page-load performance and lower hosting costs.
Neovim, TMux and Dockerized Editing
The Dockerfile and
Makefile
in PlanZero's root directory have been updated to describe a "development" image that
enables host command make tmux to launch a
tmux session
that can run various development activities in a similar environment to the one created on GitHub by
the build_and_test workflow.
Neovim is installed in this image as an editor, as well as
Jupyter.
Commands such as make jupyter and make local are meant to be run within this tmux environment, to run a jupyter server and local site respectively
on the ports described in the Makefile.
I hope, later, to introduce code acceptance tests in the build and test job that enforce style guidelines,
and to encourage those same style guidelines via neovim plugin configuration.
So far, neovim has simply been configured to edit Python files with default settings of
Pyright and
Ruff.
These tools find a lot of code quality issues! I intend to fix issues manually for a while, and build up a set of style-guide exceptions before e.g. running automatic
fixes, or requiring code quality checks to pass on the main branch (GH#90).
- © James Bergstra, 2026.
- Licensed under CC-BY.
- Statements on this site are not necessarily true or fit for any purpose.
- Design: HTML5 UP