@@ -354,6 +354,47 @@ def mae(self, other: PhononDos, two_sided: bool = True) -> float:
354354
355355 return self_mae
356356
357+ def get_last_peak (self , threshold : float = 0.1 ) -> float :
358+ """Find the last peak in the phonon DOS defined as the highest frequency with a DOS
359+ value at least threshold * height of the overall highest DOS peak.
360+ A peak is any local maximum of the DOS as a function of frequency.
361+ Use dos.get_interpolated_value(peak_freq) to get density at peak_freq.
362+
363+ TODO method added by @janosh on 2023-12-18. seems to work well in most cases but
364+ was not extensively tested. PRs with improvements welcome!
365+
366+ Args:
367+ threshold (float, optional): Minimum ratio of the height of the last peak
368+ to the height of the highest peak. Defaults to 0.1 = 10%. In case no peaks
369+ are high enough to match, the threshold is reset to half the height of the
370+ second-highest peak.
371+
372+ Returns:
373+ float: last DOS peak frequency (in THz)
374+ """
375+ first_deriv = np .gradient (self .densities , self .frequencies )
376+ second_deriv = np .gradient (first_deriv , self .frequencies )
377+
378+ maxima = ( # maxima indices of the first DOS derivative w.r.t. frequency
379+ (first_deriv [:- 1 ] > 0 ) & (first_deriv [1 :] < 0 ) & (second_deriv [:- 1 ] < 0 )
380+ )
381+ # get mean of the two nearest frequencies around the maximum as better estimate
382+ maxima_freqs = (self .frequencies [:- 1 ][maxima ] + self .frequencies [1 :][maxima ]) / 2
383+
384+ # filter maxima based on the threshold
385+ max_dos = max (self .densities )
386+ threshold = threshold * max_dos
387+ filtered_maxima_freqs = maxima_freqs [self .densities [:- 1 ][maxima ] >= threshold ]
388+
389+ if len (filtered_maxima_freqs ) == 0 :
390+ # if no maxima reach the threshold (i.e. 1 super high peak and all other peaks
391+ # tiny), use half the height of second highest peak as threshold
392+ second_highest_peak = sorted (self .densities )[- 2 ]
393+ threshold = second_highest_peak / 2
394+ filtered_maxima_freqs = maxima_freqs [self .densities [:- 1 ][maxima ] >= threshold ]
395+
396+ return max (filtered_maxima_freqs )
397+
357398
358399class CompletePhononDos (PhononDos ):
359400 """This wrapper class defines a total dos, and also provides a list of PDos.
0 commit comments