You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The EquivalentSources class implements a simple method that uses 1/distance as the kernel function. It's also based on the Verde model of fit/predict/grid. This means that it works for any potential field with few extra parameters. But it has some restrictions:
It can only fit and predict one data type (whatever field it fits, that's what it predicts).
It can't handle magnetic data specific operations like reduction to the pole because it's not really modelling magnetic fields.
It can't fit multiple data types, for example gravity + gravity gradients or magnetic total-field anomaly and anomalous B field components (from SWARM for example).
It can't predict fields it didn't fit. For example, predict anomalous field components from fitting total-field anomaly data.
The grid method is a bit strange because it needs the extra upward component. So our classes aren't really compatible with Verde. This style also doesn't work if we want to implement the other restrictions above (how do we specify inc/dec for total field anomaly or the field type?).
Me and @indiauppal have been playing with implementations for an upcoming paper that fits total-field anomaly and predicts the 3-component anomalous magnetic field (basically undo the projection onto the main field directions). While coding and using these magnetic-specific equivalent sources, we found that:
The fit/predict/grid model doesn't generalize. The main problem is .grid. It's so much simpler to just have fit and predict and let users call verde.grid_coordinates and verde.make_xarray_grid. This handles every possible use case without us having to guess what people want to do.
Passing data to fit be tricky. See below.
Predicting should be relatively easy. predict can take an extra field argument that can take a string or list of strings of fields to predict. For magnetics, we never need to predict total field anomaly since that can be calculated separately by function that takes the 3 field components and the main field direction. field can default to something or just be mandatory.
Basically ditch all pretense that equivalent sources are based on the Verde gridder model. This won't work anyway and has been discussed in the past (can't find a link right now).
Proposal for field-specific equivalent sources
Simplify the code classes for EquivalentSources and EquivalentSourcesGB. Make them not based on verde.base.BaseGridder. Inherit from scikit-learn directly.
Only implement fit and predict as public methods (maybe a few more the gradient-boosted version if needed). For the current classes, the arguments of these methods remain the same.
Start with magnetic equivalent sources since mag is more complicated than grav.
Arguments for fit could be a single data argument. It would be a dictionary with keys=fields and values = tuple of (coordinates, data, weights). For total-field anomaly it would need (coordinates, data, weights, main_field_direction).
predict takes coordinates, field only, both required.
To predict total-field anomaly, use field="whatever we use for all 3 components" and then we can call a separate function total_field_anomaly(field_components, main_field_direction). This one extra function call but makes everything so much simpler because we don't have to deal with the extra field direction argument that is only used for this (did I mention that magnetics suck?).
To reduce an anomaly to the pole correctly, we need to use the correct magnetization direction for the sources when fitting. Then, we need to predict while changing the direction of the sources to the pole and setting the main field direction also to the pole. This is a problem because the source direction is a parameter of the class. Using set_params would mean that we lose the original class so probably not the best option. A way to do this would be to add a method to_pole that checks if the class is fitted (issue a warning/error that you should fit first) and returns a copy of the class (keeping references to estimated attributes) with the source direction changed to the pole. It would be used as total_field_anomaly(eqs.fit(...).to_pole().predict(...), direction_at_pole).
Whatever works for magnetics will also work for gravity. So that's why we should do this one first. Tests of the API would be:
An example fitting and predicting total-field anomaly using the defaults.
An example reducing an anomaly to the pole.
Predicting the 3-field components correctly is tricky and @indiauppal is working on this as a research question.
The text was updated successfully, but these errors were encountered:
Basically, the fit method should take keyword arguments (one for each field), with tuples containing the coordinates of the observation points, the observed data, their weights (optionally), and in case we are working if tfa (total field anomaly) we should also pass the inclination of declination of the background field.
The predict method will ask the coordinates and the field that should be computed. This "field" should be one of the ones available in the forward modelling functions: b, b_e, b_n, b_u (see #447 for more details). The tfa is not going to be a valid field: users should predict the three magnetic components and then compute the total field anomaly from them.
The
EquivalentSources
class implements a simple method that uses 1/distance as the kernel function. It's also based on the Verde model of fit/predict/grid. This means that it works for any potential field with few extra parameters. But it has some restrictions:grid
method is a bit strange because it needs the extra upward component. So our classes aren't really compatible with Verde. This style also doesn't work if we want to implement the other restrictions above (how do we specify inc/dec for total field anomaly or the field type?).Me and @indiauppal have been playing with implementations for an upcoming paper that fits total-field anomaly and predicts the 3-component anomalous magnetic field (basically undo the projection onto the main field directions). While coding and using these magnetic-specific equivalent sources, we found that:
.grid
. It's so much simpler to just havefit
andpredict
and let users callverde.grid_coordinates
andverde.make_xarray_grid
. This handles every possible use case without us having to guess what people want to do.fit
be tricky. See below.predict
can take an extrafield
argument that can take a string or list of strings of fields to predict. For magnetics, we never need to predict total field anomaly since that can be calculated separately by function that takes the 3 field components and the main field direction.field
can default to something or just be mandatory.Proposal for field-specific equivalent sources
EquivalentSources
andEquivalentSourcesGB
. Make them not based onverde.base.BaseGridder
. Inherit from scikit-learn directly.fit
andpredict
as public methods (maybe a few more the gradient-boosted version if needed). For the current classes, the arguments of these methods remain the same.fit
could be a singledata
argument. It would be a dictionary with keys=fields and values = tuple of (coordinates, data, weights). For total-field anomaly it would need (coordinates, data, weights, main_field_direction).predict
takescoordinates, field
only, both required.field="whatever we use for all 3 components"
and then we can call a separate functiontotal_field_anomaly(field_components, main_field_direction)
. This one extra function call but makes everything so much simpler because we don't have to deal with the extra field direction argument that is only used for this (did I mention that magnetics suck?).set_params
would mean that we lose the original class so probably not the best option. A way to do this would be to add a methodto_pole
that checks if the class is fitted (issue a warning/error that you should fit first) and returns a copy of the class (keeping references to estimated attributes) with the source direction changed to the pole. It would be used astotal_field_anomaly(eqs.fit(...).to_pole().predict(...), direction_at_pole)
.Whatever works for magnetics will also work for gravity. So that's why we should do this one first. Tests of the API would be:
Predicting the 3-field components correctly is tricky and @indiauppal is working on this as a research question.
The text was updated successfully, but these errors were encountered: