Skip to content

Commit 6ea831b

Browse files
committed
Add hampel & findpeaks
1 parent e407113 commit 6ea831b

File tree

4 files changed

+166
-11
lines changed

4 files changed

+166
-11
lines changed

documentation/all_docs_ref/all_refs.md

+9-8
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
| \myreflink{grdmask} | \myreflink{grdmath} | grdmix | \myreflink{grdpaste} | grdproject | \myreflink{grdsample} | \myreflink{grdtrack} | \myreflink{grdtrend} |
2121
| \myreflink{grdvector} | \myreflink{grdview} | grdvolume | greenspline | \myreflink{histogram} | \myreflink{image} | \myreflink{inset} | kml2gmt |
2222
| \myreflink{legend} | \myreflink{makecpt} | mapproject | \myreflink{mask} | \myreflink{movie} | \myreflink{nearneighbor} | \myreflink{plot} | \myreflink{plot3d} |
23-
| \myreflink{project} | psconvert | \myreflink{rose} | \myreflink{sample1d} | \myreflink{solar} | spectrum1d | sph2grd | sphdistance |
23+
| \myreflink{project} | psconvert | \myreflink{rose} | \myreflink{sample1d} | \myreflink{solar} | \myreflink{spectrum1d} | sph2grd | sphdistance |
2424
| \myreflink{sphinterpolate} | \myreflink{sphtriangulate} | \myreflink{subplot} | \myreflink{surface} | \myreflink{ternary} | \myreflink{text} | \myreflink{trend1d} | \myreflink{trend2d} |
2525
| \myreflink{triangulate} | \myreflink{wiggle} | \myreflink{xyz2grd} | | | | | |
2626

@@ -57,13 +57,14 @@ its use requires resorting to the \myreflink{Monolithic} mode.
5757
| | | | | | | | |
5858
|:-----|:----|:----|:----|:----|:----|:----|:----|
5959
| \myreflink{ablines} | \myreflink{append2fig} | \myreflink{blendimg!} | \myreflink{cart2pol} | \myreflink{cart2sph} | \myreflink{colorzones!} | \myreflink{cpt4dcw} | \myreflink{crop} |
60-
| \myreflink{cubeplot} | \myreflink{coastlinesproj} | \myreflink{cubeslice} | \myreflink{date2doy} | \myreflink{delrows!} | \myreflink{doy2date} | \myreflink{gadm} | \myreflink{geocoder} |
61-
| \myreflink{geodetic2enu} | \myreflink{getbyattrib} | \myreflink{gmtread} | \myreflink{gmtwrite} | \myreflink{graticules} | \myreflink{gridit} | \myreflink{gunique} | \myreflink{imagesc} |
62-
| \myreflink{inpolygon} | \myreflink{inwhichpolygon} | \myreflink{image_alpha!} | \myreflink{image_cpt!} | \myreflink{imshow} | \myreflink{ind2rgb} | \myreflink{info} | \myreflink{isnodata} |
63-
| \myreflink{lelandshade} | \myreflink{linearfitxy} | \myreflink{magic} | \myreflink{mat2ds} | \myreflink{mat2grid} | \myreflink{mat2img} | \myreflink{mosaic} | \myreflink{ODE2ds} |
64-
| \myreflink{orbits} | \myreflink{pca} | \myreflink{plotgrid!} | \myreflink{plotyy} \myreflink{pol2cart} | \myreflink{polygonlevels} | \myreflink{rasterzones!} | \myreflink{regiongeog} | \myreflink{remotegrid} |
65-
| \myreflink{rescale} | \myreflink{slicecube} | \myreflink{sph2cart} | \myreflink{stackgrids} | \myreflink{ter2cart} | \myreflink{theme} | \myreflink{uniqueind} | \myreflink{vecangles} |
66-
| \myreflink{weather} | \myreflink{whereami} | \myreflink{worldrectgrid} | \myreflink{worldrectcoast} | \myreflink{worldrectangular} | \myreflink{xyzw2cube} | \myreflink{yeardecimal} | \myreflink{zonal_stats} |
60+
| \myreflink{cubeplot} | \myreflink{coastlinesproj} | \myreflink{cubeslice} | \myreflink{date2doy} | \myreflink{delrows!} | \myreflink{doy2date} | \myreflink{findpeaks} | \myreflink{gadm} |
61+
| \myreflink{geocoder} | \myreflink{geodetic2enu} | \myreflink{getbyattrib} | \myreflink{gmtread} | \myreflink{gmtwrite} | \myreflink{graticules} | \myreflink{gridit} | \myreflink{gunique} |
62+
| \myreflink{hampel} | \myreflink{imagesc} | \myreflink{inpolygon} | \myreflink{inwhichpolygon} | \myreflink{image_alpha!} | \myreflink{image_cpt!} | \myreflink{imshow} | \myreflink{ind2rgb} |
63+
| \myreflink{info} | \myreflink{isnodata} | \myreflink{lelandshade} | \myreflink{linearfitxy} | \myreflink{magic} | \myreflink{mat2ds} | \myreflink{mat2grid} | \myreflink{mat2img} |
64+
| \myreflink{mosaic} | \myreflink{ODE2ds} | \myreflink{orbits} | \myreflink{pca} | \myreflink{plotgrid!} | \myreflink{plotyy} | \myreflink{pol2cart} | \myreflink{polygonlevels} |
65+
| \myreflink{rasterzones!} | \myreflink{regiongeog} | \myreflink{remotegrid} | \myreflink{rescale} | \myreflink{slicecube} | \myreflink{sph2cart} | \myreflink{stackgrids} | \myreflink{ter2cart} |
66+
| \myreflink{theme} | \myreflink{uniqueind} | \myreflink{vecangles} | \myreflink{whereami} | \myreflink{worldrectgrid} | \myreflink{worldrectcoast} | \myreflink{worldrectangular} | \myreflink{xyzw2cube} |
67+
| \myreflink{yeardecimal} | \myreflink{zonal_stats} | | | | | | |
6768

