Skip to content

Commit

Permalink
Update contributing_code.md
Browse files Browse the repository at this point in the history
rewrote the lost last part of the markdown doc
  • Loading branch information
avolu committed Feb 16, 2024
1 parent 129ef9e commit 5bcc620
Showing 1 changed file with 41 additions and 1 deletion.
42 changes: 41 additions & 1 deletion _doc/contributing_code.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ In this example we will incorporate two new functions into the toolbox: A functi
### Where do these functions belong?
The function to prune channels belongs to /siproc/quality.py and will simply be called "prune". It will then be available with

`import cedalion.sigproc.quality` and calling `quality.prune()`.
`import cedalion.sigproc.quality` and calling `quality.prune()`. The `quality.prune()`function will use an SNR threshold, amongst others, to classify channels as bad channels. For this we create a small helper function in the same module, `quality.snr()`, as it might come in handy elswhere too.

The function to identify motion artifacts belongs to a new module in the sigproc subpackage, since at the time of this example sigproc only has a module "frequency" and "quality". We will call this module "artifact" and the function "id_motion". It will then be available with

Expand Down Expand Up @@ -84,3 +84,43 @@ def function_name(inputVar1: cdt.NDTimeSeries, inputVar2: Quantity):
This generates a new function *function_name* with two input arguments *inputVar1* and *inputVar2* that returns what it did as *something*.
The input arguments should have expected data types assigned to them. Here, *inputVar1* is expected to be of the data type "NDTimeSeriesSchema", which is an xarray that contains at least two dimensions "channel" and "time". *inputVar2* is expected to be of the data type *Quantity* ==[TBD? @emiddell]==.
The function is wrapped by putting `@cdc.validate_schemas`in front, which will check these data types and assert an error at runtime, if the inputs do not match the expected type.

Now we can create a small helper function that calculates the SNR of fNIRS channels that will be used in the main `quality.prune()` routine. Using restricting the argument to an xarray time series input type allows us to calculate the SNR in a single line.

```
@cdc.validate_schemas
def snr(amplitudes: cdt.NDTimeSeries):
"""Calculates channel SNR of each channel and wavelength as the ratio betwean mean and std
of the amplitude signal
"""
snr = amplitudes.mean("time") / amplitudes.std("time")
return snr
```

The actual `quality.prune()` method can be built around this helper function and includes some other thresholding parameters. The pruning function is expected to provide a list of either active (good) or pruned (bad) channels. In the current approach we use "MeasList", which is a subset of the xarray "channel" coordinates: Every channel that gets pruned is simply removed from that list. The output data structure of the function is therefore identical to the input data structure, with simply an added/changed "MeasList" that can be used to easily select or reject (un)pruned channels.

```
#@cdc.validate_schemas
def prune(data: cdt.NDTimeSeries, SNRThresh: Quantity, dRange: Quantity, SDrange: Quantity):
# create list of active channels if it does not exist yet
if not hasattr(data, "MeasList"):
# add measurement list to dat xarray object. it countains the full list of channels
data['MeasList'] = list(data.coords['channel'].values)
# for all active channels in the MeasList check if they meet the conditions or drop them from the list
## find channels with bad snr
# calculate SNR of channel amplitudes and find channels with SNR below threshold. Then remove them from the MeasList
dat_snr = snr(data.amp)
drop_list = dat_snr.where(dat_snr < SNRThresh).dropna(dim="channel").channel.values
data = data.drop_sel(MeasList=drop_list)
## Calculate channel distances for all channels in the measurement list from the geo3D coordinates
## Remove channels outside of dRange:TBD + update quality.prune
## Remove channels outside of SDrange:TBD + update quality.prune
return data
```

0 comments on commit 5bcc620

Please sign in to comment.