<!---
# cspell: ignore Bambu, pyinstaller, BambuLab, Jayo
---> 

# slicer_tools

A library of python tools for working with 3D slicer files (.3mf). Currently the
library supports Bambu Studio on the following very limited function set:
- Comparison of printer presets across multiple files. Comparisons are presented
as Excel (.xlsx, readable by LibreOffice) files, which detail the differences between
presets in all of the selected files and the system presets. The main purpose of this
is to extract common settings from multiple files, but may also be useful in debugging
files with many changes.
- A dumper that will export all settings contained in preset (generated by walking
the preset inheritance tree).

Minor editorial comment: The preset file structure used by BambuStudio (and presumably
other slicers in the same family) is so chaotic and internally inconsistent that while
this project should have been a couple of hundred lines of quick and dirty code, it's
now approaching 2000 for fairly minimal functionality. I'm releasing it because the
difference function has been genuinely useful for me in building new presets, and the
dump function is useful for checking presets. It also provides a first pass for
programmatic access to .3mf files and presets, but it's up to someone else to decide if
it is worth picking up to do more with.

# Change Log

From v0.9.0 is the first release, with limited feature set.

# Installation

Two options: 

- Download the Windows executable (created with pyinstaller) from the 
[Releases](https://github.com/BuongiornoTexas/slicer_tools/releases) page.

- Install the package from pip: `pip install slicer_tools`.

To run, fire up a command or terminal window and run `slicer_tools.exe`, or to run from
the python package, use `py -m slicer_tools.tools`. The rest of the docs use
`slicer_tools.exe`, but feel free to use the python version if you want very slightly
faster output (or if you are on a non-windows platform).  

# Usage

## Differences

To generate preset differences for a single file, run:

`slicer_tools diff --source <path to 3mf file> --output <output file>`

The output file is optional and defaults to `preset_diffs.xlsx`, and will be created in
the same folder as the input file.

To generate preset differences for all `.3mf` files in a folder, run:

`slicer_tools diff --source <path to folder> --output <output file>`

Both source and output are optional for this mode. If source is skipped, the difference
will be performed on the working directory, and if output is skipped, the output is
written to `preset_diffs.xlsx`.

For help, run `slicer_tools diff -h`.

See [Difference File Structure](#difference-file-structure) for details and cautions on
using the output file.

## Preset Export

To generate one or more complete presets from a single file, each in `.json` format,
run:

`slicer_tools export <path to file name>`

The slicer tools will then guide you through selecting the preset type you want to
export and allow you to choose one or more presets of that type for export.

As I've needed to do some hacks for generating differences, please read the
[**WARNINGS**](#warnings-please-read-this-section) in the following section, as the
exported files may not perfectly match the structure used internally by BambuStudio
(they work well enough for the purposes of creating new presets, and I've run out of
patience to deal with the special cases). The warnings about the following special
fields are relevant:

- `name` and `<type>_settings_id`.
- `inherits`.
- `from`.
- `version`. 

If you plan to use any of these fields, please cross check against the original preset
file. 

All other fields should be consistent with the original files and inheritance trees.

# Difference File Structure

A slicer_tools difference file is an Excel/Libre Office compatible `.xlsx` file that:

- contains preset difference information for all of the `.3mf` files processed by the
slicer_tools `diff` subcommand; and 
- consists of three work sheets, one for each of `filament`, `process` and `machine`,
corresponding to the BambuStudio preset types.  

By far the easiest way to understand the difference file structure is to run a diff 
on a folder containing a couple of `.3mf` files and take a look at the resulting diff
file. Once you have done that, the long winded descriptions in the rest of this section
will be more useful and will likely make more sense.

Each worksheet summarises the differences between `project`/`override` presets and the
`system` presets they have been built/inherited from. As these terms don't have a formal
BambuStudio definition (at least not as far as I've found!), they and the related `user`
preset are defined as follows for the purposes of slicer_tools:

- A `system` preset is one of the default presets available within BambuStudio, which
are available from the "System presets" dropdowns in BambuStudio and can be found in the
`%AppData%\BambuStudio\system\BBL` folder on Windows.
- A `user` preset is a user defined preset that is shared between all `.3mf` project
files. These are stored in the `%AppData%\BambuStudio\user\<userid>` folder on Windows.
These may form part of the inheritance tree for a project preset. (BUT: See
[**WARNINGS**](#warnings-please-read-this-section) and discussion below for handling of
`base` user presets in slicer_tools.)
- A `project` preset is preset saved as a "Preset Inside Project" within a `.3mf`
project file.
- An `override` preset is a preset that applies to one or more objects in a current
model - it is the preset name that appears in the drop down selection box for the
machine, each of the filaments and the current process settings for the project. An
override preset may have a number of changes that apply for the project (orange values
in the GUI), or may be the same as the source preset they are build from (no orange
values). 

  Note 1: that `override` presets are not defined at all in BambuStudio - they are a
  group I have created in order to be able to capture differences that result from using
  orange **override** values in BambuStudio. (It's up to you to decide if they are
  useful or not!).

  Note 2: `override` presets do not have unique names in BambuStudio - they have the
  same name as the parent preset they are built from. To handle this quirk in the
  difference tool, I take the parent name and append a suffix consisting an underscore
  and some random characters to provide the `override` with a unique name. Again, this
  is a useful convention for differencing and has no meaning within BambuStudio.

The slicer_tools package refers to the collective of the `system`, `user`, `project`
and `override` presets as "preset groups".

With all that defined, difference are generated using the following logic:

- For each `project` and `override` preset in a `.3mf` file (the `active` preset):
  - Generate  a list of all settings and settings values for the `active` preset by
  walking the inheritance tree for the preset.
  - While walking the inheritance tree, identify the youngest `system` ancestor of the
  `active` preset (the `system` ancestor furtherest away from the root of the tree).
  - If the setting value for the youngest `system` ancestor is the same as the setting
  value for the `active` preset, proceed to the next setting (no difference found).
  - Otherwise, a difference exists, so record the setting name, the `active` value and
  the value for the youngest `system` ancestor (this is the `system` reference value).

When recording the value in the worksheet, the following rules are applied:

- If the value is a string value or a list containing a single string \[string\], the 
 string value is recorded (list entry popped if required).
- If the value is empty (unfortunately, yes this can happen), an empty string is
recorded.
- Otherwise the value is recorded verbatim - e.g. ["string1", "string2"], etc.

After this, the values are colour coded to address a whole series of special cases and
issues:

- If the reference value is unset, the reference value is an empty cell, highlighted in
pink. 
- If either value has a format more complex than string or \[string\], it is highlighted
as too complex to difference.
- A normal reference `system` value is highlighted in green.
- If the `active` preset is an `override` and the setting value is different from 
the system value and different from the `active` preset's parents value, then the
difference is highlighted as an `override`. I believe this more or less matches orange
highlighted values in BambuStudio.

Finally, a small number of settings are highlighted as *Special*. These are settings
where I have either altered the BambuStudio data to make the difference work, or are
values that require special handling when generating your own presets from the
difference data - see [Warnings](#warnings-please-read-this-section) for more detail on
each field and the [workflow](#workflow-for-creating-new-presets) for creating new
presets for more detail on these. If you are particularly concerned about where I have
modified fields, please review the warnings about base `user` presets, version values
and inherits values.

## WARNINGS: PLEASE READ THIS SECTION

These warnings may repeat information from elsewhere. 

- `override` presets do not exist in BambuStudio. They are a convenience I have created
for the purposes of differencing.
- Similarly, `override` presets do not have unique names (or names at all). As a
convenience for differencing, I've created random names by appending an underscore and
random characters to the end of the parent preset name.
- BambuStudio's JSON handling is all over the place. Some values are strings, 
some values are lists containing a single string, and some are more complex. The diff
tool will extract the string value for the first two cases and doesn't handle the third.
If you are using the output from the diff tool, please be aware of this and cross check 
 that your json format matches the json format in an actual BambuStudio file (i.e. the
 diff tool is not definitive for formatting).
- BambuStudio treats `user` defined base presets as if they were `system` presets. I
follow this treatment, but to make it work, I redefine the `FROM` field for these
presets from `user` to `system`. As the difference tool isn't designed to work on these
presets, I don't think this has any practical impact for differencing. However, this is
important for settings export as the `FROM` field will be incorrect (but you should just
be referring directly to the base file in this case anyway). 
- I do not know how to create consistent version numbers, so if a version number is
missing, I specify it as `xx.xx.xx.xx`. 
- Some system files are missing `INHERITS` values. This only occurs in files at the root
of the inheritance tree, so I add in a {"inherits": ""} setting to allow the difference
engine to work correctly.
- The difference engine highlights several values as *special*, as these are values that
BambuStudio either always creates in preset files, or are related to one another, or
both. If you are going to use difference output to create your own presets, I suggest
using the workflow outlined in the following section to generate templates that will
create these fields for you automatically.

# Workflow for Creating New Presets

I'd suggest using this process for creating **process** and **filament** presets only.
A lot could go wrong with tweaking **machine** presets, so this is probably better done
within the slicer itself (where the slicer should handle error checking properly).

## Creating a Template

This process handles creating a preset containing internally correct *special* values
(see [Warnings](#warnings-please-read-this-section)).

- Run BambuStudio.
- Create a dummy preset to use as a template:
  1) Start with a preset that is the basis for the new preset. For example, for a
  generic TPU, select "Generic TPU" or "Bambulab TPU95A", or for a process preset for
  the X1C start with "0.20mm Standard @BBL X1C".
  2) Save the preset as a **user** preset. E.g. "Jayo TPU" or "0.20mm Standard for
  Jayo TPU @BBL X1C". **Don't** make any changes to this preset.
  3) Export the presets. `File->Export->Export Preset Bundle ... `
     - `-> Process presets(.zip)` and extract the preset .json file you have just
     created.
     - `-> Filament presets(.zip)` and extract the preset .json file you have just
     created.

     These json files are the templates for your new presets, and should have all of the
     *special* fields prepopulated for you -
     See [Warnings](#warnings-please-read-this-section).
  
  4) Back inside Bambu Studio, **DELETE** the presets you created in step (2).

I've included filament and process template files in the
[examples](https://github.com/BuongiornoTexas/slicer_tools/tree/main/examples) folder to
give an idea of the expected output (`Generic TPU - Jayo Template.json` and `0.20mm
Standard Jayo TPU Template @BBL X1C.json`).

## Create Preset File, Add New Fields

This step is pretty straightforward: 
- Copy the template file and rename with a `.json` extension to create the new preset
file.
- Add any new settings/value pairs that you want to the new preset file, taking care to
not replace any of the *special* fields copied over from the template.

If you are using the output of a difference run to decide which fields you want to add,
note again that the difference tool tries to provide value differences, but provides no
information about the correct formats for each field. JSON fields may be in a couple of
different formats:

1. A list containing a string value. 
    ```
    "filament_max_volumetric_speed": [
        "2.5"
    ],
    ```

2. A string value.
    ```
    "brim_width": "5",
    ```

3. Something more complex:
    ```
    "bed_exclude_area": [
        "0x0",
        "18x0",
        "18x28",
        "0x28"
    ],
    ```

I've found the easiest way to set up new fields and values is to assume everything
follows format (2), setup an Excel formula to generate the fields in a spreadsheet,
copy/paste the values into the preset file, and then compare the formats to an
[exported preset](#preset-export) and correct the format if required. 

As I've only been working with 15-20 settings per file, the modest amount of manual data
handling required is massively lower than the effort to get slicer tools to sort the
output format correctly, so I'm willing to live with it. If any one wants to pick up
the automation torch, please go wild! (contributions happily accepted)

## Load and Test the Preset

Import the preset(s) created in the previous steps back into Bambu Studio.
`File->Import->Import Configs`.

Finally use the slicer_tools utility (difference or export) or the slicer GUI compare
interface to check that your new preset settings match up with the settings you created
above. You can also re-export your newly imported preset and check that all of the
fields/settings are as expected.

# Sample TPU Presets

The slicer tools repository includes the following TPU
[preset examples](https://github.com/BuongiornoTexas/slicer_tools/tree/main/examples) I
developed using this package:

- A process preset for generic TPU: `0.20mm Standard for Jayo TPU @BBL X1C.json`.
- A filament preset for generic TPU: `Generic TPU High Quality.json`. 
- A filament preset calibrated for Jayo TPU at my local ambient conditions (60%
humidity, 13C): `Jayo TPU Flow Rate Calibrated.json`.

To use these, you will need to import the process preset and one of the filament presets
and use **both** of them together (the process preset is critical for extrusion speed
control, and the same preset works with both filament presets).

Again, the Jayo TPU filament preset is calibrated for my local ambient conditions. 
I'd strongly calibrating your own filament by starting with the generic TPU preset
(which uses the BambuLab `Generic TPU` settings for temperature, flow ratio and
K-factor), and run the following calibrations for your own filament:
- a temperature tower (I've had good success at 205C, but many TPU profiles run between
220C and 240C, and depending on your filament this may be needed to ensure good layer
adhesion (my TPU looks best at 190C, but I've needed to go a bit higher for strength at
the cost of a small amount of stringing and slightly worse overhangs);
- a flow calibration (0.931 flow ratio for my TPU); and
- a pressure advance calibration (0.04 K-factor for me). 

(If you do try my Jayo settings and don't get great results, I'd suggest bumping your
nozzle temperatures as a first fix - also check the manufacturer temperature range.)

If you want to try it out from BambuStudio directly, please see my demonstration model
on [MakerWorld](https://makerworld.com/en/@user_18681024/profile) - if it's not live
already, it will be uploaded shortly. The MakerWorld page has a bit more detail on the
basis for the settings and a lot of photos. 