Skip to content

QUS Bug Report: Incorrect attenuation coefficient quantification & suggested fix on Clarius RF #55

Description

@j1weeks

name: General Issue and suggested Fix
about: Report bugs, request features, or ask questions
title: ''
labels: ''
assignees: ''

Issue Type

  • Bug Report
  • Feature Request
  • Installation Issue
  • Question/Help
  • Documentation
  • Other

Description

The current quantitative results for the attenuation coefficient on the Clarius system produce a very narrow range of values which are tightly clustered around the user-provided reference attenuation value. The source of the issue is an incorrect calculation of the axial depth, which flattens the slope $$p_0$$ in the following lines, located in qus/quantus/analysis/paramap/analysis_methods/attenuation_coef.py:

local_attenuation = ref_attenuation * f[f_idx] - (1 / 4) * p[0]
attenuation_coefficients.append(local_attenuation / f[f_idx])

The first line is equivalent to:

$$\mathrm{local_attenuation}(f)=\alpha_{\mathrm{ref}} f-\frac{1}{4} p_0$$

where

  • $\alpha_{\text{ref}}$ is the reference attenuation (dB/cm/MHz)
  • $f$ is the frequency (MHz)
  • $p_0$ is the slope of the linear regression of spectral difference vs. depth

The reported attenuation estimate is:

$$\hat{\alpha}(f)=\alpha_{\text{ref}}-\frac{p_0}{4 f}$$

Final form of the estimator:

$$\hat{\alpha}(f)=\alpha_{\text{ref}}-\frac{p_0}{4 f}$$

In short, the actual estimator is just the user-provided reference attenuation value minus a correction term. This is broadly the same as the approach of Han et al. (https://doi.org/10.1002/jum.14537). Since f is fixed, the issue must be that $p_0$ is artificially small due to some issue earlier in the code.

Since $p_0$ is the slope of the log spectral difference versus depth, if the slope is small, the correction term will be even smaller. Therefore the estimate naturally collapses to the reference attenuation value.

Suggested Fix

In line 62 of attenuation_coef.py, the following line begins the scaling of the window depths:

# Convert window depths to cm
axial_res_cm = image_data.axial_res / 10

On the real Clarius C3 data, we find that image_data.axial_res = 1.994. But this is not a useful value for the remainder of the computation. If we examine the .yml file for the RF data, we find the following:

imaging depth: 99.70 mm
size: {samples per line: 1952,number of lines: 192,sample size: 2 bytes}

The axial spacing per RF sample, (dz), can be computed from the imaging depth and number of samples per line as:

$$ dz = \frac{\text{imaging depth (mm)}}{\text{samples per line}} $$

To convert to centimeters per sample:

$$ dz_\text{cm} = \frac{dz}{10} = \frac{\text{imaging depth (mm)}}{\text{samples per line} \times 10} $$

For example, if the imaging depth is 99.7 mm and there are 1952 samples per line as per our example:

$$ dz_\text{cm} = \frac{99.7}{1952 \times 10} \approx 0.00511 \text{ cm/sample} $$

Which is much smaller than the 0.1994 suggested by the current calculation. The current implementation is therefore inflating the RF_data_size by ~39x, resulting in an artifactually low slope.

The attenuation_coef function should use the .yml header data to determine the true resolution rather than using the image_data.axial_res, which is likely vestigial from some other metadata format. This will also be robust to changes in resolution due to different probes or presets.

I tested this fix locally; with hard-coded corrections to the resolution, a much more realistic range of values is achieved.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Fields

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