6869
## Solids functions
6970

documentation/modules/scatter.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,16 @@ Optional Arguments
3333
Take the vector `xx` (same size as number os points in data) and interpolate the current color scale to paint the
3434
symbols based on that color scale. The form `zcolor=true` is equivant to *zcolor=1:npoints*
3535

36-
- **S** or *symbol* or *marker* or *Marker* or *shape* : -- Default is `circle` with a diameter of 7 points
36+
- **S** or **symbol** or **marker** or **Marker** or **shape** : -- Default is `circle` with a diameter of 7 points
3737
- *symbol=symbol* string\
3838
A full GMT compact string.
3939
- *symbol=(symb=??, size=??, unit=??)*\
4040
Where *symb* is one \myreflink{Symbols} like `:circle`, *size* is symbol size in cm, unless *unit*
4141
is specified i.e. `:points`
4242

43-
In alternative to the `symbol keyword, user can select the symbol name with either `marker or `shape
43+
In alternative to the `symbol` keyword, user can select the symbol name with either `marker` or `shape`
4444
and symbol size with `markersize` or `ms`. The value of these keywords can be either numeric
45-
(symb meaning size in cm) or string if an unit is appended, *e.g.* markersize="5p"` This form of symbol
45+
(symb meaning size in cm) or string if an unit is appended, *e.g.* `markersize="5p"` This form of symbol
4646
selection allows also to specify a variable symbol size. All it's need for this is that the keyword's value
4747
be an array with the same number of elements as the number of data points.
4848

