[ENH]: Rename (f)ALFF markers to be shorter and ALFF prefixed #216

Merged
synchon merged 16 commits from refactor/alff-falff into main 2023-03-30 16:23:55 +00:00
14 changed files with 60 additions and 70 deletions

View file

@ -176,11 +176,11 @@ Available
- Calculate regional homogeneity over spheres placed on coordinates - Calculate regional homogeneity over spheres placed on coordinates
- Done - Done
- 0.0.1 - 0.0.1
* - :class:`junifer.markers.AmplitudeLowFrequencyFluctuationParcels` * - :class:`junifer.markers.ALFFParcels`
- Calculate (f)ALFF and aggregate using parcellations - Calculate (f)ALFF and aggregate using parcellations
- Done - Done
- 0.0.1 - 0.0.1
* - :class:`junifer.markers.AmplitudeLowFrequencyFluctuationSpheres` * - :class:`junifer.markers.ALFFSpheres`
- Calculate (f)ALFF and aggregate using spheres placed on coordinates - Calculate (f)ALFF and aggregate using spheres placed on coordinates
- Done - Done
- 0.0.1 - 0.0.1
@ -541,13 +541,13 @@ Available
* - Nilearn's MNI152 1mm-resolution mask * - Nilearn's MNI152 1mm-resolution mask
- | ``compute_brain_mask`` - | ``compute_brain_mask``
- 0.0.2 - 0.0.2
- | Compute the whole-brain mask. This mask is calculated using MNI152 1mm-resolution template mask onto the - | Compute the whole-brain mask. This mask is calculated using MNI152 1mm-resolution template mask onto the
| target image. See :func:`nilearn.masking.compute_brain_mask` | target image. See :func:`nilearn.masking.compute_brain_mask`
* - Nilearn's mask computed from FMRI data * - Nilearn's mask computed from FMRI data
- | ``compute_epi_mask`` - | ``compute_epi_mask``
- 0.0.2 - 0.0.2
- | Compute a brain mask from fMRI data. This is based on an heuristic proposed by T.Nichols: find the least - | Compute a brain mask from fMRI data. This is based on an heuristic proposed by T.Nichols: find the least
| dense point of the histogram, between fractions ``lower_cutoff`` and ``upper_cutoff`` of the total image | dense point of the histogram, between fractions ``lower_cutoff`` and ``upper_cutoff`` of the total image
| histogram. See :func:`nilearn.masking.compute_epi_mask` | histogram. See :func:`nilearn.masking.compute_epi_mask`
* - Nilearn's background mask * - Nilearn's background mask
- | ``compute_background_mask`` - | ``compute_background_mask``

View file

@ -1 +1 @@
Fix :class:`junifer.markers.AmplitudeLowFrequencyFluctuationParcels`, :class:`junifer.markers.AmplitudeLowFrequencyFluctuationSpheres`, :class:`junifer.markers.ReHoSpheres` and :class:`junifer.markers.ReHoParcels` pass the ``extra_input`` parameter by `Fede Raimondo`_ Fix :class:`junifer.markers.ALFFParcels`, :class:`junifer.markers.ALFFSpheres`, :class:`junifer.markers.ReHoSpheres` and :class:`junifer.markers.ReHoParcels` pass the ``extra_input`` parameter by `Fede Raimondo`_

View file

@ -0,0 +1 @@
``AmplitudeLowFrequencyFluctuationParcels`` and ``AmplitudeLowFrequencyFluctuationSpheres`` are renamed to :class:`junifer.markers.ALFFParcels` and :class:`junifer.markers.ALFFSpheres` by `Synchon Mandal`_

View file

@ -150,9 +150,8 @@ Features
- Implement :class:`junifer.markers.ReHoParcels` and - Implement :class:`junifer.markers.ReHoParcels` and
fraimondo commented 2023-03-30 14:56:29 +00:00 (Migrated from github.com)

I would change this fragemtn to the right object: .ALFFParcels and .ALFFSphere

