DISCO: Disentangling Signal Restoration and Corruption Identification via Sample-Wise Latent Low-Rank Similarity
Supplemental Material
Description of Software and Data
The code and data in the zip file referenced above are a snapshot of the software and data that were used in the research reported in the paper "DISCO: Disentangling Signal Restoration and Corruption Identification via Sample-Wise Latent Low-Rank Similarity" by Yifeng Wang, Shancong Mou, Jianjun Shi, and Chuck Zhang. This repository is also available via Github.
The goal of this repository is to replicate the numerical experiments in the paper.
Computer and Software Environment
The following describes the computer hardware conditions and software environment on which the authors produce the results reported in the paper:
The results reported in the paper were produced using PyTorch 2.0.1 (CUDA 11.8 build) in Python 3.10.6 on Windows 11 (64-bit), running on an NVIDIA GeForce RTX 3060 Laptop GPU (6 GB, compute capability 8.6; CUDA 11.8, cuDNN 8.7) and an AMD Ryzen 9 5900HS with Radeon Graphics (3.30 GHz).
Dependencies
The code in this repository requires the following dependencies. The dependency version number corresponds to the version of the package with which the code was tested.
The code was tested with Python 3.10.6, torch 2.0.1+cu118, torchvision 0.15.2+cu118, numpy 1.26.4, scipy 1.11.4, scikit-learn 1.3.2, scikit-image 0.25.0, opencv-python 4.8.0, matplotlib 3.8.2, Pillow 11.1.0, pandas 1.5.1, and tqdm 4.66.1.
Installation
File Structure:
Codes/
├── models.py network definitions
├── utlis.py dataset loader, ADMM operators, RPCA, metrics
├── train_RobMemAE.py DISCO training (ADMM decomposition X = L + S + E)
├── test_RobMemAE.py evaluation: Dice, DMS-PSNR/SSIM
├── roc_pixelevel.py threshold-free evaluation: pixel-level AUROC / AUPRC
├── train_rdae.py, test_rdae.py RDAE bottleneck-variant baseline (training / evaluation)
├── simulation_data.py generates the simulated contaminated datasets
├── check_rank.py, plot_*.py latent-rank analysis & figure scripts
│
├── DRAEM/ DRÆM baseline (Zavrtanik et al., ICCV 2021; MIT ©
│ VitjanZ)
│
├── data/ INPUT DATA
│ ├── BTech_Dataset_Transformed/ BTAD images for case study
│ └── btad_simulation/ simulated data, one folder per contamination level;
│ each category has train/{good, defect,
│ defect_background, defect_ground_truth}/
│
└── temp_var/ trained weights + decomposition tensors (L/S/E/Y) per category —
the artifacts the evaluation loads (the epoch is chosen in the
model_para dict inside the eval scripts); pretrained_weight/ holds
the autoencoder pretraining checkpoints
Setup
- Install Python 3.10 (tested on 3.10.6). Optionally create a fresh environment (conda create -n disco python=3.10).
- Install the packages listed under Dependencies. The CUDA-11.8 PyTorch build plus the rest:
- pip install torch==2.0.1+cu118 torchvision==0.15.2+cu118 --extra-index-url https://download.pytorch.org/whl/cu118
- pip install numpy scipy scikit-learn scikit-image opencv-python matplotlib pillow tqdm
- Data File: temp_var\DMS5.xlsx
- Code File:
plot_dms.py - Output: The DMS₅-PSNR and DMS₅-SSIM curves of Figure 2(b) and (c) (8 methods each)
- Run Time at the Above-Specified Computer Conditions: ~seconds
- Data File: data\btad_simulation\02_sim_contam_level_0.02 (sim1/2/3) + trained variants in temp_var\rdae_bottleneck_variants\
- Code File:
test_rdae.py - Output: Per-variant Dice + DMS-PSNR/SSIM (CSV: summary_*, *_sim_combined.csv); comparison selects 5×5 (s234)
- Run Time at the Above-Specified Computer Conditions: ~1–2 minutes
- Data File: same variant artifacts in temp_var\rdae_bottleneck_variants\
- Code File:
roc_pixelevel.py (eval_rdae_variants=True) - Output: AUROC/AUPRC for all 5 bottlenecks + combined → roc_pixelevel_results_rdae.txt
- Run Time at the Above-Specified Computer Conditions: ~1–2 minutes
- Data File: data\btad_simulation\02_sim_contam_level_0.02 (02_sim1 training set) + disco & disco-wo-p weights in temp_var\02_sim1\
- Code File:
check_rank.py (category='02_sim1') - Output: (a) SV spectrum of P + (b) effective-rank histogram → rank_compare_02_sim1_disco_vs_disco-wo-p_trained.png
- Run Time at the Above-Specified Computer Conditions: ~1 minute
- Data File: rdae_s234 variant in temp_var\rdae_bottleneck_variants\02_sim1|02_sim2|02_sim3\
- Code File:
roc_pixelevel.py (eval_rdae_variants=True) - Output: rdae_s234 AUROC/AUPRC per sim + combined → roc_pixelevel_results_rdae.txt
- Run Time at the Above-Specified Computer Conditions: ~1–2 minutes
- Data File: rdae_s234 variant in temp_var\rdae_bottleneck_variants\02_sim1|02_sim2|02_sim3\
- Code File:
roc_pixelevel.py (eval_rdae_variants=True) - Output: rdae_s234 AUROC/AUPRC per sim + combined → roc_pixelevel_results_rdae.txt
- Run Time at the Above-Specified Computer Conditions: ~1–2 minutes
- Data File: data\btad_simulation\02_sim_contam_level_0.02 (the sim category holding the chosen blob/line sample) + decomposition tensors in temp_var\<sim>\
- Code File:
test_RobMemAE.py (whether_plot=True, whether_just_result=False; set model_running + category) - Output: Per-method, per-sample panels via plot_result (input X, restored L, detected S mask) → hand-assembled into Figure 4
- Run Time at the Above-Specified Computer Conditions: ~seconds per sample
- Data File: rdae_s234 variant in temp_var\rdae_bottleneck_variants\<sim>\
- Code File:
test_rdae.py (whether_plot=True, strides=(2,3,4) - Output: RDAE panels via plot_result (same layout)
- Run Time at the Above-Specified Computer Conditions: ~seconds per sample
- Data File: data\btad_simulation\02_sim_contam_level_0.02 (sim1/2/3) + decomposition tensors in temp_var\02_sim1|02_sim2|02_sim3\
- Code File:
test_RobMemAE.py (whether_plot=True, whether_just_result=False; set model_running + category per run) - Output: Per-sample Dice + blob/line group means + DMS₂₀-PSNR/SSIM per sim (printed); pooled across sim1/2/3 → the table values
- Run Time at the Above-Specified Computer Conditions: ~2–3 minutes
- Data File: rdae_s234 variant in temp_var\rdae_bottleneck_variants\02_sim1|02_sim2|02_sim3\
- Code File:
test_rdae.py (strides=(2,3,4); run per sim) - Output: Blob/Line/Overall Dice + DMS₂₀-PSNR/SSIM → summary_* / rdae_s234_sim_combined_summary.csv
- Run Time at the Above-Specified Computer Conditions: ~1 minute
- Data File:Values are inline in the script; originally computed on data\btad_simulation\02_sim_contam_level_0.02|_0.05|_0.08|_0.1
- Code File:
plot_sensitivity.py - Output: Figure 5 (2×3 panel) → temp_var\sensitivity_combined.png
- Run Time at the Above-Specified Computer Conditions: ~seconds
- Data File:2%: data\btad_simulation\02_sim_contam_level_0.02 (sim1/2/3)5/8/10%: ..._0.05|_0.08|_0.1 + tensors in temp_var\&alt;category&glt;\
- Code File:
roc_pixelevel.py2% col: eval_contam_levels=False; 5/8/10% cols: eval_contam_levels=True (both eval_rdae_variants=False) - Output: AUROC/AUPRC per anomaly ratio → temp_var\roc_pixelevel_results.txt
- Run Time at the Above-Specified Computer Conditions: ~2–3 minutes
- Data File:rdae_s234 in temp_var\rdae_bottleneck_variants\ (sim1/2/3 for 2%; contam _0.05/_0.08/_0.1 for 5/8/10%)\
- Code File:
roc_pixelevel.py with eval_rdae_variants=True 2%: eval_contam_levels=False; 5/8/10%: eval_contam_levels=True - Output: rdae_s234 AUROC/AUPRC per anomaly ratio → roc_pixelevel_results_rdae.txt
- Run Time at the Above-Specified Computer Conditions: ~1–2 minutes
- Data File:2%: data\btad_simulation\02_sim_contam_level_0.02 (sim1/2/3) 5/8/10%: ..._0.05|_0.08|_0.1 + tensors in temp_var\&alt;category&glt;\
- Code File:
test_RobMemAE.py (whether_plot=True; set model_running + category per contam level) - Output: Overall Dice, DMS₂₀-PSNR, DMS₂₀-SSIM (mean±std) per anomaly ratio
- Run Time at the Above-Specified Computer Conditions: ~1–2 minutes
- Data File: rdae_s234 in temp_var\rdae_bottleneck_variants\ (sim1/2/3 for 2%; contam _0.05/_0.08/_0.1 for 5/8/10%)
- Code File:
test_rdae.py (strides=(2,3,4); run per contam level) - Output: Overall Dice, DMS₂₀-PSNR, DMS₂₀-SSIM → summary_* CSVs
- Run Time at the Above-Specified Computer Conditions: ~1 minute
- Data File: data\BTech_Dataset_Transformed (BTAD3_sys training set) + disco & disco-wo-p weights in temp_var\BTAD3_sys\
- Code File:
check_rank.py (category='BTAD3_sys') - Output: (a) SV spectrum of P + (b) effective-rank histogram → rank_compare_BTAD3_sys_disco_vs_disco-wo-p_trained.png
- Run Time at the Above-Specified Computer Conditions: ~1 minute
- Data File: data\BTech_Dataset_Transformed (BTAD3_sys) + decomposition tensors in temp_var\BTAD3_sys\
- Code File:
roc_pixelevel.py (eval_contam_levels=False, eval_rdae_variants=False) - Output: BTAD3_sys AUROC/AUPRC → temp_var\roc_pixelevel_results.txt
- Run Time at the Above-Specified Computer Conditions: ~2–3 minutes
- Data File: rdae_s234 in temp_var\rdae_bottleneck_variants\BTAD3_sys\
- Code File:
roc_pixelevel.py (eval_rdae_variants=True, eval_contam_levels=False) - Output: rdae_s234 BTAD3_sys AUROC/AUPRC → roc_pixelevel_results_rdae.txt
- Run Time at the Above-Specified Computer Conditions: ~1–2 minutes
- Data File: data\BTech_Dataset_Transformed (BTAD3_sys) + decomposition tensors in temp_var\BTAD3_sys\
- Code File:
test_RobMemAE.py (whether_plot=True, whether_just_result=False; category='BTAD3_sys', set model_running per method) - Output: Per-method, per-sample panels via plot_result (input X, restored L, detected S mask) → hand-assembled into Figure 7
- Run Time at the Above-Specified Computer Conditions: ~seconds per sample
- Data File: rdae_s234 in temp_var\rdae_bottleneck_variants\BTAD3_sys\
- Code File:
test_rdae.py (whether_plot=True, strides=(2,3,4), category='BTAD3_sys') - Output: RDAE panels via plot_result (same layout)
- Run Time at the Above-Specified Computer Conditions: ~seconds per sample
- Data File: data\BTech_Dataset_Transformed (BTAD3_sys) + decomposition tensors in temp_var\BTAD3_sys\
- Code File:
test_RobMemAE.py (whether_plot=True, whether_just_result=False; category='BTAD3_sys', set model_running per method) - Output: Per-defect-type Dice + Overall Dice
- Run Time at the Above-Specified Computer Conditions: ~2–3 minutes
- Data File: rdae_s234 in temp_var\rdae_bottleneck_variants\BTAD3_sys\
- Code File:
test_rdae.py (strides=(2,3,4), category='BTAD3_sys') - Output: Per-type Dice + Overall → summary_BTAD3_sys_rdae_s234_*.csv
- Run Time at the Above-Specified Computer Conditions: ~1 minute
- Data File: data\btad_simulation\02_sim_contam_level_0.02 + decomposition tensors in temp_var\&alt;sim&glt;\
- Code File:
test_RobMemAE.py (whether_plot=True, whether_just_result=False; set model_running + category) - Output: Per-method, per-sample panels via plot_result (input X, restored L, detected S mask) → hand-assembled into Figure 8
- Run Time at the Above-Specified Computer Conditions: ~seconds per sample
- Data File: data\btad_simulation\02_sim_contam_level_0.02 (sim1/2/3) + decomposition tensors in temp_var\02_sim1|02_sim2|02_sim3\
- Code File:
test_RobMemAE.py (whether_plot=True, whether_just_result=False; set model_running + category per run) - Output: Per-sample Dice + blob/line group means + DMS₂₀-PSNR/SSIM per sim (printed); pooled across sim1/2/3 → the table values
- Run Time at the Above-Specified Computer Conditions: ~2–3 minutes
- Data File: data\BTech_Dataset_Transformed (BTAD3_sys) + decomposition tensors in temp_var\BTAD3_sys\
- Code File:
test_RobMemAE.py (whether_plot=True, whether_just_result=False; category='BTAD3_sys', set model_running per method) - Output: Per-method, per-sample panels via plot_result (input X, restored L, detected S mask) → hand-assembled into Figure 9
- Run Time at the Above-Specified Computer Conditions: ~seconds per sample
- Data File: data\BTech_Dataset_Transformed (BTAD3_sys) + decomposition tensors in temp_var\BTAD3_sys\
- Code File:
test_RobMemAE.py (whether_plot=True, whether_just_result=False; category='BTAD3_sys', set model_running per method) - Output: Per-defect-type Dice + Overall Dice
- Run Time at the Above-Specified Computer Conditions: ~2–3 minutes
- Data File: DRAEM/datasets/data/
/ (training images) + DRAEM/datasets/dtd/ (DTD textures, i.e., anomaly source for training); hosted externally - Code File:
DRAEM/train_DRAEM.py (train per category, 500 epochs) → DRAEM/test_DRAEM.py (save_train_S) - Output: test_DRAEM.py computes results in Tables 2, 4, 5, 7 and Figures 4, 7 directly; it also exports temp_var/
/S_ _draem.pt, which roc_pixelevel.py loads for results in Tables 1, 3, 6 - Run Time at the Above-Specified Computer Conditions: ~1–3 h/category for training, ~seconds for anomaly map generation
- In all benchmark tables and figures, the RDAE results are from the best bottleneck variant (s234, 5×5 latent), reproduced via test_rdae.py / roc_pixelevel.py with eval_rdae_variants=True rather than the generic rdae output of the main scripts.
- Several results share a single execution: the threshold-dependent metrics (Tables 2, 4, 5, 7, 8, 9) are produced by test_RobMemAE.py / test_rdae.py, which output Dice and DMS₂₀-PSNR / SSIM together; the threshold-free metrics (Tables 1, 3, 6) come from roc_pixelevel.py; and Figure 5 plots the same values as Tables 3–5.
- The 2%-anomaly-ratio column of the sensitivity Tables 3, 4, 5 equals the simulation-study values in Tables 1 and 2.
- The DRÆM baseline is trained and evaluated entirely in the DRAEM/ subfolder (train_DRAEM.py → test_DRAEM.py). test_DRAEM.py computes DRÆM's Dice and DMS₂₀-PSNR / SSIM (Tables 2, 4, 5, 7) and its qualitative panels (Figures 4, 7) directly; it also exports temp_var/
/S_ _draem.pt, which roc_pixelevel.py loads to compute DRÆM's threshold-free metrics (Tables 1, 3, 6). test_RobMemAE.py does not evaluate DRÆM. - All DISCO scripts are configured by editing variables at the top (dataset / category / model_running); the DRÆM scripts instead take command-line arguments (see DRAEM/command.txt).
No build/compilation step is required. To run, set the dataset/category/model at the top of the relevant script and execute it, e.g., python train_RobMemAE.py (for training) and python test_RobMemAE.py / python roc_pixelevel.py (for evaluation).
Reproducibility Workflow
To reproduce the results in Figure 2(b), (c)
To reproduce the results in RDAE bottleneck-structure choice in Section 4.4 — Dice / DMS (main criterion)
To reproduce the results in RDAE bottleneck-structure choice in Section 4.4 — pixel-level AUROC/AUPRC
To reproduce the results in Figure 3
To reproduce the results in Table 1 (RPCA, MemAE, DISCO rows)
To reproduce the results in Table 1 (RDAE row, s234 variant)
To reproduce the results in Figure 4 (RPCA, MemAE, DISCO columns)(RDAE row, s234 variant)
To reproduce the results in Figure 4 (RDAE column, s234 variant)
To reproduce the results in Table 2 (RPCA, MemAE, DISCO rows)
To reproduce the results in Table 2 (RDAE row, s234 variant)
To reproduce the results in Figure 5
To reproduce the results in Table 3 (RPCA, MemAE, DISCO rows)
To reproduce the results in Table 3 (RDAE row, s234 variant)
To reproduce the results in Tables 4 & 5 (RPCA, MemAE, DISCO rows)
To reproduce the results in Tables 4 & 5 (RDAE row, s234 variant)
To reproduce the results in Figure 6
To reproduce the results in Table 6 (RPCA, MemAE, DISCO rows)
To reproduce the results in Table 6 (RDAE row, s234 variant)
To reproduce the results in Figure 7 (RPCA, MemAE, DISCO columns)
To reproduce the results in Figure 7 (RDAE column, s234 variant)
To reproduce the results in Table 7 (RPCA, MemAE, DISCO rows)
To reproduce the results in Table 7 (RDAE row, s234 variant)
To reproduce the results in Figure 8
To reproduce the results in Table 8
To reproduce the results in Figure 9
To reproduce the results in Table 9
To reproduce the results in DRÆM baseline (all DRÆM rows/columns in Tables 1, 2, 3, 4, 5, 6, 7 & Figures 4, 7)
Notes
Cite
To cite the contents of this repository, please cite both the paper and this repository using their respective DOIs.
Article: https://doi.org/10.1287/ijds.2026.0150
Software and Data Repository: https://doi.org/10.1287/ijds.2026.0150.cd
License
Copyright (c) (2026 Wang, Mou, Shi, Zhang)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

