# GNAT Developer Guide (`DEVELOPERS.md`)

This document is for people who work on GNAT more regularly  
(maintainer, postdocs, PhD students in the group, close collaborators).

It assumes you have read **`CONTRIBUTING.md`** and are comfortable with:

- Cloning the repository,
- Creating and working on feature branches, and
- Opening pull requests (PRs) into `master`.

If you are a first-time or occasional contributor, start with `CONTRIBUTING.md`.

---

## 1. Project overview

GNAT (General NMR Analysis Toolbox) is a MATLAB toolbox for processing and analysing NMR data.

High-level goals:

- Provide a robust, general-purpose environment for NMR data processing.
- Support a range of experiments used in the group and by collaborators.
- Be usable by non-programmers via a GUI and/or simple scripts.
- Remain maintainable by scientists with limited time and no formal software team.

The repo currently targets MATLAB on desktop (Windows, macOS, Linux) and is used in both academic and industrial environments.

> **Note:** GNAT is expected to be gradually superseded by newer Python-based tools, but we still treat GNAT as a live project and aim to keep it working and usable.

---

## 2. Repository layout

This section gives a brief orientation to the main folders and top-level files in GNAT.

Top-level directories:

- `Documentation/`  
  User and developer documentation (manuals, notes, and other written material related to GNAT).

- `Import_Export/`  
  Functions for reading and writing NMR data in various formats (vendor-specific import, export utilities, and related helpers).

- `Multivariate/`  
  Multivariate analysis routines (e.g. PCA/PLS-style methods, chemometric workflows, and related tools).

- `Univariate/`  
  Univariate processing and analysis routines (1D processing steps, fitting and peak-based operations, etc.).

- `Auxiliary_functions_Spen/`  
  Auxiliary functions used by SPEN-related methods. Subdirectories include:
  - `read_parameters/` – parameter-reading utilities for SPEN data.
  - `Spen_GNAT/` – core SPEN routines integrated with GNAT.
  - `phase_function/` – SPEN phase-handling functions.
  - `peak_picking/` – SPEN peak-picking routines.
  - `Nuclist/` – nucleus lists or related lookup utilities.
  - `Shear_gui/` – SPEN shear GUI components.

- `Macros/`  
  Macro definitions and related code to automate common GNAT workflows.
  - `Defaults/` – default macro settings and configuration files.

- `Associated Toolbox/`  
  Bundled third-party toolboxes used by GNAT. These are treated as external dependencies and should normally not be modified. Subdirectories include:
  - `FastICA_25/` – FastICA implementation for independent component analysis.
  - `Regularization Toolbox/` – regularisation routines for inverse problems.
  - `nway/` – N-way (multiway) analysis tools.
  - `icoshift_v1_2/` – icoshift alignment toolbox.
  - `MERA-master/` – MERA routines (multi-exponential / relaxation-related analysis).
  - `Chemometrics/` – additional chemometric utilities.
  - `natsortfiles/` – natural-order file sorting utilities.

- `Auxillary/`  
  Additional auxiliary functions. (Note: legacy folder name with a spelling variant; kept for historical reasons. New auxiliary code should generally go into the more specific folders above.)

Top-level files:

- `README.md`  
  User-facing overview of GNAT, installation notes, and basic usage.

- `CONTRIBUTING.md`  
  Short, scientist-friendly guide for anyone contributing changes (branches, PRs, expectations).

- `DEVELOPERS.md`  
  This document – internal notes for regular developers and the maintainer.

- `GNATLog.txt`  
  Log file used by GNAT (for recording run information, debugging notes, or session logs).

- `exponential_column_fit.m`  
- `optimize_exponential_fit.m`  
- `OptimizedFiddle_SCORE_OUTSCORE.m`  
- `OptimizedFiddle_SCORE_OUTSCORE_alfa.m`  
  Standalone analysis / fitting scripts and functions used in GNAT workflows (exponential fitting and FIDDLE-related scoring). These may later be reorganised into more specific subdirectories as the codebase is cleaned up.

The `.git/` directory contains git’s internal metadata and should not be edited manually.

## 3. Branching and release model (developer detail)

The Git structure is intentionally simple.

### 3.1 Long-lived branches

- `master`
  - Single main development branch.
  - Should always build and run in a reasonably stable way.
  - All new work is merged here via pull requests.

- `GNAT-2.0`
  - Historical branch corresponding to the GNAT 2.0 release that was distributed to end-users.
  - Normally not touched; kept for reference only.

We do **not** keep a permanent `dev` branch.

As a convention, only the maintainer (or explicitly designated maintainers) merge pull requests
into `master`. Contributors open PRs targeting `master` and wait for review rather than merging
their own work.


### 3.2 Feature branches

- New work always happens on a short-lived branch from `master`.
- Name convention (suggested, not rigid):
  - `<initials>-<type>-<short-description>`
  - Examples:
    - `MN-bugfix-Bruker-RD-export`
    - `AA-feature-LOCODOSY`
    - `XX-docs-installation-update`

After the PR is merged into `master`:

- The remote feature branch is deleted via the GitHub UI.
- Local copies are deleted by developers when convenient.

### 3.3 Releases and tags

- Official versions are marked with **tags** and **GitHub Releases**.
- Existing example: `GNAT-2.0` (tag and release).
- Future releases should use the same pattern:
  - Tag: `GNAT-2.1`, `GNAT-2.2`, etc.  
    (or a semantic version scheme like `v2.1.0` if we adopt it later).
  - Tag is created on `master`.
  - GitHub Release is created with short notes.

There is currently no policy to maintain multiple active release branches in parallel (e.g. 2.0.x vs 2.1.x). If that becomes necessary, we will update this section.

---

## 4. Local development environment

### 4.1 Recommended tools

- **MATLAB**  
  Use a reasonably recent release.  
  TODO: document the oldest MATLAB version we aim to support.

- **VS Code**  
  - Used as the primary text editor for `.m` files.
  - Recommended extensions:
    - MATLAB language support (syntax highlighting, basic navigation).
    - Git integration.

- **GitHub Desktop**  
  - Recommended for everyday git usage (fetch, pull, branches, commits, PRs).

- **Command line git** (optional but useful)
  - For occasional advanced operations (e.g. cleaning up branches, rebasing).

> **Note on repository location:**  
> Avoid storing your local clone of `UoM_GNAT` inside a synchronised folder (OneDrive, Dropbox,
> iCloud Drive, etc.). These services can modify or lock files inside the `.git` directory and
> cause corruption or spurious conflicts. Prefer a simple path such as
> `~/Documents/GitHub/UoM_GNAT` outside any sync service.

### 4.2 Basic workflow framing

A typical developer setup:

A typical developer setup:

1. Clone `UoM_GNAT` to `~/Documents/GitHub/UoM_GNAT` (or a similar folder **outside** any
   OneDrive/Dropbox/iCloud synchronisation).
2. Open this folder in VS Code for editing.
3. Use MATLAB with the same folder as the working directory.
4. Use GitHub Desktop to:
   - Keep `master` up to date.
   - Create and switch branches.
   - Commit, push, and create PRs.


---

## 5. Coding guidelines (MATLAB)

These guidelines are deliberately lightweight.

### 5.1 General style

- Aim for clear, readable MATLAB code.
- Prefer descriptive names over short ones, especially for top-level functions.
- Use functions rather than scripts where practical.
- Keep functions focused; if a function grows very long or complicated, consider refactoring.

### 5.2 Comments and documentation

- Use comments to explain *why* something is done, not just *what* the code does.
- For important or non-obvious functions, include a short header comment describing:
  - Purpose,
  - Inputs and outputs,
  - Any important assumptions (units, dimensions, expected data format).
- When handling file formats or subtle numerical issues, err on the side of more explanation.

### 5.3 Error handling

- Prefer explicit checks with helpful error messages over failing silently.
- Use `error` for situations where the user cannot reasonably proceed.
- Use `warning` when the situation is recoverable but noteworthy.
- Avoid catching errors and ignoring them without logging or rethrowing.

### 5.4 Dependencies and compatibility

- Avoid relying on very new MATLAB features unless necessary.
- If you add a dependency on a specific toolbox or function, document it in:
  - The function header comment, and
  - `README.md` (or a dedicated dependency section) if it is user-visible.

---

## 6. Testing and sample data

GNAT currently relies mostly on manual testing with representative datasets.

We aim to formalise this gradually; in the meantime, developers should:

- Test new functionality on at least one relevant dataset.
- Run a small set of key GNAT workflows to check nothing obvious has broken.

> **TODO:** Once agreed, document:
>
> - Where test data lives in the repo (if included), or where it is stored externally.
> - Which scripts / pipelines should be run as a “smoke test”.
> - Any automated tests or scripts (e.g. a MATLAB script that exercises common paths).

Suggested eventual structure (for when we get there):

- `testdata/`
  - Small anonymised datasets for regression testing.
- `tests/` or `devtools/tests/`
  - MATLAB scripts that run a standard set of operations and report success/failure.

---

## 7. Common developer tasks

This section is meant as a quick reference for frequent tasks.  
Fill in concrete details as patterns stabilise.

### 7.1 Adding a new processing function