documentation/utilities/findpeaks.md

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# findpeaks
2+
3+
```
4+
findpeaks(y, x=1:length(y); min_height=minimum(y), min_prom=minimum(y), min_dist=0, threshold=0)
5+
or
6+
7+
findpeaks(D::GMTdataset; min_height=D.bbox[1], min_prom=zero(D[1]), min_dist=0, threshold=0)
8+
```
9+
10+
Returns indices of local maxima (sorted from highest peaks to lowest) in 1D array of real numbers.
11+
Similar to MATLAB's findpeaks().
12+
13+
A local peak is a data sample that is either larger than its two neighboring samples or is equal to Inf.
14+
The peaks are output in order of occurrence. This function is from the [Findpeaks.jl](https://github.com/tungli/Findpeaks.jl) package.
15+
16+
### Args
17+
- `y`: Input data, specified as a vector. `y` must be real and must have at least three elements.
18+
19+
- `x`: Locations, specified as a vector or a datetime array. `x` must increase monotonically and have the
20+
same length as `y`. If `x` is omitted, then the indices of `y` are used as locations.
21+
22+
- `D`: Alternatively to `y` and `x` you can provide a `GMTdataset` with two, `x,y` (or more), columns.
23+
24+
### Kwargs
25+
- `min_height`: Minimum peak height, specified as a real scalar. Use this argument to have
26+
``findpeaks`` return only those peaks higher than `min_height`.
27+
28+
- `min_prom`: Minimum peak prominence, specified as a nonnegative real scalar. Use this
29+
argument to have ``findpeaks`` return only those peaks that have a relative importance of at least
30+
`min_prom` (see [Prominence](https://www.mathworks.com/help/signal/ref/findpeaks.html#buff2uu)).
31+
32+
- `min_dist`: Minimum peak separation (keeping highest peaks). When you specify a value for this option,
33+
the algorithm chooses the tallest peak and ignores all peaks within `min_dist` of it.
34+
35+
- `threshold`: Minimal difference (absolute value) between peak and neighboring points. Use this argument to have
36+
``findpeaks`` return only those peaks that exceed their immediate neighboring values by at least the value of `threshold`.
37+
38+
### Returns
39+
- `peaks`: A vector of indices of local maxima (sorted from highest peaks to lowest).
40+
41+
### Examples
42+
43+
\begin{examplefig}{}
44+
```julia
45+
using GMT
46+
47+
D = gmtread(TESTSDIR * "assets/example_spectrum.txt");
48+
peaks = findpeaks(D, min_prom=1000.);
49+
50+
plot(D, title="Prominent peaks")
51+
scatter!(D[peaks,:], mc=:red, show=true)
52+
```
53+
\end{examplefig}
54+
55+
\begin{examplefig}{}
56+
```julia
57+
using GMT
58+
59+
D = gmtread(TESTSDIR * "assets/example_spectrum.txt");
60+
peaks = findpeaks(D, min_dist=0.2)
61+
62+
plot(D, title="Peaks at least 0.2 units apart")
63+
scatter!(D[peaks,:], mc=:red, show=true)
64+
```
65+
\end{examplefig}

documentation/utilities/hampel.md

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# hampel
2+
3+
```
4+
hampel(x; spread=mad(x), threshold=2)
5+
```
6+
7+
Identify outliers using the Hampel criterion.
8+
9+
Given vector `x`, identify elements xₖ such that
10+
11+
```math
12+
|xₖ - m| > t S,
13+
```
14+
15+
where ``m`` is the median of the elements, the dispersion scale ``S`` is provided by the function
16+
`spread`, and the parameter ``t`` is given by `threshold`. The return value is a `Bool` vector.
17+
18+
By default, `spread` is \myreflink{mad} and `threshold` is 2.
19+
20+
21+
---------
22+
23+
```
24+
hampel(x, K; spread=mad, threshold=2, boundary=:truncate)
25+
```
26+
27+
Apply a windowed Hampel filter to a time series.
28+
29+
Given vector `x` and half-width `K`, apply a Hampel criterion within a sliding window of width
30+
2K+1. The median ``m`` of the window replaces the element ``xₖ`` at the center of the window if it satisfies
31+
32+
```math
33+
|xₖ - m| > t S,
34+
```
35+
36+
where the dispersion scale ``S`` is provided by the function `spread` and the parameter
37+
``t`` is given by `threshold`. The window shortens near the beginning and end of the vector
38+
to avoid referencing fictitious elements. Larger values of ``t`` make the filter less agressive,
39+
while ``t=0`` is the standard median filter.
40+
41+
For recursive filtering, see `hampel!`
42+
43+
The value of `boundary` determines how the filter handles the boundaries of the vector:
44+
45+
- `:truncate` (default): the window is shortened at the boundaries
46+
- `:reflect`: values are reflected across the boundaries
47+
- `:repeat`: end values are repeated as necessary
48+
49+
---------
50+
51+
```
52+
hampel(x, weights; ...)
53+
```
54+
55+
Apply a weighted Hampel filter to a time series.
56+
57+
Given vector `x` and a vector `weights` of positive intgers, before computing the criterion
58+
each element in the window is repeated by the number of times given by its corresponding
59+
weight. This is typically used to make the central element more influential than the others.
60+
61+
62+
### CREDITS
63+
This function is adapted from [HampelOutliers.jl](https://github.com/tobydriscoll/HampelOutliers.jl) and you should
64+
consult the original source for more details and examples. The differences with respect to original
65+
`HampelOutliers.jl` functions is that here we created different methods for `Hampel.identify` and
66+
`Hampel.filter` and called them collectively just ``hampel`` and let the multi-dispatch do the work.
67+
68+
### Returns
69+
- A vector of Boolean saying if points were considered _regular_ or outliers.
70+
or
71+
- A filtered version of `x`
72+
73+
### Example
74+
75+
\begin{examplefig}{}
76+
```julia
77+
using GMT
78+
79+
t = (1:50) / 10;
80+
x = [1:2:40; 5t + (@. 6cos(t + 0.5(t)^2)); fill(40,20)];
81+
x[12] = -10; x[50:52] .= -12; x[79:82] .= [-5, 50, 55, 0];
82+
m = hampel(x, 4, threshold=0);
83+
y = hampel(x, 4);
84+
85+
plot(x, marker=:point, mc=:blue, lc=:blue, label="Original", xlabel="k", ylabel="x_k")
86+
scatter!(m, ms="2p", mc=:red, MarkerEdgeColor=true, label="Median filter")
87+
scatter!(y, ms="2p", mc=:green, MarkerEdgeColor=true, label="Hampel filter", show=true)
88+
```
89+
\end{examplefig}

0 commit comments

Comments
 (0)