.. _faq:

==========================
Frequently Asked Questions
==========================

This page addresses common questions, issues, and best practices when using MedTDA.

.. contents:: Contents
   :local:
   :depth: 2

Installation and Setup
======================

How do I install MedTDA?
------------------------

**Basic installation:**

.. code-block:: bash

    pip install medtda

**From source:**

.. code-block:: bash

    git clone https://github.com/dashtiali/medtda.git
    cd medtda
    pip install -e .

**With optional dependencies:**

.. code-block:: bash

    pip install medtda[visualization,notebook]

See :doc:`installation` for detailed instructions.

What are the system requirements?
----------------------------------

**Minimum:**

- Python 3.8+
- 4 GB RAM
- NumPy, SciPy

**Recommended:**

- Python 3.9+
- 16 GB RAM
- GUDHI, scikit-learn
- GPU (for large-scale processing)

Can I use MedTDA on Windows/Mac/Linux?
---------------------------------------

Yes! MedTDA is cross-platform and works on:

- **Windows** 10/11
- **macOS** 10.14+
- **Linux** (Ubuntu 18.04+, CentOS 7+, etc.)

Installation is the same on all platforms via pip.

Dependencies won't install - what should I do?
-----------------------------------------------

**Common solutions:**

1. **Update pip:**

   .. code-block:: bash

       pip install --upgrade pip

2. **Use conda for difficult packages:**

   .. code-block:: bash

       conda install -c conda-forge gudhi numpy scipy

3. **Check Python version:**

   .. code-block:: bash

       python --version  # Should be 3.8+

4. **Install build tools** (if compiling from source):

   - **Linux:** ``sudo apt-get install build-essential``
   - **macOS:** ``xcode-select --install``
   - **Windows:** Install Visual Studio Build Tools

Getting Started
===============

Where should I start?
---------------------

1. Read the :doc:`quickstart` (5-minute introduction)
2. Try the :doc:`tutorials/notebook` (interactive tutorial)
3. Explore :doc:`examples/basic_usage` (practical examples)
4. Consult :doc:`user_guide` for in-depth coverage

What file formats are supported?
---------------------------------

**3D Medical Images:**

- NIFTI (``.nii``, ``.nii.gz``) ✓ Recommended
- DICOM (``.dcm``) ✓
- NRRD (``.nrrd``, ``.nhdr``) ✓
- Analyze (``.hdr/.img``) ✓

**2D Images:**

- PNG (``.png``) ✓
- TIFF (``.tiff``, ``.tif``) ✓
- JPEG (``.jpg``, ``.jpeg``) ✓

**Arrays:**

- NumPy arrays (directly in Python) ✓

See :doc:`api/loaders` for loading different formats.

Can I use 2D images?
--------------------

Yes! MedTDA works with any dimensionality:

- **2D images:** H0 (connected components) and H1 (loops)
- **3D images:** H0, H1, and H2 (voids)

For 2D, set ``max_dimension=1``:

.. code-block:: python

    from medtda import FeatureExtractor
    
    extractor = FeatureExtractor(max_dimension=1)
    features = extractor.execute('2d_image.png')

Common Errors and Solutions
============================

ValueError: Image and mask shapes don't match
----------------------------------------------

**Problem:** Image and mask have different dimensions.

**Solution:**

1. **Check shapes:**

   .. code-block:: python

       from medtda.loaders import load_image, load_mask
       
       image, _ = load_image('image.nii.gz')
       mask, _ = load_mask('mask.nii.gz')
       
       print(f"Image: {image.shape}")
       print(f"Mask: {mask.shape}")

2. **Resample mask to match image:**

   .. code-block:: python

       from medtda.utils import resample_mask
       
       mask_resampled = resample_mask(mask, image.shape)

3. **Verify loading:**

   .. code-block:: python

       from medtda.loaders import validate_compatibility
       
       validate_compatibility(image, mask)

MemoryError: Unable to allocate array
--------------------------------------

**Problem:** Image too large for available RAM.

**Solutions:**

1. **Downsample the image:**

   .. code-block:: python

       extractor = FeatureExtractor(
           spacing=(2.0, 2.0, 2.0)  # Halve resolution each axis
       )

2. **Crop to ROI:**

   .. code-block:: python

       extractor = FeatureExtractor(
           crop_to_roi=True,
           roi_padding=5
       )

3. **Process 2D slices instead of 3D volume**

4. **Use a machine with more RAM**

Empty barcodes / No features detected
--------------------------------------

**Problem:** Persistent homology returns no features.

**Possible causes:**

1. **ROI too small or homogeneous:**

   .. code-block:: python

       # Check ROI size
       import numpy as np
       roi_voxels = np.sum(mask > 0)
       print(f"ROI voxels: {roi_voxels}")

2. **Wrong filtration type:**

   .. code-block:: python

       # Try both sublevel and superlevel
       extractor_sub = FeatureExtractor(filtration_type='sublevel')
       extractor_sup = FeatureExtractor(filtration_type='superlevel')

3. **Need normalization:**

   .. code-block:: python

       extractor = FeatureExtractor(normalize=True)

RuntimeError: GUDHI failed to compute
--------------------------------------

**Problem:** Underlying GUDHI library error.

**Solutions:**

1. **Check image values:**

   .. code-block:: python

       import numpy as np
       
       # Check for NaN/Inf
       if np.isnan(image).any():
           image = np.nan_to_num(image, nan=0.0)
       
       if np.isinf(image).any():
           image = np.nan_to_num(image, posinf=0.0, neginf=0.0)

2. **Normalize first:**

   .. code-block:: python

       extractor = FeatureExtractor(
           normalize=True,
           normalize_method='robust'
       )

3. **Reduce max_dimension:**

   .. code-block:: python

       extractor = FeatureExtractor(max_dimension=1)  # Skip H2

Feature Extraction Questions
=============================

Which vectorization method should I use?
-----------------------------------------

**Quick guide:**

- **Need interpretable features?** → ``PersStats``
- **For machine learning?** → ``PersImage``
- **Want to see evolution over scale?** → ``BettiCurve``
- **Statistical analysis?** → ``PersLandscape``
- **Single complexity measure?** → ``EntropySummary``

How do I choose between sublevel and superlevel?
-------------------------------------------------

**Sublevel filtration** (default):

- Grows components from **low** to **high** intensities
- Good for **dark features** (e.g., vessels in angiography, cells in microscopy)
- Most common choice

**Superlevel filtration:**

- Grows components from **high** to **low** intensities
- Good for **bright features** (e.g., lesions in T2 MRI, enhancing tumors)

**Try both** and visualize to decide:

.. code-block:: python

    from medtda import FeatureExtractor
    
    # Sublevel
    extractor_sub = FeatureExtractor(filtration_type='sublevel')
    features_sub, barcodes_sub = extractor_sub.execute(image, return_barcodes=True)
    
    # Superlevel
    extractor_sup = FeatureExtractor(filtration_type='superlevel')
    features_sup, barcodes_sup = extractor_sup.execute(image, return_barcodes=True)
    
    # Compare number of features
    print(f"Sublevel: {len(barcodes_sub[1])} H1 features")
    print(f"Superlevel: {len(barcodes_sup[1])} H1 features")

What dimensions should I compute (H0, H1, H2)?
-----------------------------------------------

**Homology dimensions:**

- **H0** (dimension 0): Connected components
  
  - Always present
  - Counts separate objects/regions
  
- **H1** (dimension 1): Loops/holes
  
  - Cavities, vessels, circular structures
  - Most informative for many applications
  
- **H2** (dimension 2): Voids/cavities
  
  - Only for 3D images
  - Computationally expensive
  - Often less informative than H0/H1

**Recommendations:**

- **2D images:** ``max_dimension=1`` (H0, H1)
- **3D exploratory analysis:** ``max_dimension=1`` (faster)
- **3D detailed analysis:** ``max_dimension=2`` (complete)

.. code-block:: python

    # Fast: H0 and H1 only
    extractor = FeatureExtractor(max_dimension=1)
    
    # Complete: H0, H1, and H2
    extractor = FeatureExtractor(max_dimension=2)

How many features will I get?
------------------------------

**It depends on the vectorization method:**

.. list-table::
   :header-rows: 1
   :widths: 30 20 50

   * - Method
     - Feature Count
     - Notes
   * - ``PersStats``
     - 13
     - Fixed size
   * - ``BettiCurve``
     - 100 (default)
     - Configurable via ``resolution``
   * - ``PersImage``
     - 400 (20×20)
     - ``resolution²``
   * - ``PersLandscape``
     - 500 (5×100)
     - ``num_landscapes × resolution``
   * - ``EntropySummary``
     - 1
     - Single value per dimension
   * - ``PersSilhouette``
     - 100 (default)
     - Configurable

**Configuring size:**

.. code-block:: python

    extractor = FeatureExtractor(vectorization_method='PersImage')
    
    extractor.set_vectorization_params(
        'PersImage',
        resolution=30  # 30×30 = 900 features
    )

Performance and Optimization
=============================

How long does processing take?
-------------------------------

**Typical times** (256×256×128 image on standard desktop):

- **Preprocessing:** 1-5 seconds
- **Persistent homology:** 5-30 seconds
- **Vectorization:** 0.1-2 seconds

**Total:** ~10-40 seconds per image

**Factors affecting speed:**