I would change this fragemtn to the right object: `.ALFFParcels` and `.ALFFSphere`
:class:`junifer.markers.ReHoSpheres` markers by `Synchon Mandal`_ (:gh:`36`) :class:`junifer.markers.ReHoSpheres` markers by `Synchon Mandal`_ (:gh:`36`)
- Implement :class:`junifer.markers.AmplitudeLowFrequencyFluctuationParcels` and - Implement :class:`junifer.markers.ALFFParcels` and
:class:`junifer.markers.AmplitudeLowFrequencyFluctuationSpheres` markers by :class:`junifer.markers.ALFFSpheres` markers by `Fede Raimondo`_ (:gh:`35`)
`Fede Raimondo`_ (:gh:`35`)
Misc Misc
^^^^ ^^^^

View file

@ -18,10 +18,7 @@ from .functional_connectivity import (
EdgeCentricFCSpheres, EdgeCentricFCSpheres,
) )
from .reho import ReHoParcels, ReHoSpheres from .reho import ReHoParcels, ReHoSpheres
from .falff import ( from .falff import ALFFParcels, ALFFSpheres
AmplitudeLowFrequencyFluctuationParcels,
AmplitudeLowFrequencyFluctuationSpheres,
)
from .temporal_snr import ( from .temporal_snr import (
TemporalSNRParcels, TemporalSNRParcels,
TemporalSNRSpheres, TemporalSNRSpheres,

View file

@ -3,5 +3,5 @@
# Authors: Federico Raimondo <f.raimondo@fz-juelich.de> # Authors: Federico Raimondo <f.raimondo@fz-juelich.de>
# License: AGPL # License: AGPL
from .falff_parcels import AmplitudeLowFrequencyFluctuationParcels from .falff_parcels import ALFFParcels
from .falff_spheres import AmplitudeLowFrequencyFluctuationSpheres from .falff_spheres import ALFFSpheres

View file

@ -10,10 +10,10 @@ from typing import Dict, List, Optional
from ...utils.logging import raise_error from ...utils.logging import raise_error
from ..base import BaseMarker from ..base import BaseMarker
from .falff_estimator import AmplitudeLowFrequencyFluctuationEstimator from .falff_estimator import ALFFEstimator
class AmplitudeLowFrequencyFluctuationBase(BaseMarker): class ALFFBase(BaseMarker):
"""Base class for (fractional) Amplitude Low Frequency Fluctuation. """Base class for (fractional) Amplitude Low Frequency Fluctuation.
Parameters Parameters
@ -144,7 +144,7 @@ class AmplitudeLowFrequencyFluctuationBase(BaseMarker):
"before calling the `compute` method." "before calling the `compute` method."
) )
estimator = AmplitudeLowFrequencyFluctuationEstimator() estimator = ALFFEstimator()
alff, falff = estimator.fit_transform( alff, falff = estimator.fit_transform(
use_afni=self.use_afni, use_afni=self.use_afni,

View file

@ -26,16 +26,15 @@ if TYPE_CHECKING:
@singleton @singleton
class AmplitudeLowFrequencyFluctuationEstimator: class ALFFEstimator:
"""Estimator class for AmplitudeLowFrequencyFluctuationBase. """Estimator class for (fractional) Amplitude Low Frequency Fluctuation.
This class is a singleton and is used for efficient computation of fALFF, This class is a singleton and is used for efficient computation of fALFF,
by caching the voxel-wise ALFF map for a given set of file path and by caching the voxel-wise ALFF map for a given set of file path and
computation parameters. computation parameters.
.. warning:: This class can only be used via .. warning:: This class can only be used via
:class:`junifer.markers.falff.AmplitudeLowFrequencyFluctuationBase` :class:`junifer.markers.falff.ALFFBase` as it serves a specific purpose.
as it serves a specific purpose.
Parameters Parameters
---------- ----------

View file

@ -9,13 +9,11 @@ from typing import Dict, List, Optional, Union
from ...api.decorators import register_marker from ...api.decorators import register_marker
from .. import ParcelAggregation from .. import ParcelAggregation
from .falff_base import AmplitudeLowFrequencyFluctuationBase from .falff_base import ALFFBase
@register_marker @register_marker
class AmplitudeLowFrequencyFluctuationParcels( class ALFFParcels(ALFFBase):
AmplitudeLowFrequencyFluctuationBase
):
"""Class for computing fALFF/ALFF on parcels. """Class for computing fALFF/ALFF on parcels.
Parameters Parameters

View file

@ -9,13 +9,11 @@ from typing import Dict, List, Optional, Union
from ...api.decorators import register_marker from ...api.decorators import register_marker
from .. import SphereAggregation from .. import SphereAggregation
from .falff_base import AmplitudeLowFrequencyFluctuationBase from .falff_base import ALFFBase
@register_marker @register_marker
class AmplitudeLowFrequencyFluctuationSpheres( class ALFFSpheres(ALFFBase):
AmplitudeLowFrequencyFluctuationBase
):
"""Class for computing fALFF/ALFF on spheres. """Class for computing fALFF/ALFF on spheres.
Parameters Parameters

View file

@ -10,22 +10,20 @@ from nibabel import Nifti1Image
from scipy.stats import pearsonr from scipy.stats import pearsonr
from junifer.datareader import DefaultDataReader from junifer.datareader import DefaultDataReader
from junifer.markers.falff.falff_estimator import ( from junifer.markers.falff.falff_estimator import ALFFEstimator
AmplitudeLowFrequencyFluctuationEstimator,
)
from junifer.pipeline.utils import _check_afni from junifer.pipeline.utils import _check_afni
from junifer.testing.datagrabbers import PartlyCloudyTestingDataGrabber from junifer.testing.datagrabbers import PartlyCloudyTestingDataGrabber
from junifer.utils import logger from junifer.utils import logger
def test_AmplitudeLowFrequencyFluctuationEstimator_cache_python() -> None: def test_ALFFEstimator_cache_python() -> None:
"""Test that the cache works properly when using python.""" """Test that the cache works properly when using python."""
with PartlyCloudyTestingDataGrabber() as dg: with PartlyCloudyTestingDataGrabber() as dg:
input = dg["sub-01"] input = dg["sub-01"]
input = DefaultDataReader().fit_transform(input) input = DefaultDataReader().fit_transform(input)
estimator = AmplitudeLowFrequencyFluctuationEstimator() estimator = ALFFEstimator()
start_time = time.time() start_time = time.time()
alff, falff = estimator.fit_transform( alff, falff = estimator.fit_transform(
use_afni=False, use_afni=False,
@ -111,14 +109,14 @@ def test_AmplitudeLowFrequencyFluctuationEstimator_cache_python() -> None:
@pytest.mark.skipif( @pytest.mark.skipif(
_check_afni() is False, reason="requires afni to be in PATH" _check_afni() is False, reason="requires afni to be in PATH"
) )
def test_AmplitudeLowFrequencyFluctuationEstimator_cache_afni() -> None: def test_ALFFEstimator_cache_afni() -> None:
"""Test that the cache works properly when using afni.""" """Test that the cache works properly when using afni."""
with PartlyCloudyTestingDataGrabber() as dg: with PartlyCloudyTestingDataGrabber() as dg:
input = dg["sub-01"] input = dg["sub-01"]
input = DefaultDataReader().fit_transform(input) input = DefaultDataReader().fit_transform(input)
estimator = AmplitudeLowFrequencyFluctuationEstimator() estimator = ALFFEstimator()
start_time = time.time() start_time = time.time()
alff, falff = estimator.fit_transform( alff, falff = estimator.fit_transform(
use_afni=True, use_afni=True,
@ -204,13 +202,13 @@ def test_AmplitudeLowFrequencyFluctuationEstimator_cache_afni() -> None:
@pytest.mark.skipif( @pytest.mark.skipif(
_check_afni() is False, reason="requires afni to be in PATH" _check_afni() is False, reason="requires afni to be in PATH"
) )
def test_AmplitudeLowFrequencyFluctuationEstimator_afni_vs_python() -> None: def test_ALFFEstimator_afni_vs_python() -> None:
"""Test that the cache works properly when using afni.""" """Test that the cache works properly when using afni."""
with PartlyCloudyTestingDataGrabber() as dg: with PartlyCloudyTestingDataGrabber() as dg:
input = dg["sub-01"] input = dg["sub-01"]
input = DefaultDataReader().fit_transform(input) input = DefaultDataReader().fit_transform(input)
estimator = AmplitudeLowFrequencyFluctuationEstimator() estimator = ALFFEstimator()
# Use an arbitrary TR to test the AFNI vs Python implementation # Use an arbitrary TR to test the AFNI vs Python implementation
afni_alff, afni_falff = estimator.fit_transform( afni_alff, afni_falff = estimator.fit_transform(

View file

@ -11,7 +11,7 @@ from numpy.testing import assert_array_equal
from scipy.stats import pearsonr from scipy.stats import pearsonr
from junifer.datareader import DefaultDataReader from junifer.datareader import DefaultDataReader
from junifer.markers.falff import AmplitudeLowFrequencyFluctuationParcels from junifer.markers.falff import ALFFParcels
from junifer.pipeline.utils import _check_afni from junifer.pipeline.utils import _check_afni
from junifer.storage import SQLiteFeatureStorage from junifer.storage import SQLiteFeatureStorage
from junifer.testing.datagrabbers import PartlyCloudyTestingDataGrabber from junifer.testing.datagrabbers import PartlyCloudyTestingDataGrabber
@ -21,8 +21,8 @@ from junifer.utils import logger
_PARCELLATION = "Schaefer100x7" _PARCELLATION = "Schaefer100x7"
def test_AmplitudeLowFrequencyFluctuationParcels_python() -> None: def test_ALFFParcels_python() -> None:
"""Test AmplitudeLowFrequencyFluctuationParcels using python.""" """Test ALFFParcels using python."""
# Get the SPM auditory data: # Get the SPM auditory data:
with PartlyCloudyTestingDataGrabber() as dg: with PartlyCloudyTestingDataGrabber() as dg:
@ -30,7 +30,7 @@ def test_AmplitudeLowFrequencyFluctuationParcels_python() -> None:
input = DefaultDataReader().fit_transform(input) input = DefaultDataReader().fit_transform(input)
# Create ParcelAggregation object # Create ParcelAggregation object
marker = AmplitudeLowFrequencyFluctuationParcels( marker = ALFFParcels(
parcellation=_PARCELLATION, parcellation=_PARCELLATION,
method="mean", method="mean",
use_afni=False, use_afni=False,
@ -46,15 +46,15 @@ def test_AmplitudeLowFrequencyFluctuationParcels_python() -> None:
@pytest.mark.skipif( @pytest.mark.skipif(
_check_afni() is False, reason="requires afni to be in PATH" _check_afni() is False, reason="requires afni to be in PATH"
) )
def test_AmplitudeLowFrequencyFluctuationParcels_afni() -> None: def test_ALFFParcels_afni() -> None:
"""Test AmplitudeLowFrequencyFluctuationParcels using afni.""" """Test ALFFParcels using afni."""
# Get the SPM auditory data: # Get the SPM auditory data:
with PartlyCloudyTestingDataGrabber() as dg: with PartlyCloudyTestingDataGrabber() as dg:
input = dg["sub-01"] input = dg["sub-01"]
input = DefaultDataReader().fit_transform(input) input = DefaultDataReader().fit_transform(input)
# Create ParcelAggregation object # Create ParcelAggregation object
marker = AmplitudeLowFrequencyFluctuationParcels( marker = ALFFParcels(
parcellation=_PARCELLATION, parcellation=_PARCELLATION,
method="mean", method="mean",
use_afni=True, use_afni=True,
@ -67,7 +67,7 @@ def test_AmplitudeLowFrequencyFluctuationParcels_afni() -> None:
assert afni_values.shape == (1, 100) assert afni_values.shape == (1, 100)
# Again, should be blazing fast # Again, should be blazing fast
marker = AmplitudeLowFrequencyFluctuationParcels( marker = ALFFParcels(
parcellation=_PARCELLATION, method="mean", fractional=False parcellation=_PARCELLATION, method="mean", fractional=False
) )
assert marker.use_afni is None assert marker.use_afni is None
@ -82,10 +82,10 @@ def test_AmplitudeLowFrequencyFluctuationParcels_afni() -> None:
@pytest.mark.parametrize( @pytest.mark.parametrize(
"fractional", [True, False], ids=["fractional", "non-fractional"] "fractional", [True, False], ids=["fractional", "non-fractional"]
) )
def test_AmplitudeLowFrequencyFluctuationParcels_python_vs_afni( def test_ALFFParcels_python_vs_afni(
fractional: bool, fractional: bool,
) -> None: ) -> None:
"""Test AmplitudeLowFrequencyFluctuationParcels using python. """Test ALFFParcels using python.
Parameters Parameters
---------- ----------
@ -98,7 +98,7 @@ def test_AmplitudeLowFrequencyFluctuationParcels_python_vs_afni(
input = DefaultDataReader().fit_transform(input) input = DefaultDataReader().fit_transform(input)
# Create ParcelAggregation object # Create ParcelAggregation object
marker_python = AmplitudeLowFrequencyFluctuationParcels( marker_python = ALFFParcels(
parcellation=_PARCELLATION, parcellation=_PARCELLATION,
method="mean", method="mean",
use_afni=False, use_afni=False,
@ -110,7 +110,7 @@ def test_AmplitudeLowFrequencyFluctuationParcels_python_vs_afni(
assert python_values.ndim == 2 assert python_values.ndim == 2
assert python_values.shape == (1, 100) assert python_values.shape == (1, 100)
marker_afni = AmplitudeLowFrequencyFluctuationParcels( marker_afni = ALFFParcels(
parcellation=_PARCELLATION, parcellation=_PARCELLATION,
method="mean", method="mean",
use_afni=True, use_afni=True,
@ -127,10 +127,10 @@ def test_AmplitudeLowFrequencyFluctuationParcels_python_vs_afni(
assert r > 0.99 assert r > 0.99
def test_AmplitudeLowFrequencyFluctuationParcels_storage( def test_ALFFParcels_storage(
tmp_path: Path, tmp_path: Path,
) -> None: ) -> None:
"""Test AmplitudeLowFrequencyFluctuationParcels storage. """Test ALFFParcels storage.
Parameters Parameters
---------- ----------
@ -142,7 +142,7 @@ def test_AmplitudeLowFrequencyFluctuationParcels_storage(
input = dg["sub-01"] input = dg["sub-01"]
input = DefaultDataReader().fit_transform(input) input = DefaultDataReader().fit_transform(input)
# Create ParcelAggregation object # Create ParcelAggregation object
marker = AmplitudeLowFrequencyFluctuationParcels( marker = ALFFParcels(
parcellation=_PARCELLATION, parcellation=_PARCELLATION,
method="mean", method="mean",
use_afni=False, use_afni=False,

View file

@ -11,7 +11,7 @@ from numpy.testing import assert_array_equal
from scipy.stats import pearsonr from scipy.stats import pearsonr
from junifer.datareader import DefaultDataReader from junifer.datareader import DefaultDataReader
from junifer.markers.falff import AmplitudeLowFrequencyFluctuationSpheres from junifer.markers.falff import ALFFSpheres
from junifer.pipeline.utils import _check_afni from junifer.pipeline.utils import _check_afni
from junifer.storage import SQLiteFeatureStorage from junifer.storage import SQLiteFeatureStorage
from junifer.testing.datagrabbers import PartlyCloudyTestingDataGrabber from junifer.testing.datagrabbers import PartlyCloudyTestingDataGrabber
@ -21,8 +21,8 @@ from junifer.utils import logger
_COORDINATES = "DMNBuckner" _COORDINATES = "DMNBuckner"
def test_AmplitudeLowFrequencyFluctuationSpheres_python() -> None: def test_ALFFSpheres_python() -> None:
"""Test AmplitudeLowFrequencyFluctuationSpheres using python.""" """Test ALFFSpheres using python."""
# Get the SPM auditory data: # Get the SPM auditory data:
with PartlyCloudyTestingDataGrabber() as dg: with PartlyCloudyTestingDataGrabber() as dg:
@ -30,7 +30,7 @@ def test_AmplitudeLowFrequencyFluctuationSpheres_python() -> None:
input = DefaultDataReader().fit_transform(input) input = DefaultDataReader().fit_transform(input)
# Create ParcelAggregation object # Create ParcelAggregation object
marker = AmplitudeLowFrequencyFluctuationSpheres( marker = ALFFSpheres(
coords=_COORDINATES, coords=_COORDINATES,
radius=5, radius=5,
method="mean", method="mean",
@ -47,15 +47,15 @@ def test_AmplitudeLowFrequencyFluctuationSpheres_python() -> None:
@pytest.mark.skipif( @pytest.mark.skipif(
_check_afni() is False, reason="requires afni to be in PATH" _check_afni() is False, reason="requires afni to be in PATH"
) )
def test_AmplitudeLowFrequencyFluctuationSpheres_afni() -> None: def test_ALFFSpheres_afni() -> None:
"""Test AmplitudeLowFrequencyFluctuationSpheres using afni.""" """Test ALFFSpheres using afni."""
# Get the SPM auditory data: # Get the SPM auditory data:
with PartlyCloudyTestingDataGrabber() as dg: with PartlyCloudyTestingDataGrabber() as dg:
input = dg["sub-01"] input = dg["sub-01"]
input = DefaultDataReader().fit_transform(input) input = DefaultDataReader().fit_transform(input)
# Create ParcelAggregation object # Create ParcelAggregation object
marker = AmplitudeLowFrequencyFluctuationSpheres( marker = ALFFSpheres(
coords=_COORDINATES, coords=_COORDINATES,
radius=5, radius=5,
method="mean", method="mean",
@ -69,7 +69,7 @@ def test_AmplitudeLowFrequencyFluctuationSpheres_afni() -> None:
assert afni_values.shape == (1, 6) assert afni_values.shape == (1, 6)
# Again, should be blazing fast # Again, should be blazing fast
marker = AmplitudeLowFrequencyFluctuationSpheres( marker = ALFFSpheres(
coords=_COORDINATES, coords=_COORDINATES,
radius=5, radius=5,
method="mean", method="mean",
@ -87,10 +87,10 @@ def test_AmplitudeLowFrequencyFluctuationSpheres_afni() -> None:
@pytest.mark.parametrize( @pytest.mark.parametrize(
"fractional", [True, False], ids=["fractional", "non-fractional"] "fractional", [True, False], ids=["fractional", "non-fractional"]
) )
def test_AmplitudeLowFrequencyFluctuationSpheres_python_vs_afni( def test_ALFFSpheres_python_vs_afni(
fractional: bool, fractional: bool,
) -> None: ) -> None:
"""Test AmplitudeLowFrequencyFluctuationSpheres python vs afni results. """Test ALFFSpheres python vs afni results.
Parameters Parameters
---------- ----------
@ -102,7 +102,7 @@ def test_AmplitudeLowFrequencyFluctuationSpheres_python_vs_afni(
input = DefaultDataReader().fit_transform(input) input = DefaultDataReader().fit_transform(input)
# Create ParcelAggregation object # Create ParcelAggregation object
marker_python = AmplitudeLowFrequencyFluctuationSpheres( marker_python = ALFFSpheres(
coords=_COORDINATES, coords=_COORDINATES,
radius=5, radius=5,
method="mean", method="mean",
@ -115,7 +115,7 @@ def test_AmplitudeLowFrequencyFluctuationSpheres_python_vs_afni(
assert python_values.ndim == 2 assert python_values.ndim == 2
assert python_values.shape == (1, 6) assert python_values.shape == (1, 6)
marker_afni = AmplitudeLowFrequencyFluctuationSpheres( marker_afni = ALFFSpheres(
coords=_COORDINATES, coords=_COORDINATES,
radius=5, radius=5,
method="mean", method="mean",
@ -133,10 +133,10 @@ def test_AmplitudeLowFrequencyFluctuationSpheres_python_vs_afni(
assert r > 0.99 assert r > 0.99
def test_AmplitudeLowFrequencyFluctuationSpheres_storage( def test_ALFFSpheres_storage(
tmp_path: Path, tmp_path: Path,
) -> None: ) -> None:
"""Test AmplitudeLowFrequencyFluctuationSpheres storage. """Test ALFFSpheres storage.
Parameters Parameters
---------- ----------
@ -148,7 +148,7 @@ def test_AmplitudeLowFrequencyFluctuationSpheres_storage(
input = dg["sub-01"] input = dg["sub-01"]
input = DefaultDataReader().fit_transform(input) input = DefaultDataReader().fit_transform(input)
# Create ParcelAggregation object # Create ParcelAggregation object
marker = AmplitudeLowFrequencyFluctuationSpheres( marker = ALFFSpheres(
coords=_COORDINATES, coords=_COORDINATES,
radius=5, radius=5,
method="mean", method="mean",

View file

@ -13,7 +13,7 @@ from nilearn.maskers import NiftiMasker
from ..api.decorators import register_marker from ..api.decorators import register_marker
from ..data import get_mask, load_parcellation, merge_parcellations from ..data import get_mask, load_parcellation, merge_parcellations
from ..stats import get_aggfunc_by_name from ..stats import get_aggfunc_by_name
from ..utils import logger, warn_with_log, raise_error from ..utils import logger, raise_error, warn_with_log
from .base import BaseMarker from .base import BaseMarker