Typical steps (to be adapted to GNAT’s actual architecture):

1. Identify the appropriate module / folder where similar functions live.
2. Add your new `.m` file there with a clear name and header comment.
3. Integrate it into the workflow:
   - Update any central dispatch / pipeline code.
   - If applicable, expose it in the GUI (menu item, button, etc.).
4. Add minimal documentation:
   - Short note in the help / manual.
   - Example usage script or update to an existing example.
5. Test on a representative dataset.
6. Commit on a feature branch and open a PR.

### 7.2 Modifying the GUI

The GUI has potential for subtle breakage, so take extra care:

1. Locate the main GUI `.m` file(s) and associated callbacks.
2. If adding a new button/menu:
   - Follow the patterns used for existing controls.
   - Keep the UI text consistent with the rest of GNAT.
3. Ensure that callbacks:
   - Handle invalid inputs gracefully.
   - Do not assume undocumented global state.
4. Test:
   - Launch the GUI from a clean MATLAB session.
   - Exercise both the new and a few existing features.
5. Commit with a clear message indicating it is a GUI change.

> **TODO:** Add concrete filenames and patterns once we standardise the GUI structure.

### 7.3 Adding or updating file format support

1. Identify the import/export layer (e.g. where Bruker, JEOL, etc. formats are handled).
2. Encapsulate format-specific logic in clearly named functions.
3. Document assumptions about:
   - Directory structure,
   - Required metadata,
   - Units and scaling.
4. Test with multiple datasets (if possible) from slightly different instruments/versions.
5. If this change might affect existing users, mention it clearly in the PR and release notes.

---

## 8. Branch tidy-up policy

Because contributors come and go, old branches accumulate. To keep the repo healthy:

- Branches that have been **merged into `master`** should be:
  - Deleted on GitHub after merge.
  - Deleted locally by developers when convenient.

- Branches that have **not been merged** and are clearly abandoned:
  - Can be deleted after a sanity check of the diff.
  - If in doubt, open an issue and mention the original author.

Occasional maintenance task for the maintainer:

- Review remote branches (e.g. every few months).
- For each:
  - If merged → delete.
  - If not merged but obsolete → delete after a brief look at the diff.
  - If not merged and potentially important → open an issue / talk to the group.

---

## 9. Getting help

If you are stuck or unsure about a change:

- Open a GitHub issue labelled `question` or `dev-help`, or
- Talk directly to the maintainer / local GNAT expert in the group.

It is always better to ask early than to spend time heading in the wrong direction.

## 10. Maintainer checklist

This section summarises routine tasks for the GNAT maintainer.

### 10.1 When reviewing pull requests

- [ ] Check that the PR targets the correct branch:
  - **Base branch:** `master`
  - **Compare branch:** contributor’s feature branch
- [ ] Skim the diff:
  - Only relevant files changed
  - No accidental edits (e.g. large reformatting, unrelated files)
- [ ] Confirm that the contributor has tested their changes on at least one appropriate dataset  
  (via PR description or comments).
- [ ] If satisfied, merge the PR (using a merge commit or squash merge, as appropriate).
- [ ] Ensure the feature branch is deleted on GitHub  
  (this should usually happen automatically via the “delete head branches” setting).
- [ ] In GitHub Desktop (or via git), pull the latest `master` so your local copy is up to date.

### 10.2 When preparing a new GNAT release

- [ ] Ensure `master` is in a good state:
  - All intended PRs have been merged
  - No known serious regressions
- [ ] On GitHub, go to **Releases → Draft a new release**.
- [ ] Create a new tag from `master` for the release, for example:
  - `GNAT-2.1`, `GNAT-2.2`, etc.
- [ ] Set the release title to match the tag (e.g. `GNAT 2.1`).
- [ ] Write short release notes:
  - Key new features
  - Important bug fixes
  - Any compatibility notes (MATLAB version, data formats, etc.)
- [ ] Publish the release.
- [ ] Optionally:
  - Download the release archive (zip/tar)
  - Update the GNAT homepage and documentation to point to this release

### 10.3 Periodic housekeeping (e.g. once per term)

- [ ] Review branches on GitHub:
  - Delete branches that are clearly merged and no longer needed.
  - For old, unmerged branches:
    - Briefly inspect the diff.
    - Talk to the original author or open an issue summarising the state.
- [ ] Review releases:
  - Check that the latest release matches what you are recommending to users.
- [ ] Review issues:
  - Label new issues as `bug`, `enhancement`, `question`, etc.
  - Close issues that are clearly obsolete, fixed, or superseded.
- [ ] Consider whether any frequently repeated manual checks could be
  turned into simple scripts or tests for future automation.
