name: General Issue and suggested Fix
about: Report bugs, request features, or ask questions
title: ''
labels: ''
assignees: ''
Issue Type
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.
name: General Issue and suggested Fix
about: Report bugs, request features, or ask questions
title: ''
labels: ''
assignees: ''
Issue Type
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:
where
The reported attenuation estimate is:
Final form of the estimator:
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:
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:
To convert to centimeters per sample:
For example, if the imaging depth is 99.7 mm and there are 1952 samples per line as per our example:
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.