sampsapursiainen / zeffiro_interface

Interface for using finite elements in inverse problems with complex domains
GNU General Public License v3.0
24 stars 15 forks source link

lead_field_eeg_fem: separate stensil construction and interpolation into separate steps (+ ZefSourceModel breaks forward compatibility, read more below) #102

Closed SeSodesa closed 2 years ago

SeSodesa commented 2 years ago

This is squash of 66 commits into a single one. The main differences are the ones mentioned in the title, and the utilized interpolation functions are called zef_{lead_field,whitney,hdiv,st_venant}_interpolation, which are found in the m/ folder.

Also, the zef.source_model is now specified as the ZefSourceModel enumeration. This can be found in m/ZefSourceModel.m. NOTE: Old versions of ZI cannot open models that have been save with this new type of source model type, but new versions can open old models.

In addition, the sign if the analytical lead field 𝐿, constructed by zef_lead_field_eeg_multilayer_sphere.m based on the Ary model was inverted. This was because the test function zef_lead_field_sign seemed to return a correct orientation for the FEM 𝐿, but a wrong one for the analytical 𝐿.

Below is a collection of the 66 independent commit messages. Some of them might not be visible on GitHub because of commit message size limitations.


Added enumeration ZefSourceModel

Also added a function zef_source_model_from(input) for mapping integers and strings to its different variants ZefSourceModel.{Error, Hdiv, Whitney}.

zef_source_model_from: added more robustness, like handling of ZefSourceModels idempotently

Added zef_string_from_source_model for converting ZefSourceModel variants to character arrays

Took ZefSourceModel and zef_source_model_from into use

In other words, instead of plain integers, the source model is now expressed as an enumeration ZefSourceModel.{Whitney, Hdiv}. The function converts given integers and strings into corresponding source model variants.

Added a function m/zef_tetra_barycentra

Does what the name implies.

lead_field_eeg_fem: replaced lead field interpolation with function zef_lead_field_interpolation

At least mostly. Still debating whether tetrahedral barycentra should be given as a parameter.

Added missing function m/zef_lead_field_interpolation

Added separate functions m/zef_{whitney,hdiv}_interpolation

lead_field_eegfem: took functions m/zef{whitney,hdiv}_interpolation into use

Removed function m/zef_lead_field_interpolation.m

It was trying too hard to be too general. Better to have source model -dependent separate functions.

zef_hdiv_interpolation: removed leftover Whitney code

zef_{whitney,hdiv}_interpolation: switched roles of {dir,loc}_mat

Aux_mat_1 represented directions in the old code, whereas Aux_mat_2 represented locations. I think.

Added function m/zef_adjacency_matrix.m

zef_adjacency_matrix: added progress bar

zef_adjacency_matrix: removed unnecessary call to waitbar

Added file m/zef_st_venant_interpolation.m

An initial untested implementation.

zef_transfer_matrix: cleanup in preparation for adding into EEG lead field routine

Added function m/zef_L2_norm

Does what the name implies.

zef_L2_norm: added a missing semicolon

zef_L2_norm: add check for 2 input arguments

zef_L2_norm: fixed name of first parameter {vec → arr}

zef_transfer_matrix: made variable names and waitbar title more descriptive

zef_tetra_barycentra: updated description of tetrahedra.

lead_field_eeg_fem + interpolation functions: update of responsibilities

• The EEG lead field routine now calculates a transfer matrix or stensil 𝑇 just like how the tES routine does it, with zef_transfer_matrix.

• The interpolation functions zef_{whitney,hdiv}_interpolation were changed to reflect this: they now construct the interpolation weight matrix 𝐺 in one go, and the actual lead field interpolation is done via multiplication: 𝐿 = 𝑇' * 𝐺.

Added function m/zef_lead_field_interpolation

lead_field_eeg_fem: took zef_lead_field_interpolaiton into use

zef_ew_dipoles: renamed variables to make them more descriptive

zef_fi_dipoles: renamed variables and added documentation comments

zef_st_venant_interpolation: added a missing comma to parameter list

zef_L2_norm: sum over all elements if no dimension is given

lead_field_eeg_fem: removed unnecessary clear statement

zef_source_model_from copied as a static method ZefSourceModel.from

Also replaced invocations of the function with the static method.

Removed the separate function zef_source_model_from

This is no longer needed because of the static method ZefSourceModel.from, which works identically.

zef_adjacency_matrix: renamed N → n_of_nodes

zef_st_venant_interpolation: fixed dimension mismatches between restriction matrices

Also skipped iterations with nodes that had no neighbours in adjacency matrix, created by zef_adjacency_matrix.

lead_field_eeg_gem + zef_lead_field_interpolation: added St. Venant as an accepted interpolation method

Not convinced it works as intended yet, though.

zef_st_venant_interpolation: restriction matrix P rows now built correctly?

Projections onto x-, y- and z-components of the moments made with the cartesian basis matrix.

zef_tetra_barycentra: added argument validation

zef_adjacency_matrix: added argument validation

zef_tetra_volume: added argument validation

zef_tetra_volume: more descriptive variable names and comments

Added parameter validation to zef_{whitney,hdiv,st_venant}_interpolation

Also removed a commented line from zef_st_venant_interpolation.

Fixed parameter name in zef_{whitney,hdiv,st_venant}_interpolation

Added lead field comparison scripts in m/auxiliary_scripts

Currently calculate_differences.m takes into account that the lead field is inverted and not properly shifted in relation to the ground potential level with negation and averaging, respectively. This should be changed in the EEG lead field routine itself (zef_transfer_matrix).

zef_transfer_matrix: added a TODO regarding setting the potential level and changing the sign of the transfer matrix

lead_field_eeg_fem + zef_build_electrodes: define impedance_vec even when PEM is used

Previously impedance_vec was not set properly when using Point Electrode Model, resulting in a runtime error about missing variables.

lead_field_eeg_fem: implemented potential level setting

… as the removal of row sums from the transfer matrix T. This seems to reduce the differences between the analytical and the FEM lead fields.

zef_build_electrodes: reduced number of arguments and renamed variables

zef_lead_field_eeg_multilayer_sphere: added proper indentations

zef_fi_dipoles: added a missing line break

zef_fi_dipoles: made variable names more descriptive.

Added function zef_lead_field_sign

zef_fi_dipoles: added better documentation and better variable names

Also turned the face mapping matrix into a private validated function in the same file.

zef_lead_field_sign: settled on a signature

The lead field L contains the orientations of the sources as column triplets, so the directions do not need to be passed in as an argument.

zef_ew_dipoles: added cleanup operations for waitbar

lead_field_eeg_fem: added potential level and sign setting

Done by subtracting the mean of L_eeg over the electrodes and multiplying L_eeg by its sign, determined by zef_lead_field_sign.

zef_build_electrodes: added cleanup object

zef_lead_field_sign: change comparison logic

Instead of comparing source closest to origin (SCO) and electrode with largest z-coordinate, compare the SCO and electrode whose xy-projection is closest to that of SCO.

zef_build_electrodes: changed output to console to a clear warning

zef_lead_field_sign: renamed parameters and added argument validations

zef_lead_field_sign: changed leftover EGZ → PCE in comment

Added a more "funcitonal version" of the calculate_differences -script

Removed unnecessary copy of zef_lead_field_multilayer_sphere

zef_lead_field_sign: should work as intended now

Hardcoded the (positive) cartesian z-direction for source closest to origin.

zef_lead_field_sign: removed unnecessary line

zef_eeg_multilayer_sphere: invert sign at the end

Also added line breaks