Skip to content

Commit f2f771b

Browse files
authored
Merge pull request #380 from fooof-tools/suboex
[DOC] - Add sub-object example
2 parents 0d4b17c + 7a3204a commit f2f771b

File tree

1 file changed

+356
-0
lines changed

1 file changed

+356
-0
lines changed
Lines changed: 356 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,356 @@
1+
"""
2+
Model Sub-Objects
3+
=================
4+
5+
Introducing the objects used within the model object.
6+
7+
In order to flexible fit model definitions to data, the Model object needs to manage
8+
multiple pieces of information, including relating to the data, the fit modes,
9+
the fit algorithm, and the model results. To do so, the model object contains multiple
10+
sub-objects, which each manage one of these elements.
11+
12+
The model object also have several convenience methods attached directly the object
13+
(e.g., `fit`, `report`, `plot`, `get_params`, etc) so that for most basic usage you
14+
don't need to know the exact organization of the information within the model object.
15+
However, for more advanced analyses, and/or to start customizing model fitting, you need
16+
to know a bit about this structure. This example overviews the organization of the Model
17+
object, introducing each of the sub-objects.
18+
"""
19+
20+
###################################################################################################
21+
22+
# Define a helper function to explore object APIs
23+
def print_public_api(obj):
24+
"""Print out the public methods & attributes of an object."""
25+
print('\n'.join([el for el in dir(obj) if el[0] != '_']))
26+
27+
###################################################################################################
28+
# Data Object
29+
# -----------
30+
#
31+
# The :class:`~specparam.data.data.Data` object manages data.
32+
#
33+
34+
###################################################################################################
35+
36+
# Import the data object
37+
from specparam.data.data import Data
38+
39+
# Import simulation function to make some example data
40+
from specparam.sim import sim_power_spectrum
41+
42+
###################################################################################################
43+
44+
# Initialize a Data object
45+
data = Data()
46+
47+
###################################################################################################
48+
49+
# Check the options available on the data object
50+
print_public_api(data)
51+
52+
###################################################################################################
53+
54+
# Simulate an example power spectrum
55+
freqs, powers = sim_power_spectrum([3, 35],
56+
{'fixed' : [0, 1]}, {'gaussian' : [10, 0.5, 2]}, nlv=0.025)
57+
58+
# Add data to data object
59+
data.add_data(freqs, powers)
60+
61+
###################################################################################################
62+
63+
# Check some meta data from the data object
64+
print('Frequency resolution:\t\t', data.freq_res)
65+
print('Frequency range:\t\t', data.freq_range)
66+
67+
###################################################################################################
68+
69+
# Plot example data
70+
data.plot()
71+
72+
###################################################################################################
73+
74+
# Check printed data summary
75+
data.print()
76+
77+
###################################################################################################
78+
# Modes Object
79+
# ------------
80+
#
81+
# The :class:`~specparam.modes.modes.Modes` object manages fit modes.
82+
#
83+
# The :class:`~specparam.modes.modes.Modes` object itself contains individual mode definitions,
84+
# which are implemented in :class:`~specparam.modes.mode.Mode` objects. Defining custom fit
85+
# modes with the :class:`~specparam.modes.mode.Mode` object is covered in the custom modes example.
86+
# Here we will import pre-defined mode definitions and explore the
87+
# :class:`~specparam.modes.modes.Modes` object.
88+
#
89+
90+
###################################################################################################
91+
92+
# Import the Mode & Modes objects, plus collections of pre-defined modes
93+
from specparam.modes.modes import Modes
94+
from specparam.modes.definitions import PE_MODES, AP_MODES
95+
96+
###################################################################################################
97+
98+
# Print out the available pre-defined modes
99+
print(PE_MODES)
100+
print(AP_MODES)
101+
102+
###################################################################################################
103+
104+
# Initialize a Modes object, passing in initialize Mode objects
105+
modes = Modes(AP_MODES['fixed'], PE_MODES['gaussian'])
106+
107+
###################################################################################################
108+
109+
# Check the options available on the modes object
110+
print_public_api(modes)
111+
112+
###################################################################################################
113+
114+
# Print description of the modes
115+
modes.print(True)
116+
117+
###################################################################################################
118+
# Algorithm Object
119+
# ----------------
120+
#
121+
# The :class:`~specparam.algorithms.algorithm.Algorithm` object manages fit algorithms.
122+
#
123+
# Defining custom fit algorithms with the :class:`~specparam.algorithms.algorithm.Algorithm`
124+
# object is covered in the custom algorithms example. Here we will import pre-defined fit
125+
# algorithms and explore the
126+
# :class:`~specparam.algorithms.algorithm.Algorithm` object.
127+
#
128+
129+
###################################################################################################
130+
131+
# Import the Algorithm object, plus collection of pre-defined algorithms
132+
from specparam.algorithms.algorithm import Algorithm
133+
from specparam.algorithms.definitions import ALGORITHMS
134+
135+
###################################################################################################
136+
137+
# Select and initialize an algorithm
138+
algorithm = ALGORITHMS['spectral_fit']()
139+
140+
###################################################################################################
141+
142+
# Check the options available on the algorithm object
143+
print_public_api(algorithm)
144+
145+
###################################################################################################
146+
147+
# Check the description of the algorithm
148+
algorithm.description
149+
150+
###################################################################################################
151+
152+
# Print out information about the algorithm
153+
algorithm.print()
154+
155+
###################################################################################################
156+
# Results Object
157+
# --------------
158+
#
159+
# The :class:`~specparam.results.results.Results` object manages fit results.
160+
#
161+
162+
###################################################################################################
163+
164+
# Import the Results object
165+
from specparam.results.results import Results
166+
167+
###################################################################################################
168+
169+
# Initialize a results object
170+
results = Results()
171+
172+
###################################################################################################
173+
174+
# Check the options available on the results object
175+
print_public_api(results)
176+
177+
###################################################################################################
178+
# Results Sub-Objects
179+
# ~~~~~~~~~~~~~~~~~~~
180+
#
181+
# As you may notice above, the :class:`~specparam.results.results.Results` object itself
182+
# has several sub-objects to manage results information and related information.
183+
#
184+
# This includes the `Bands` object, which manages frequency band definitions, and the
185+
# `Metrics` object, which manages post-fitting evaluation metrics.
186+
#
187+
188+
###################################################################################################
189+
190+
# Check the Bands object which is attached to the Results object
191+
print(results.bands)
192+
193+
# Check the Metrics object which is attached to the Results object
194+
print(results.metrics)
195+
196+
###################################################################################################
197+
# ModelParameters
198+
# ~~~~~~~~~~~~~~~
199+
#
200+
# The :class:`~specparam.results.params.ModelParameters` object manages model fit parameters.
201+
#
202+
203+
###################################################################################################
204+
205+
# Import the ModelParameters object
206+
from specparam.results.params import ModelParameters
207+
208+
###################################################################################################
209+
210+
# Initialize model parameters object
211+
params = ModelParameters()
212+
213+
# Check the API of the object
214+
print_public_api(params)
215+
216+
###################################################################################################
217+
218+
# Check what object stores by exporting as a dictionary
219+
params.asdict()
220+
221+
###################################################################################################
222+
# ModelComponents
223+
# ~~~~~~~~~~~~~~~
224+
#
225+
# The :class:`~specparam.results.components.ModelComponents` object manages model components.
226+
#
227+
228+
###################################################################################################
229+
230+
# Import the ModelComponents object
231+
from specparam.results.components import ModelComponents
232+
233+
###################################################################################################
234+
235+
# Initialize model components object
236+
components = ModelComponents()
237+
238+
# Check the API of the object
239+
print_public_api(components)
240+
241+
###################################################################################################
242+
# Base Model Object
243+
# -----------------
244+
#
245+
# In the above, we have introduced the sub-objects that provide for the functionality of
246+
# model fitting, including managing the data, fit modes, fit algorithm, and results.
247+
#
248+
# Before the user-facing model objects, there is one final piece: the
249+
# :class:`~specparam.models.base.BaseModel` object. This base level model object is
250+
# inherited by all the model objects, providing a shared common definition of some
251+
# base functionality.
252+
#
253+
254+
###################################################################################################
255+
256+
# Import the base model object
257+
from specparam.models.base import BaseModel
258+
259+
###################################################################################################
260+
261+
# Initialize a base model, passing in empty mode definitions
262+
base = BaseModel(None, None, False)
263+
264+
# Check the API of the object
265+
print_public_api(base)
266+
267+
###################################################################################################
268+
#
269+
# In the above, we can see that the :class:`~specparam.models.base.BaseModel` object
270+
# implements a few elements that are common across all derived model objects, including
271+
# includes the modes definition and a couple methods.
272+
#
273+
274+
###################################################################################################
275+
# Model Objects
276+
# -------------
277+
#
278+
# Finally, we get to the user-facing model objects!
279+
#
280+
# Here, we will start with the :class:`~specparam.models.model.SpectralModel` object,
281+
# initializing it as typically done as a user, and then explore the sub-objects.
282+
#
283+
# To see more detail on how the Model object initializes and gets built based on all
284+
# the sub-objects, see the implementation, including the `__init__`.
285+
#
286+
287+
###################################################################################################
288+
289+
# Import a spectral model object
290+
from specparam import SpectralModel
291+
292+
###################################################################################################
293+
294+
# Initialize a model object
295+
fm = SpectralModel()
296+
297+
# Check the API of the object
298+
print_public_api(fm)
299+
300+
###################################################################################################
301+
302+
# Check the sub-objects
303+
print(type(fm.data))
304+
print(type(fm.modes))
305+
print(type(fm.algorithm))
306+
print(type(fm.results))
307+
308+
###################################################################################################
309+
#
310+
# Looking into these sub-objects, you see that they are all the same as we introduced by
311+
# initializing all these sub-objects one-by-one above, the only different being that they are
312+
# now all connected together in the model object!
313+
#
314+
315+
###################################################################################################
316+
# Derived model objects
317+
# ~~~~~~~~~~~~~~~~~~~~~
318+
#
319+
# Above, we used the `SpectralModel` object as an example object to introduce the
320+
# structure of the model object & sub-objects.
321+
#
322+
# The same approach is used for derived model objects (e.g. `SpectralGroupModel`) is used,
323+
# the only difference being that as the shape and size of the data and results change, different
324+
# versions of the data and results sub-objects are used (e.g. `Data2D` and `Results2D`).
325+
326+
###################################################################################################
327+
328+
# Import a spectral model object
329+
from specparam import SpectralGroupModel, SpectralTimeModel, SpectralTimeEventModel
330+
331+
###################################################################################################
332+
333+
# Initialize a group model object
334+
fg = SpectralGroupModel()
335+
336+
# Check the sub-objects
337+
print(type(fg.data))
338+
print(type(fg.results))
339+
340+
###################################################################################################
341+
342+
# Initialize a time model object
343+
ft = SpectralTimeModel()
344+
345+
# Check the sub-objects
346+
print(type(ft.data))
347+
print(type(ft.results))
348+
349+
###################################################################################################
350+
351+
# Initialize an event model object
352+
fe = SpectralTimeEventModel()
353+
354+
# Check the sub-objects
355+
print(type(fe.data))
356+
print(type(fe.results))

0 commit comments

Comments
 (0)