- Image size (biggest factor)
- Number of voxels in ROI
- ``max_dimension`` (H2 is slow)
- Vectorization method
- Hardware (CPU, RAM)

How can I speed up processing?
-------------------------------

**Top strategies:**

1. **Downsample images:**

   .. code-block:: python

       extractor = FeatureExtractor(spacing=(2.0, 2.0, 2.0))

2. **Crop to ROI:**

   .. code-block:: python

       extractor = FeatureExtractor(crop_to_roi=True)

3. **Reduce max_dimension:**

   .. code-block:: python

       extractor = FeatureExtractor(max_dimension=1)  # Skip H2

4. **Use faster vectorization:**

   .. code-block:: python

       extractor = FeatureExtractor(
           vectorization_method='PersStats'  # Fastest

5. **Parallel batch processing:**

   .. code-block:: python

       from multiprocessing import Pool
       
       with Pool(processes=8) as pool:
           results = pool.map(process_image, image_paths)

How much RAM do I need?
------------------------

**Estimate:**

- **Small images** (128³): 2-4 GB
- **Medium images** (256³): 8-16 GB
- **Large images** (512³): 32-64 GB

**Reduce memory usage:**

1. Downsample with ``spacing``
2. Crop with ``crop_to_roi=True``
3. Process one image at a time
4. Use ``max_dimension=1``

Can I use GPU acceleration?
----------------------------

Currently, MedTDA uses CPU-based libraries (GUDHI, NumPy). GPU acceleration is not yet supported but is planned for future releases.

For batch processing, **CPU multiprocessing** provides good parallelization:

.. code-block:: python

    from medtda import FeatureExtractor
    from multiprocessing import Pool
    
    def process(img_path):
        extractor = FeatureExtractor()
        return extractor.execute(img_path)
    
    with Pool(8) as pool:  # 8 parallel processes
        results = pool.map(process, image_paths)

Machine Learning Integration
=============================

How do I integrate features with scikit-learn?
-----------------------------------------------

.. code-block:: python

    from medtda import FeatureExtractor
    from sklearn.ensemble import RandomForestClassifier
    import numpy as np
    
    # Extract features for all samples
    extractor = FeatureExtractor(
        normalize=True,
        vectorization_method='PersImage'
    )
    
    X = []
    for img_path in training_images:
        features = extractor.execute(img_path)
        # features is a flat dict: {'PersImage_H0_f0': ..., 'PersImage_H1_f0': ..., ...}
        X.append(list(features.values()))
    
    X = np.array(X)
    
    # Train
    clf = RandomForestClassifier()
    clf.fit(X, y_train)

See :doc:`examples/batch_workflow` for complete examples.

Should I normalize features?
-----------------------------

**Image normalization:** Yes, always recommended:

.. code-block:: python

    extractor = FeatureExtractor(normalize=True)

**Feature scaling for ML:**

.. code-block:: python

    from sklearn.preprocessing import StandardScaler
    
    scaler = StandardScaler()
    X_train_scaled = scaler.fit_transform(X_train)
    X_test_scaled = scaler.transform(X_test)

How do I do feature selection?
-------------------------------

.. code-block:: python

    from sklearn.feature_selection import SelectKBest, f_classif
    
    # Select top 50 features
    selector = SelectKBest(f_classif, k=50)
    X_train_selected = selector.fit_transform(X_train, y_train)
    X_test_selected = selector.transform(X_test)
    
    # Get selected feature indices
    selected_idx = selector.get_support()

Can I combine multiple vectorization methods?
----------------------------------------------

Yes! This often improves performance:

.. code-block:: python

    from medtda import FeatureExtractor
    import numpy as np
    
    extractor = FeatureExtractor(normalize=True)
    extractor.enable_vectorization_methods([
        'PersStats',
        'BettiCurve',
        'PersImage'
    ])
    
    features = extractor.execute(image)
    
    # features is a flat dict with all method features combined
    # e.g., {'PersStats_H0_mean': ..., 'BettiCurve_H0_f0': ..., 'PersImage_H0_f0': ...}
    combined = np.array(list(features.values()))

Results Interpretation
======================

What do the barcode plots mean?
--------------------------------

**Persistence barcodes** show features as horizontal bars:

- **X-axis:** Filtration value (intensity threshold)
- **Length:** Persistence (how long feature survives)
- **Longer bars** = more significant features
- **Short bars** = noise

**By dimension:**

- **H0 bars:** Connected components merging
- **H1 bars:** Loops appearing and disappearing
- **H2 bars:** Voids filling

See :doc:`theory/barcodes_diagrams` for details.

How do I interpret persistence statistics?
-------------------------------------------

The ``PersStats`` method returns 13 values per dimension:

1. **Count:** Number of features
2. **Mean:** Average persistence
3. **Std:** Standard deviation of persistence
4. **Min:** Smallest persistence
5. **25%:** First quartile
6. **50%:** Median
7. **75%:** Third quartile
8. **Max:** Largest persistence
9-13. **Additional statistics** (skewness, kurtosis, etc.)

**Interpretation:**

- **High count:** Many topological features
- **High mean/max:** Prominent features
- **High std:** Diverse feature scales

What's a "good" persistence value?
-----------------------------------

**It depends on your application!**

- **Absolute values** depend on image intensities and normalization
- **Relative comparisons** are meaningful (within same preprocessing)
- **Statistical significance:** Compare to random/null distribution

**General guidance:**

- Features with persistence < 1% of max are often noise
- Focus on top 10-20% most persistent features
- Domain knowledge helps interpret what's "significant"

Why are my features all similar/different between groups?
----------------------------------------------------------

**All similar (low variance):**

1. Images are actually similar (expected)
2. ROIs too small → extract larger context
3. Wrong filtration type → try both sublevel/superlevel
4. Need different vectorization method

**Too different (high variance):**

1. Preprocessing inconsistent → standardize pipeline
2. Image quality varies → add quality control
3. ROI placement varies → improve segmentation
4. Outliers present → check and remove

Troubleshooting
===============

Code runs but gives unexpected results
---------------------------------------

**Checklist:**

1. ✓ Image loaded correctly?
2. ✓ Mask matches image?
3. ✓ Normalization applied?
4. ✓ Correct filtration type?
5. ✓ ROI not empty?
6. ✓ Preprocessing consistent?

**Debug by visualizing:**

.. code-block:: python

    import matplotlib.pyplot as plt
    from medtda.plotting import plot_persistence_diagram
    
    # Visualize processed image
    plt.imshow(processed[:, :, processed.shape[2]//2], cmap='gray')
    plt.show()
    
    # Plot persistence diagram
    _, barcodes = extractor.execute(image, return_barcodes=True)
    plot_persistence_diagram(barcodes)
    plt.show()

"Module not found" errors
--------------------------

**Problem:** Import fails.

**Solutions:**

1. **Verify installation:**

   .. code-block:: bash

       pip list | grep medtda

2. **Reinstall:**

   .. code-block:: bash

       pip uninstall medtda
       pip install medtda

3. **Check Python environment:**

   .. code-block:: bash

       which python
       which pip

4. **Use correct environment:**

   .. code-block:: bash

       # Activate environment first
       conda activate myenv
       # Then install
       pip install medtda

Processing hangs / takes forever
---------------------------------

**Possible causes:**

1. **Image too large** → downsample or crop
2. **Computing H2 on large image** → use ``max_dimension=1``
3. **Very complex image** → increase ``spacing`` to reduce resolution
4. **Insufficient RAM** → close other programs, use smaller images

**Add timeout:**

.. code-block:: python

    import signal
    
    def timeout_handler(signum, frame):
        raise TimeoutError("Processing took too long")
    
    signal.signal(signal.SIGALRM, timeout_handler)
    signal.alarm(300)  # 5 minute timeout
    
    try:
        features = extractor.execute(image)
    except TimeoutError:
        print("Processing timed out")
    finally:
        signal.alarm(0)

Where to Get Help
=================

I read the FAQ but still have questions
----------------------------------------

1. **Search documentation:** Use search box (top right)
2. **Check examples:** :doc:`examples/index`
3. **GitHub Issues:** `Search existing issues <https://github.com/dashtiali/medtda/issues>`_
4. **Ask a question:** `Open new issue <https://github.com/dashtiali/medtda/issues/new>`_
5. **Discussions:** `GitHub Discussions <https://github.com/dashtiali/medtda/discussions>`_

How do I report a bug?
----------------------

`Open a bug report <https://github.com/dashtiali/medtda/issues/new?template=bug_report.md>`_ with:

1. **MedTDA version:** ``medtda.__version__``
2. **Python version:** ``python --version``
3. **Operating system**
4. **Minimal code to reproduce**
5. **Error message / unexpected output**
6. **Expected behavior**

Can I request a feature?
------------------------

Yes! `Open a feature request <https://github.com/dashtiali/medtda/issues/new?template=feature_request.md>`_ describing:

1. What you want to do
2. Why current functionality doesn't work
3. Proposed solution (if any)
4. Example use case

How can I contribute?
---------------------

See :doc:`contributing` for:

- Code contributions
- Documentation improvements
- Bug reports
- Feature suggestions
- Example notebooks

See Also
========

* :doc:`installation` - Installation guide
* :doc:`quickstart` - Quick start tutorial
* :doc:`user_guide` - Complete user guide
* :doc:`troubleshooting` - Detailed troubleshooting
* :doc:`contributing` - How to contribute
