Skip to content

Commit df4a3f1

Browse files
authored
turn dipole attrs into properties (#13153)
1 parent 3077476 commit df4a3f1

File tree

2 files changed

+76
-15
lines changed

2 files changed

+76
-15
lines changed

mne/beamformer/_rap_music.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,8 @@ def _apply_rap_music(
146146
)
147147
for dipole, ori in zip(dipoles, oris):
148148
signs = np.sign((dipole.ori * ori).sum(-1, keepdims=True))
149-
dipole.ori *= signs
150-
dipole.amplitude *= signs[:, 0]
149+
dipole._ori *= signs
150+
dipole._amplitude *= signs[:, 0]
151151
logger.info("[done]")
152152
return dipoles, explained_data
153153

mne/dipole.py

Lines changed: 74 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -131,28 +131,77 @@ def __init__(
131131
verbose=None,
132132
):
133133
self._set_times(np.array(times))
134-
self.pos = np.array(pos)
135-
self.amplitude = np.array(amplitude)
136-
self.ori = np.array(ori)
137-
self.gof = np.array(gof)
138-
self.name = name
139-
self.conf = dict()
134+
self._pos = np.array(pos)
135+
self._amplitude = np.array(amplitude)
136+
self._ori = np.array(ori)
137+
self._gof = np.array(gof)
138+
self._name = name
139+
self._conf = dict()
140140
if conf is not None:
141141
for key, value in conf.items():
142-
self.conf[key] = np.array(value)
143-
self.khi2 = np.array(khi2) if khi2 is not None else None
144-
self.nfree = np.array(nfree) if nfree is not None else None
142+
self._conf[key] = np.array(value)
143+
self._khi2 = np.array(khi2) if khi2 is not None else None
144+
self._nfree = np.array(nfree) if nfree is not None else None
145145

146146
def __repr__(self): # noqa: D105
147147
s = f"n_times : {len(self.times)}"
148148
s += f", tmin : {np.min(self.times):0.3f}"
149149
s += f", tmax : {np.max(self.times):0.3f}"
150150
return f"<Dipole | {s}>"
151151

152+
@property
153+
def pos(self):
154+
"""The dipoles positions (m) in head coordinates."""
155+
return self._pos
156+
157+
@property
158+
def amplitude(self):
159+
"""The amplitude of the dipoles (Am)."""
160+
return self._amplitude
161+
162+
@property
163+
def ori(self):
164+
"""The dipole orientations (normalized to unit length)."""
165+
return self._ori
166+
167+
@property
168+
def gof(self):
169+
"""The goodness of fit."""
170+
return self._gof
171+
172+
@property
173+
def name(self):
174+
"""Name of the dipole."""
175+
return self._name
176+
177+
@name.setter
178+
def name(self, name):
179+
_validate_type(name, str, "name")
180+
self._name = name
181+
182+
@property
183+
def conf(self):
184+
"""Confidence limits in dipole orientation."""
185+
return self._conf
186+
187+
@property
188+
def khi2(self):
189+
"""The χ^2 values for the fits."""
190+
return self._khi2
191+
192+
@property
193+
def nfree(self):
194+
"""The number of free parameters for each fit."""
195+
return self._nfree
196+
152197
@verbose
153198
def save(self, fname, overwrite=False, *, verbose=None):
154199
"""Save dipole in a ``.dip`` or ``.bdip`` file.
155200
201+
The ``.[b]dip`` format is for :class:`mne.Dipole` objects, that is,
202+
fixed-position dipole fits. For these fits, the amplitude, orientation,
203+
and position vary as a function of time.
204+
156205
Parameters
157206
----------
158207
fname : path-like
@@ -203,7 +252,7 @@ def crop(self, tmin=None, tmax=None, include_tmax=True, verbose=None):
203252
self.times, tmin, tmax, sfreq=sfreq, include_tmax=include_tmax
204253
)
205254
self._set_times(self.times[mask])
206-
for attr in ("pos", "gof", "amplitude", "ori", "khi2", "nfree"):
255+
for attr in ("_pos", "_gof", "_amplitude", "_ori", "_khi2", "_nfree"):
207256
if getattr(self, attr) is not None:
208257
setattr(self, attr, getattr(self, attr)[mask])
209258
for key in self.conf.keys():
@@ -521,15 +570,23 @@ def ch_names(self):
521570
return self.info["ch_names"]
522571

523572
@verbose
524-
def save(self, fname, verbose=None):
525-
"""Save dipole in FIF format.
573+
def save(self, fname, *, overwrite=False, verbose=None):
574+
"""Save fixed dipole in FIF format.
575+
576+
The ``.fif[.gz]`` format is for :class:`mne.DipoleFixed` objects, that is,
577+
fixed-position and optionally fixed-orientation dipole fits. For these fits,
578+
the amplitude (and optionally orientation) vary as a function of time,
579+
but not the position.
526580
527581
Parameters
528582
----------
529583
fname : path-like
530584
The name of the FIF file. Must end with ``'-dip.fif'`` or
531585
``'-dip.fif.gz'`` to make it explicit that the file contains
532586
dipole information in FIF format.
587+
%(overwrite)s
588+
589+
.. versionadded:: 1.10.0
533590
%(verbose)s
534591
535592
See Also
@@ -547,7 +604,7 @@ def save(self, fname, verbose=None):
547604
),
548605
(".fif", ".fif.gz"),
549606
)
550-
_write_evokeds(fname, self, check=False)
607+
_write_evokeds(fname, self, check=False, overwrite=overwrite)
551608

552609
def plot(self, show=True, time_unit="s"):
553610
"""Plot dipole data.
@@ -595,6 +652,10 @@ def plot(self, show=True, time_unit="s"):
595652
def read_dipole(fname, verbose=None):
596653
"""Read a dipole object from a file.
597654
655+
Non-fixed-position :class:`mne.Dipole` objects are usually saved in ``.[b]dip``
656+
format. Fixed-position :class:`mne.DipoleFixed` objects are usually saved in
657+
FIF format.
658+
598659
Parameters
599660
----------
600661
fname : path-like

0 commit comments

Comments
 (0)