Skip to content

[bug]: (damage branch) nodestats : key error : 'avg_mask' #1369

@SylviaWhittle

Description

@SylviaWhittle

Checklist

  • Run using the main branch to check if the issue persists. Instructions on how to do this can be found here.
  • Find the offending file in the output. If processing halts, re-run analysis with topostats --core 1 process.
  • Describe the bug.
  • Include the configuration file.
  • Copy of the log-file from running with topostats --log-level debug <command>.
  • The exact command that failed. This is what you typed at the command line, including any options.
  • TopoStats version, this is reported by topostats --version
  • Operating System and Python Version

Describe the bug

On the damage branch, with a particular image, (specifically 20251203_TAF_water_blank.0_00002.topostats found in the damage project directory on the X drive (ask Tobi or Sylvia), can't post full path or image here), nodestats crashes.

Copy of the log-file from running with topostats --log-level debug <command>

here's the relevant part:

[Tue, 16 Jun 2026 12:35:27] [INFO    ] [topostats] [20251203_TAF_water_blank.0_00002.spm] : Disordered Tracing stage completed successfully.
[Tue, 16 Jun 2026 12:35:27] [INFO    ] [topostats] [20251203_TAF_water_blank.0_00002.spm] : Disordered trace plotting completed successfully.
[Tue, 16 Jun 2026 12:35:27] [INFO    ] [topostats] [20251203_TAF_water_blank.0_00002.spm] : *** Nodestats ***
[Tue, 16 Jun 2026 12:35:27] [INFO    ] [topostats] [20251203_TAF_water_blank.0_00002.spm] : There are 1 grains
[Tue, 16 Jun 2026 12:35:27] [ERROR   ] [topostats] [20251203_TAF_water_blank.0_00002.spm] : Nodestats for grain 0 failed. Please consider raising an issue on GitHub. Error: 
Traceback (most recent call last):
  File "/Users/sylvi/src/TopoStats/topostats/tracing/nodestats.py", line 1764, in nodestats_image
    _, node_image_dict = nodestats.get_node_stats()
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/sylvi/src/TopoStats/topostats/tracing/nodestats.py", line 167, in get_node_stats
    self.analyse_nodes(max_branch_length=self.branch_pairing_length)
  File "/Users/sylvi/src/TopoStats/topostats/tracing/nodestats.py", line 540, in analyse_nodes
    branch_image, avg_image = nodeStats.add_branches_to_labelled_image(
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/sylvi/src/TopoStats/topostats/tracing/nodestats.py", line 649, in add_branches_to_labelled_image
    avg_image[masked_image[branch_index]["avg_mask"] != 0] = i + 1
              ~~~~[Tue, 16 Jun 2026 12:35:27] [ERROR   ] [topostats] [nodestats.py] [1783] [20251203_TAF_water_blank.0_00002.spm] : Nodestats for grain 0 failed. Please consider raising an issue on GitHub. Error: 
Traceback (most recent call last):
  File "/Users/sylvi/src/TopoStats/topostats/tracing/nodestats.py", line 1764, in nodestats_image
    _, node_image_dict = nodestats.get_node_stats()
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/sylvi/src/TopoStats/topostats/tracing/nodestats.py", line 167, in get_node_stats
    self.analyse_nodes(max_branch_length=self.branch_pairing_length)
  File "/Users/sylvi/src/TopoStats/topostats/tracing/nodestats.py", line 540, in analyse_nodes
    branch_image, avg_image = nodeStats.add_branches_to_labelled_image(
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/sylvi/src/TopoStats/topostats/tracing/nodestats.py", line 649, in add_branches_to_labelled_image
    avg_image[masked_image[branch_index]["avg_mask"] != 0] = i + 1
              ~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^
KeyError: 'avg_mask'
~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^
KeyError: 'avg_mask'
[Tue, 16 Jun 2026 12:35:27] [INFO    ] [topostats] [20251203_TAF_water_blank.0_00002.spm] : NodeStats stage completed successfully.
[Tue, 16 Jun 2026 12:35:28] [INFO    ] [topostats] [20251203_TAF_water_blank.0_00002.spm] : Nodestats plotting completed successfully.
[Tue, 16 Jun 2026 12:35:28] [INFO    ] [topostats] [20251203_TAF_water_blank.0_00002.spm] : *** Ordered Tracing ***
[Tue, 16 Jun 2026 12:35:28] [INFO    ] [topostats] [20251203_TAF_water_blank.0_00002.spm] : Calculating Ordered Traces and Statistics for 1 grains...
[Tue, 16 Jun 2026 12:35:28] [INFO    ] [topostats] [20251203_TAF_water_blank.0_00002.spm] : Grain 1 present in NodeStats. Tracing via Nodestats.

Include the configuration file

# Config file generated 2026-04-22 13:38:04
# For more information on configuration and how to use it:
# https://afm-spm.github.io/TopoStats/main/configuration.html
base_dir: ../all_data # Directory in which to search for data files
output_dir: ./output # Directory to output results to
log_level: info # Verbosity of output. Options: warning, error, info, debug
cores: 1 # Number of CPU cores to utilise for processing multiple files simultaneously.
file_ext: .spm # File extension of the data files.
output_stats: full # Options : basic (image, grain), full (image, grain, molecule, branch)
loading:
  channel: Height Sensor # Channel to pull data from in the data files.
  extract: raw # Array to extract when loading .topostats files.
filter:
  run: true # Options : true, false
  row_alignment_quantile: 0.5 # lower values may improve flattening of larger features
  threshold_method: std_dev # Options : otsu, std_dev, absolute
  otsu_threshold_multiplier: 1.0
  threshold_std_dev:
    below: 10.0 # Threshold for data below the image background
    above: 1.0 # Threshold for data above the image background
  threshold_absolute:
    below: -1.0 # Threshold for data below the image background
    above: 1.0 # Threshold for data above the image background
  gaussian_size: 1.0121397464510862 # Gaussian blur intensity in px
  gaussian_mode: nearest # Mode for Gaussian blurring. Options : nearest, reflect, constant, mirror, wrap
  # Scar removal parameters. Be careful with editing these as making the algorithm too sensitive may
  # result in ruining legitimate data.
  remove_scars:
    run: false
    removal_iterations: 2 # Number of times to run scar removal.
    threshold_low: 0.250 # lower values make scar removal more sensitive
    threshold_high: 0.666 # lower values make scar removal more sensitive
    max_scar_width: 4 # Maximum thickness of scars in pixels.
    min_scar_length: 16 # Minimum length of scars in pixels.
grains:
  run: true # Options : true, false
  # Thresholding by height
  grain_crop_padding: 1 # Padding to apply to grains. Needs to be at least 1, more padding may help with unets.
  threshold_method: absolute # Options : std_dev, otsu, absolute, unet
  otsu_threshold_multiplier: 1.0
  threshold_std_dev:
    below: [10.0] # Thresholds for grains below the image background. List[float].
    above: [1.0] # Thresholds for grains above the image background. List[float].
  threshold_absolute:
    below: [-1000.0] # Thresholds for grains below the image background. List[float].
    above: [1.2] # Thresholds for grains above the image background. List[float].
  area_thresholds:
    above: [300, 300000000000] # above surface [Low, High] in nm^2 (also takes null)
    below: [null, null] # below surface [Low, High] in nm^2 (also takes null)
  remove_edge_intersecting_grains: true # Whether or not to remove grains that touch the image border
  endpoint_connection_config:
    run: true # Whether to run the endpoint connection process
    class_indices: [1] # List of class indices to process
    skeletonisation_holearea_min_max: [0, null] # Range (min, max) of a hole area in nm to refill in the smoothed masks.
    skeletonisation_mask_smoothing_dilation_iterations: 2 # Number of dilation iterations to use for grain smoothing.
    skeletonisation_mask_smoothing_gaussian_sigma: 2 # Gaussian smoothing parameter 'sigma' in pixels.
    skeletonisation_method: topostats # Options : zhang | lee | thin | topostats
    skeletonisation_height_bias: 0.6 # Percentage of lowest pixels to remove each skeletonisation iteration. 1 equates to zhang.
    endpoint_connection_distance_nm: 10.0 # Maximum distance in nm to connect endpoints.
    endpoint_connection_cost_map_height_maximum: 3.0 # Maximum height in nm to consider when building the cost map for endpoint connection. Should roughly be the maximum height of your sample.
    pruning_params:
      method: topostats # Method to clean branches of the skeleton. Options : topostats
      max_length: 10.0 # Maximum length in nm to remove a branch containing an endpoint.
      height_threshold: # The height to remove branches below.
      method_values: mid # The method to obtain a branch's height for pruning. Options : min | median | mid.
      method_outlier: abs # The method to prune branches based on height. Options : abs | mean_abs | iqr.
      only_height_prune_endpoints: False # Whether to restrict height-based pruning to skeleton segments containing an endpoint or not.
  unet_config:
    model_path: null # Path to a trained U-Net model
    upper_norm_bound: 5.0 # Upper bound for normalisation of input data. This should be slightly higher than the maximum desired / expected height of grains.
    lower_norm_bound: -1.0 # Lower bound for normalisation of input data. This should be slightly lower than the minimum desired / expected height of the background.
    remove_disconnected_grains: false # Whether to remove grains in the crop that don't touch the original grain mask.
    confidence: 0.5 # Confidence threshold for the UNet model. Smaller is more generous, larger is more strict.
  vetting:
    whole_grain_size_thresholds: null # Size thresholds for whole grains in nanometres squared, ie all classes combined. Tuple of 2 floats, ie [low, high] eg [100, 1000] for grains to be between 100 and 1000 nm^2. Can use None to not set an upper/lower bound.
    class_conversion_size_thresholds: null # Class conversion size thresholds, list of tuples of 3 integers and 2 integers, ie list[tuple[tuple[int, int, int], tuple[int, int]]] eg [[[1, 2, 3], [5, 10]]] for each region of class 1 to convert to 2 if smaller than 5 nm^2 and to class 3 if larger than 10 nm^2.
    class_region_number_thresholds: null # Class region number thresholds, list of lists, ie [[class, low, high],] eg [[1, 2, 4], [2, 1, 1]] for class 1 to have 2-4 regions and class 2 to have 1 region. Can use None to not set an upper/lower bound.
    class_size_thresholds: null # Class size thresholds (nm^2), list of tuples of 3 integers, ie [[class, low, high],] eg [[1, 100, 1000], [2, 1000, None]] for class 1 to have 100-1000 nm^2 and class 2 to have 1000-any nm^2. Can use None to not set an upper/lower bound.
    nearby_conversion_classes_to_convert: null # Class conversion for nearby regions, list of tuples of two-integer tuples, eg [[[1, 2], [3, 4]]] to convert class 1 to 2 and 3 to 4 for small touching regions
    class_touching_threshold: 5 # Number of dilation steps to use for detecting touching regions
    keep_largest_labelled_regions_classes: null # Classes to keep the only largest regions for, list of integers eg [1, 2] to keep only the largest regions of class 1 and 2
    class_connection_point_thresholds: null # Class connection point thresholds, [[[class_1, class_2], [min, max]]] eg [[[1, 2], [1, 1]]] for class 1 to have 1 connection point with class 2
  classes_to_merge: null # Classes to merge into a single combined class. List of lists, eg [[1, 2]] to merge classes 1 and 2. New classes will be appended to the tensor.
grainstats:
  run: true # Options : true, false
  edge_detection_method: binary_erosion # Options: canny, binary erosion. Do not change this unless you are sure of what this will do.
  extract_height_profile: true # Extract height profiles along maximum feret of molecules
  class_names: ["DNA", "Protein"] # The names corresponding to each class of a object identified, please specify merged classes after.
disordered_tracing:
  run: true # Options : true, false
  class_index: 1 # The class index to trace. This is the class index of the grains.
  min_skeleton_size: 10 # Minimum number of pixels in a skeleton for it to be retained.
  mask_smoothing_params:
    gaussian_sigma: 2 # Gaussian smoothing parameter 'sigma' in pixels.
    dilation_iterations: 2 # Number of dilation iterations to use for grain smoothing.
    holearea_min_max: [0, null] # Range (min, max) of a hole area in nm to refill in the smoothed masks.
  skeletonisation_params:
    method: topostats # Options : zhang | lee | thin | topostats
    height_bias: 0.6 # Percentage of lowest pixels to remove each skeletonisation iteration. 1 equates to zhang.
  pruning_params:
    method: topostats # Method to clean branches of the skeleton. Options : topostats
    max_length: 10.0 # Maximum length in nm to remove a branch containing an endpoint.
    height_threshold: # The height to remove branches below.
    method_values: mid # The method to obtain a branch's height for pruning. Options : min | median | mid.
    method_outlier: abs # The method to prune branches based on height. Options : abs | mean_abs | iqr.
    only_height_prune_endpoints: False # Whether to restrict height-based pruning to skeleton segments containing an endpoint or not.
close_strand_correction:
  run: true
  true_peak_threshold_median_multiplier: 1.1  # Minimum height in nm required for a crossing to be considered a true crossing.
  branch_explore_distance_nm: 2.5  # Maximum distance in nm to explore along a branch from a node for creating
  cost_image_exponent: 4.0  # Exponent to apply to the cost image to increase the cost of using lower pixels
  cost_image_base: 0.01  # base cost to prevent zero cost pixels, just in case
  crossing_correction_strand_minimum_height_nm: 1.0  # minimum height for a strand to be used for crossing correction
nodestats:
  run: true # Options : true, false
  node_joining_length: 7.0 # The distance in nanometres over which to join nearby crossing points.
  node_extend_dist: 14.0 # The distance in nanometres over which to join nearby odd-branched nodes.
  branch_pairing_length: 20.0 # The length in nanometres from the crossing point to pair and trace, obtaining FWHM's.
  pair_odd_branches: false # Whether to try and pair odd-branched nodes. Options: true and false.
ordered_tracing:
  run: true
  ordering_method: nodestats # The method of ordering the disordered traces. Options : nodestats | original
splining:
  run: true # Options : true, false
  method: "rolling_window" # Options : "spline", "rolling_window"
  rolling_window_size: 5.0e-9 # size in nm of the rolling window.
  rolling_window_resampling: true # Whether to resample the trace or not.
  rolling_window_resample_regular_spatial_interval: 0.5e-9 # The spatial interval to resample the trace to in nm.
  spline_step_size: 7.0e-9 # The sampling rate of the spline in metres.
  spline_linear_smoothing: 5.0 # The amount of smoothing to apply to linear features.
  spline_circular_smoothing: 5.0 # The amount of smoothing to apply to circular features.
  spline_degree: 3 # The polynomial degree of the spline.
curvature:
  run: true # Options : true, false
  smoothing_method: "gaussian" # Options : "gaussian", "savitzky_golay"
  smoothing_gaussian_sigma_nm: 1.0 # The sigma of the Gaussian smoothing kernel in nm.
  smoothing_savgol_window_length_nm: 10.0 # The window length of the Savitzky-Golay smoothing kernel in nm.
  smoothing_savgol_polyorder: 2 # The polynomial order of the Savitzky-Golay smoothing kernel.
  curvature_turn_minimum_delay_nm: 20.0 # The minimum distance in nm before re-assessing if in a turn or not.
  curvature_turn_threshold_iqr_multiplier: 1.5 # The multiplier for the IQR for determining if in a turn or not.
plotting:
  run: true # Options : true, false
  style: topostats.mplstyle # Options : topostats.mplstyle or path to a matplotlibrc params file
  savefig_format: null # Options : null, png, svg or pdf. tif is also available although no metadata will be saved. (defaults to png) See https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.savefig.html
  savefig_dpi: 400 # Options : null (defaults to the value in topostats/plotting_dictionary.yaml), see https://afm-spm.github.io/TopoStats/main/configuration.html#further-customisation and https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.savefig.html
  pixel_interpolation: null # Options : https://matplotlib.org/stable/gallery/images_contours_and_fields/interpolation_methods.html
  grain_crop_plot_size_nm: -1 # Size in nm of the square cropped grain images if using the grains image set. If -1, will use the grain's default bounding box size.
  image_set: # Options : all, core, filters, grains, grain_crops, disordered_tracing, nodestats, ordered_tracing, splining. Uncomment to include
    # - all
    - core
    # - filters
    # - grains
    # - grain_crops
    # - disordered_tracing
    - close_strand_correction
    # - nodestats
    # - ordered_tracing
    # - splining
    # - curvature
  zrange: [-3, 4] # low and high height range for core images (can take [null, null]). low <= high
  colorbar: true # Options : true, false
  trace_linewidth: 1.0 # Linewidth for spline and cuvature traces.
  axes: true # Options : true, false (due to off being a bool when parsed)
  num_ticks: [null, null] # Number of ticks to have along the x and y axes. Options : null (auto) or integer > 1
  cmap: null # Colormap/colourmap to use (default is 'nanoscope' which is used if null, other options are 'afmhot', 'viridis' etc.)
  mask_cmap: blue_purple_green # Options : blu, jet_r and any in matplotlib
  histogram_log_axis: false # Options : true, false
  number_grains: true # Add grain numbers next to each grain mask in images with mask overlays. Options : true, false
summary_stats:
  run: false # Whether to make summary plots for output data
  config: null

To Reproduce

Run the damage branch (probably main too) on this file.

TopoStats Version

Git main branch

Python Version

3.11

Operating System

MacOS M1/M2 (post-2021)

Python Packages

absl-py==2.2.2
AFMReader @ git+https://github.com/AFM-SPM/AFMReader@7869b5be94ebf9febf20d0121a2828f4202f087c
annotated-types==0.7.0
anyio==4.12.1
appnope==0.1.4
argon2-cffi==25.1.0
argon2-cffi-bindings==25.1.0
arrow==1.4.0
art==6.5
astroid==3.3.10
asttokens==3.0.0
astunparse==1.6.3
async-lru==2.3.0
attrs==26.1.0
babel==2.18.0
backrefs==6.2
beautifulsoup4==4.14.3
biopython==1.85
black==25.1.0
bleach==6.3.0
certifi==2025.4.26
cffi==2.0.0
cfgv==3.4.0
charset-normalizer==3.4.2
cheap_repr==0.5.2
click==8.2.1
cmapy==0.6.6
colorama==0.4.6
comm==0.2.2
contourpy==1.3.2
coverage==7.8.2
cycler==0.12.1
debugpy==1.8.14
decorator==5.2.1
defusedxml==0.7.1
dill==0.4.0
distlib==0.3.9
docstring_parser==0.16
docutils==0.22.4
EditorConfig==0.17.1
et_xmlfile==2.0.0
execnet==2.1.1
executing==2.2.0
fastjsonschema==2.21.2
filelock==3.18.0
filetype==1.2.0
flatbuffers==25.2.10
fonttools==4.58.0
fqdn==1.5.1
gast==0.6.0
ghp-import==2.1.0
google-pasta==0.2.0
gprof2dot==2025.4.14
griffelib==2.0.2
grpcio==1.71.0
h11==0.16.0
h5py==3.13.0
hmmlearn==0.3.3
httpcore==1.0.9
httpx==0.28.1
icdiff==2.0.7
identify==2.6.12
idna==3.10
igor==0.3
igor2==0.5.12
imageio==2.37.0
iniconfig==2.1.0
ipykernel==6.29.5
ipython==8.36.0
ipython-genutils==0.2.0
ipywidgets==8.1.8
isoduration==20.11.0
isort==6.0.1
itsdangerous==2.2.0
jedi==0.19.2
Jinja2==3.1.6
joblib==1.5.0
jsbeautifier==1.15.4
json5==0.14.0
jsonpointer==3.1.1
jsonschema==4.26.0
jsonschema-specifications==2025.9.1
jupyter-events==0.12.1
jupyter-highlight-selected-word==0.2.0
jupyter-lsp==2.3.1
jupyter_client==8.6.3
jupyter_contrib_core==0.4.2
jupyter_contrib_nbextensions==0.7.0
jupyter_core==5.8.1
jupyter_nbextensions_configurator==0.6.4
jupyter_server==2.17.0
jupyter_server_terminals==0.5.4
jupyterlab==4.5.6
jupyterlab_pygments==0.3.0
jupyterlab_server==2.28.0
jupyterlab_widgets==3.0.16
jupyterthemes==0.20.0
keras==3.10.0
kiwisolver==1.4.8
lark==1.3.1
lazy_loader==0.4
lesscpy==0.15.1
Levenshtein==0.27.3
libclang==18.1.1
line_profiler==5.0.2
llvmlite==0.44.0
loguru==0.7.3
loro==1.10.3
lxml==6.1.0
magicgui==0.10.0
marimo==0.21.1
Markdown==3.8
markdown-it-py==3.0.0
MarkupSafe==3.0.2
matplotlib==3.9.4
matplotlib-inline==0.1.7
mccabe==0.7.0
mdurl==0.1.2
mergedeep==1.3.4
mike==2.2.0
mistune==3.2.0
mkdocs==1.6.1
mkdocs-autorefs==1.4.4
mkdocs-get-deps==0.2.2
mkdocs-material==9.7.6
mkdocs-material-extensions==1.3.1
mkdocs-mermaid2-plugin==1.2.3
mkdocstrings==1.0.4
mkdocstrings-python==2.0.3
ml_dtypes==0.5.1
msgspec==0.20.0
mypy_extensions==1.1.0
namex==0.0.9
narwhals==2.18.0
nbclient==0.10.4
nbconvert==7.17.1
nbformat==5.10.4
nest-asyncio==1.6.0
networkx==3.4.2
nodeenv==1.9.1
notebook==7.5.5
notebook_shim==0.2.4
numba==0.61.2
numpy==2.0.2
numpyencoder @ git+https://github.com/AFM-SPM/numpyencoder@cd84c7cbb7e59386ed7c0a7e03e03c4134b2b84c
opencv-python==4.12.0.88
openpyxl==3.1.5
opt_einsum==3.4.0
optree==0.15.0
overrides==7.7.0
packaging==25.0
paginate==0.5.7
pandas==2.2.3
pandas_flavor==0.7.0
pandocfilters==1.5.1
parso==0.8.4
pathspec==0.12.1
patsy==1.0.1
pexpect==4.9.0
pillow==11.1.0
pingouin==0.5.5
platformdirs==4.3.8
pluggy==1.6.0
ply==3.11
pprintpp==0.4.0
pre_commit==4.2.0
prometheus_client==0.25.0
prompt_toolkit==3.0.51
protobuf==5.29.4
psutil==5.9.8
psygnal==0.13.0
ptyprocess==0.7.0
pure_eval==0.2.3
pyconify==0.2.1
pycparser==3.0
pydantic==2.12.5
pydantic_core==2.41.5
pyFFTW==0.15.0
pyfiglet==1.0.3
Pygments==2.19.1
pylint==3.3.7
pymdown-extensions==10.21.2
pyparsing==3.2.3
-e git+https://github.com/scholi/pySPM.git@b0f62f6c12c397875805a88c4faa5c9bd8ff5693#egg=pyspm
pytest==8.3.5
pytest-cov==6.1.1
pytest-durations==1.5.2
pytest-github-actions-annotate-failures==0.3.0
pytest-icdiff==0.9
pytest-mpl==0.17.0
pytest-profiling==1.8.1
pytest-regtest==2.3.1
pytest-testmon==2.1.3
pytest-xdist==3.7.0
python-dateutil==2.9.0.post0
python-json-logger==4.1.0
pytz==2025.2
pyupgrade==3.20.0
PyYAML==6.0.2
pyyaml_env_tag==1.1
pyzmq==26.4.0
QtPy==2.4.3
RapidFuzz==3.14.3
referencing==0.37.0
requests==2.32.3
rfc3339-validator==0.1.4
rfc3986-validator==0.1.1
rfc3987-syntax==1.1.0
rich==14.0.0
rpds-py==0.30.0
ruamel.yaml==0.18.10
ruamel.yaml.clib==0.2.12
schema==0.7.7
scikit-image==0.25.2
scikit-learn==1.6.1
scipy==1.15.3
seaborn==0.13.2
Send2Trash==2.1.0
six==1.17.0
skan==0.12.2
snoop==0.6.0
soupsieve==2.8.3
stack-data==0.6.3
starlette==0.52.1
statsmodels==0.14.5
superqt==0.7.3
syrupy==5.1.0
tabulate==0.9.0
tensorboard==2.19.0
tensorboard-data-server==0.7.2
tensorflow==2.19.0
tensorflow-io-gcs-filesystem==0.37.1
termcolor==3.1.0
terminado==0.18.1
threadpoolctl==3.6.0
tifffile==2025.5.21
tinycss2==1.4.0
tokenize_rt==6.2.0
tomlkit==0.13.2
toolz==1.0.0
topoly==1.1.0
-e git+ssh://git@github.com/AFM-SPM/TopoStats.git@9158227663427669d075fdaf5bf55ba07d9506ec#egg=topostats
tornado==6.5.1
tqdm==4.67.1
traitlets==5.14.3
ty==0.0.32
typing-inspection==0.4.2
typing_extensions==4.15.0
tzdata==2025.2
uri-template==1.3.0
urllib3==2.4.0
uvicorn==0.42.0
verspec==0.1.0
virtualenv==20.31.2
watchdog==6.0.0
wcwidth==0.2.13
webcolors==25.10.0
webencodings==0.5.1
websocket-client==1.9.0
websockets==16.0
Werkzeug==3.1.3
widgetsnbextension==4.0.15
wrapt==1.17.2
xarray==2025.8.0

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions