{"id":477322,"date":"2026-04-24T20:05:28","date_gmt":"2026-04-24T20:05:28","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=477322"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=477322","title":{"rendered":"\u0412\u0441\u0435 \u043e\u0431 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435 WSPR \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438 \u043d\u0430 Python (\u0447\u0430\u0441\u0442\u044c 2)"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3c9\/124\/1ec\/3c91241ec4e70a77362d143abc714a5d.png\" width=\"1280\" height=\"632\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/3c9\/124\/1ec\/3c91241ec4e70a77362d143abc714a5d.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3c9\/124\/1ec\/3c91241ec4e70a77362d143abc714a5d.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>WSPR \u2014 \u0446\u0438\u0444\u0440\u043e\u0432\u043e\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b\u0439 \u0414\u0436\u043e \u0422\u0435\u0439\u043b\u043e\u0440\u043e\u043c (K1JT) \u0432 2008-2009 \u0433\u043e\u0434\u0430\u0445, \u0441 \u0446\u0435\u043b\u044c\u044e \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0440\u0430\u0434\u0438\u043e\u0441\u0438\u0433\u043d\u0430\u043b\u043e\u0432 \u043e\u0442 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0432\u043e\u043b\u043d\u043e\u0432\u044b\u0445 \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u0447\u0438\u043a\u043e\u0432 \u043c\u0430\u043b\u043e\u0439 \u0438 \u0441\u0432\u0435\u0440\u0445\u043c\u0430\u043b\u043e\u0439 \u043c\u043e\u0449\u043d\u043e\u0441\u0442\u0438. \u0412 <a href=\"https:\/\/habr.com\/en\/articles\/1017728\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0447\u0430\u0441\u0442\u0438<\/a> \u0431\u044b\u043b\u0438 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u044b \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u043f\u043e\u043c\u0435\u0445\u043e\u0437\u0430\u0449\u0438\u0449\u0435\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0435\u0433\u043e \u0432 \u044d\u0444\u0438\u0440. \u0412 \u044d\u0442\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0430\u0442\u044c\u0438 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0434\u0435\u0442\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u043c\u043e\u0433\u043e \u0438\u0437 \u0441\u0438\u0433\u043d\u0430\u043b\u0430.<\/p>\n<p>\u0421\u0442\u0430\u0442\u044c\u044f \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430 \u0440\u0430\u0434\u0438\u043e\u043b\u044e\u0431\u0438\u0442\u0435\u043b\u044f\u043c, \u043a\u0430\u043a \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u043c, \u0442\u0430\u043a \u0438 \u043d\u0435 \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u043c \u0441 WSPR, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0442\u0435\u043c, \u043a\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442\u0441\u044f \u0442\u0435\u043c\u043e\u0439 \u0446\u0438\u0444\u0440\u043e\u0432\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u043e\u0432 \u0438 \u0445\u043e\u0447\u0435\u0442 \u043f\u043e\u043d\u044f\u0442\u044c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430.<\/p>\n<h2>\u041e\u0431\u0449\u0435\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0431\u044b\u043b\u0438 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u044b \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u044b \u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b, \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u0430.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b06\/154\/4e0\/b061544e0c85381fb46a226e5966465a.png\" alt=\"\u0420\u0438\u0441\u0443\u043d\u043e\u043a 1: \u041e\u0431\u0449\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 (\u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u044f \u043f\u043e \u0443\u0440\u043e\u0432\u043d\u044f\u043c OSI \u0443\u0441\u043b\u043e\u0432\u043d\u0430\u044f).\" title=\"\u0420\u0438\u0441\u0443\u043d\u043e\u043a 1: \u041e\u0431\u0449\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 (\u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u044f \u043f\u043e \u0443\u0440\u043e\u0432\u043d\u044f\u043c OSI \u0443\u0441\u043b\u043e\u0432\u043d\u0430\u044f).\" width=\"472\" height=\"565\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/b06\/154\/4e0\/b061544e0c85381fb46a226e5966465a.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b06\/154\/4e0\/b061544e0c85381fb46a226e5966465a.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0420\u0438\u0441\u0443\u043d\u043e\u043a 1: \u041e\u0431\u0449\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 (\u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u044f \u043f\u043e \u0443\u0440\u043e\u0432\u043d\u044f\u043c OSI \u0443\u0441\u043b\u043e\u0432\u043d\u0430\u044f).<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0434\u0435\u0442\u0435\u043a\u0446\u0438\u0438 \u0438 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e \u0441\u0432\u043e\u0435\u0439 \u0441\u0443\u0442\u0438 \u0434\u0438\u0430\u043c\u0435\u0442\u0440\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0442\u0438\u0432\u043e\u043f\u043e\u043b\u043e\u0436\u0435\u043d \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0443 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u041e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u044b\u0439 \u0441\u0438\u0433\u043d\u0430\u043b \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0432\u0435\u0440\u0433\u0430\u0435\u0442\u0441\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438 \u0434\u0430\u0443\u043d\u0441\u0435\u043c\u043f\u043b\u0438\u043d\u0433\u0443 \u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438 \u0432 \u0447\u0430\u0441\u0442\u043e\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0432\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 (\u0434\u043b\u044f \u0447\u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u044b), \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0437\u0432\u043b\u0435\u0447\u044c \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u0434\u0430\u043d\u043d\u044b\u0445; \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u0437\u0430\u0442\u0435\u043c \u043f\u043e\u0434\u0432\u0435\u0440\u0433\u0430\u044e\u0442\u0441\u044f \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u0441 \u043a\u043e\u0440\u0440\u0435\u043a\u0446\u0438\u0435\u0439 \u043e\u0448\u0438\u0431\u043e\u043a, \u0447\u0442\u043e \u0443\u0436\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u043e\u0435 WSPR-\u043c\u0430\u044f\u043a\u043e\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435.<\/p>\n<h2>\u041f\u0435\u0440\u0435\u043d\u043e\u0441 \u0441\u043f\u0435\u043a\u0442\u0440\u0430 \u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f<\/h2>\n<p>\u0412\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0437\u0432\u0443\u043a\u043e\u0432\u043e\u0439 \u0441\u0438\u0433\u043d\u0430\u043b \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432 WSPR \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u0441 \u0447\u0430\u0441\u0442\u043e\u0442\u043e\u0439 \u0434\u0438\u0441\u043a\u0440\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u0438 12.0 \u043a\u0413\u0446, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u043e\u0442\u0430 \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f \u0432 \u0437\u043e\u043d\u0435 1.5 \u043a\u0413\u0446; \u0442\u0430\u043a \u043a\u0430\u043a \u0441\u0438\u0433\u043d\u0430\u043b \u043d\u0430\u043a\u0430\u043f\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0438 110 \u0441\u0435\u043a\u0443\u043d\u0434, \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043e\u0431\u044a\u0435\u043c \u0437\u0432\u0443\u043a\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0443\u0436\u043d\u0430 \u043f\u043e\u043b\u043e\u0441\u0430 \u0448\u0438\u0440\u0438\u043d\u043e\u0439 <code>self.sample_rate \/ WSPR_DECIMATION<\/code> = 12000 \/ 32 = 375 \u0413\u0446, \u0432\u0441\u0451 \u0447\u0442\u043e \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u043c\u0438 \u044d\u0442\u043e\u0439 \u043f\u043e\u043b\u043e\u0441\u044b \u2014 \u0431\u0435\u0441\u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0439 \u0448\u0443\u043c.<\/p>\n<p>\u0414\u0430\u0443\u043d\u0441\u0435\u043c\u043f\u043b\u0438\u043d\u0433 \u0438 \u0434\u0435\u0446\u0438\u043c\u0430\u0446\u0438\u044f \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0432 WSPR \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432 \u0447\u0430\u0441\u0442\u043e\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u044f\u043c\u043e\u0435 \u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0424\u0443\u0440\u044c\u0435.<\/p>\n<pre><code class=\"python\">WSPR_DECIMATION = 32WSPR_CENTER_FREQ = 1500class WSPRMonitor(AbstractMonitor):    __slots__ = [        \"sample_rate\",        \"signal\",        ...    ]    def __init__(self, sample_rate: int):        self.signal = np.zeros(0, dtype=np.float64)        self.sample_rate = sample_rate        ...    def downsample(self) -&gt; npt.NDArray[np.complex128]:        fft_target = 46080        fft_src = fft_target * WSPR_DECIMATION        frame = np.pad(self.signal[:fft_src], (0, max(0, fft_src - len(self.signal))))        spec = np.fft.rfft(frame)        df = self.sample_rate \/ fft_src        i0 = int(WSPR_CENTER_FREQ \/ df + 0.5)        sub_spec = spec[i0: i0 + fft_target]        signal = np.fft.ifft(sub_spec) * (fft_target \/ fft_src) * 2        return signal.astype(np.complex128)    ...    def monitor_process(self, frame: npt.NDArray[np.int16]) -&gt; None:        frame_float = frame.astype(np.float32) \/ np.iinfo(np.int16).max        self.signal = np.concat([self.signal, frame_float])    ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u043b\u0435 <code>sample_rate<\/code> \u0445\u0440\u0430\u043d\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0447\u0430\u0441\u0442\u043e\u0442\u0435 \u0434\u0438\u0441\u043a\u0440\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u0441\u0438\u0433\u043d\u0430\u043b\u0430, \u0432 <code>signal<\/code> \u043d\u0430\u043a\u0430\u043f\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u0430\u043c\u043e\u0433\u043e \u0441\u0438\u0433\u043d\u0430\u043b\u0430.<\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>downsample<\/code> \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442 \u043f\u0435\u0440\u0435\u043d\u043e\u0441 \u0441\u043f\u0435\u043a\u0442\u0440\u0430 \u0438\u0437 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0432\u044b\u0441\u043e\u043a\u0438\u0445 \u0447\u0430\u0441\u0442\u043e\u0442 \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u043d\u0438\u0437\u043a\u0438\u0445, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044f \u0434\u0435\u0446\u0438\u043c\u0430\u0446\u0438\u044e \u0441\u0438\u0433\u043d\u0430\u043b\u0430.<\/p>\n<p>\u0412 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e <code>spec<\/code> \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0424\u0443\u0440\u044c\u0435 \u0434\u043b\u044f \u0432\u0435\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u0430.<\/p>\n<blockquote>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435: \u0442\u043e \u0435\u0441\u0442\u044c \u0432 \u0441\u043f\u0435\u043a\u0442\u0440\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u043e\u0442\u044b, \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0441 \u043e\u0442\u0440\u0438\u0446\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u0447\u0430\u0441\u0442\u043e\u0442\u0430\u043c\u0438 \u0437\u0435\u0440\u043a\u0430\u043b\u044c\u043d\u043e \u0441\u0438\u043c\u043c\u0435\u0442\u0440\u0438\u0447\u043d\u0430 \u0438 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f (\u0440\u0438\u0441\u0443\u043d\u043e\u043a 2).<\/em><\/p>\n<\/blockquote>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ac0\/38e\/4a2\/ac038e4a2b1308c0e7bb095307a1c893.png\" alt=\"\u0420\u0438\u0441\u0443\u043d\u043e\u043a 2: \u043e\u0442\u043b\u0438\u0447\u0438\u0435 FFT \u0438 RFFT\" title=\"\u0420\u0438\u0441\u0443\u043d\u043e\u043a 2: \u043e\u0442\u043b\u0438\u0447\u0438\u0435 FFT \u0438 RFFT\" width=\"1186\" height=\"957\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/ac0\/38e\/4a2\/ac038e4a2b1308c0e7bb095307a1c893.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ac0\/38e\/4a2\/ac038e4a2b1308c0e7bb095307a1c893.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0420\u0438\u0441\u0443\u043d\u043e\u043a 2: \u043e\u0442\u043b\u0438\u0447\u0438\u0435 FFT \u0438 RFFT<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f <code>df<\/code> \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0446\u0435\u043b\u0435\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u043e\u0442\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0424\u0443\u0440\u044c\u0435-\u0431\u0438\u043d\u043e\u0432 \u043f\u043e\u0441\u043b\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f <code>i0<\/code> \u0437\u0430\u0434\u0430\u0435\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0444\u0438\u043b\u044c\u0442\u0440\u0430 \u0432 \u0447\u0430\u0441\u0442\u043e\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438, \u2014 \u0438\u043d\u0434\u0435\u043a\u0441 \u0447\u0430\u0441\u0442\u043e\u0442\u043d\u043e\u0433\u043e \u0431\u0438\u043d\u0430 \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u043c \u0441\u043f\u0435\u043a\u0442\u0440\u0435, \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u043e\u0441\u0430 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u043d\u0438\u044f; \u043f\u043e\u043b\u043e\u0441\u0430 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u043d\u0438\u044f \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c <code>fft_target<\/code>.<\/p>\n<p>\u041c\u0430\u0441\u0441\u0438\u0432 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 <code>sub_spec<\/code> \u2014 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u043d\u043d\u044b\u0439 \u0438 \u043e\u0442\u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u043e \u0447\u0430\u0441\u0442\u043e\u0442\u0435 \u0441\u043f\u0435\u043a\u0442\u0440 \u0441\u0438\u0433\u043d\u0430. \u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u0438\u0437 \u0447\u0430\u0441\u0442\u043e\u0442\u043d\u043e\u0439 \u0432\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u044b\u043c \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0424\u0443\u0440\u044c\u0435; \u0441\u0438\u0433\u043d\u0430\u043b \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0432\u0435\u0440\u0433\u0430\u0435\u0442\u0441\u044f \u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0430\u043c\u043f\u043b\u0438\u0442\u0443\u0434 (AGC).<\/p>\n<p>\u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0424\u0443\u0440\u044c\u0435, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0441\u0438\u0433\u043d\u0430\u043b \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u043a\u043e\u043c\u043f\u043b\u0435\u043a\u0441\u043d\u044b\u0445 \u0447\u0438\u0441\u0435\u043b, \u2014 \u0442\u043e \u0435\u0441\u0442\u044c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0441\u0438\u0433\u043d\u0430\u043b \u0432 I\/Q \u0444\u043e\u0440\u043c\u0435 <img decoding=\"async\" class=\"formula inline\" source=\"z(t) = I(t) + jQ(t)\" alt=\"z(t) = I(t) + jQ(t)\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/5\/57\/572\/572f4ee784303a352f9ac647b5768dab.svg\" width=\"144\" height=\"16\" data-width=\"18.428\" data-height=\"2.262\" data-vertical-align=\"-0.566\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/5\/57\/572\/572f4ee784303a352f9ac647b5768dab.svg 780w,&#10;       https:\/\/habrastorage.org\/getpro\/habr\/formulas\/5\/57\/572\/572f4ee784303a352f9ac647b5768dab.svg 781w\" loading=\"lazy\" decode=\"async\"\/> (\u0447\u0442\u043e \u044d\u043a\u0432\u0438\u0432\u0430\u043b\u0435\u043d\u0442\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u0438 \u042d\u0439\u043b\u0435\u0440\u0430 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 \u043a\u043e\u043c\u043f\u043b\u0435\u043a\u0441\u043d\u043e\u0439 \u044d\u043a\u0441\u043f\u043e\u043d\u0435\u043d\u0442\u044b <img decoding=\"async\" class=\"formula inline\" source=\"s(t) = A(t) e^{j\\phi(t)}\" alt=\"s(t) = A(t) e^{j\\phi(t)}\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/5\/51\/514\/51448eb8f87b917d01224fff48e37c01.svg\" width=\"120\" height=\"16\" data-width=\"15.606\" data-height=\"2.7\" data-vertical-align=\"-0.784\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/5\/51\/514\/51448eb8f87b917d01224fff48e37c01.svg 780w,&#10;       https:\/\/habrastorage.org\/getpro\/habr\/formulas\/5\/51\/514\/51448eb8f87b917d01224fff48e37c01.svg 781w\" loading=\"lazy\" decode=\"async\"\/>).<\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043f\u0435\u0440\u0435\u043d\u043e\u0441 \u0441\u043f\u0435\u043a\u0442\u0440\u0430 \u0438 \u0434\u0430\u0443\u043d\u0441\u0435\u043c\u043f\u043b\u0438\u043d\u0433 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0438\u0442\u044c \u0434\u0435\u0446\u0438\u043c\u0430\u0446\u0438\u044e \u0431\u0435\u0437 \u043f\u043e\u0442\u0435\u0440\u044c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u043d\u044c\u0448\u0443\u044e \u0447\u0430\u0441\u0442\u043e\u0442\u0443 \u0434\u0438\u0441\u043a\u0440\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u0438, \u0447\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u0442 \u043e\u0431\u044a\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0445, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u043c\u0435\u043d\u044c\u0448\u0435\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0438 \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u0441\u0438\u0433\u043d\u0430\u043b\u0430; \u0442\u0430\u043a\u0436\u0435 \u0432 \u0447\u0430\u0441\u0442\u043e\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0432\u044b\u0441\u043e\u043a\u043e\u0447\u0430\u0441\u0442\u043e\u0442\u043d\u044b\u0445 \u0438 \u0432\u043d\u0435\u043f\u043e\u043b\u043e\u0441\u043d\u044b\u0445 \u0448\u0443\u043c\u043e\u0432, \u0447\u0442\u043e \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u043b\u0438\u044f\u0435\u0442 \u043d\u0430 SNR.<\/p>\n<h2>\u0414\u0435\u0442\u0435\u043a\u0446\u0438\u044f \u0441\u0438\u0433\u043d\u0430\u043b\u0430<\/h2>\n<p>\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 \u0435\u0433\u043e \u0434\u0435\u0442\u0435\u043a\u0446\u0438\u0438. \u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>decode<\/code> \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u00a0 I\/Q \u0441\u0438\u0433\u043d\u0430\u043b \u043f\u043e\u0441\u043b\u0435 \u0434\u0430\u0443\u043d\u0441\u0435\u043c\u043f\u043b\u0438\u043d\u0433\u0430.<\/p>\n<pre><code class=\"python\">class WSPRMonitor(AbstractMonitor):    __slots__ = [        ...        \"symbol_len\",        \"df\",        \"df2\",        \"dt\",        \"decode_passes\",        ...    ]    ...    def __init__(self, sample_rate: int):        ...        down_sample_rate = self.sample_rate \/ WSPR_DECIMATION        self.symbol_len = int(down_sample_rate * WSPR_SYMBOL_PERIOD)        self.df = down_sample_rate \/ self.symbol_len        self.df2 = self.df \/ 2        self.dt = 1 \/ down_sample_rate        self.decode_passes = 3        ...    def decode(self, **kwargs) -&gt; typing.Iterator[WSPRLogItem]:        iq_signal = self.downsample()        symbols = np.zeros(WSPR_NUM_BITS * 2, dtype=np.uint8)        fft_step = 128        fft_size = fft_step * 4        fft_count = 4 * (len(iq_signal) \/\/ fft_size) - 1        smooth = np.sin((np.pi \/ fft_size) * np.arange(fft_size))        pwr_spec = np.zeros((fft_count, fft_size))        block_size = 1        max_drift = 4        min_sync_2 = WSPR_MIN_SYNC_2        decodes_pass = 0        ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442\u0441\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0441\u043f\u0435\u043a\u0442\u0440\u0430 I\/Q \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u2014 <code>fft_step<\/code>, <code>fft_size<\/code>, <code>fft_count<\/code>. \u041f\u043e\u0434\u0433\u043e\u0442\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u0433\u043b\u0430\u0436\u0438\u0432\u0430\u044e\u0449\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043e\u043a\u043e\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0424\u0443\u0440\u044c\u0435.<\/p>\n<blockquote>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435: \u0432\u043c\u0435\u0441\u0442\u043e \u043e\u043a\u043d\u0430 \u0425\u0430\u043d\u043d\u0430 \u0421\u0442\u0438\u0432 \u0424\u0440\u0430\u043d\u043a\u0438 (K9AN) \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043b \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u043b\u0443\u043f\u0435\u0440\u0438\u043e\u0434 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0441\u0438\u043d\u0443\u0441. \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0425\u0430\u043d\u043d\u0430, \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0441\u0438\u043d\u0443\u0441 \u0447\u0443\u0442\u044c \u0445\u0443\u0436\u0435 \u043f\u043e\u0434\u0430\u0432\u043b\u044f\u0435\u0442 \u0431\u043e\u043a\u043e\u0432\u044b\u0435 \u043b\u0435\u043f\u0435\u0441\u0442\u043a\u0438 \u0432 \u0441\u043f\u0435\u043a\u0442\u0440\u0435.<\/em><\/p>\n<\/blockquote>\n<pre><code class=\"python\">WSPR_MIN_SYNC_1 = 0.10WSPR_MIN_SYNC_2 = 0.12...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b <code>WSPR_MIN_SYNC_1<\/code>, <code>WSPR_MIN_SYNC_2<\/code> \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d\u0438\u044f \u0447\u0430\u0441\u0442\u043e\u0442\u044b \u043f\u0440\u0438 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0446\u0438\u043a\u043b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u0430:<\/p>\n<pre><code class=\"python\">        ...        for iteration in range(self.decode_passes):            if iteration == 1 and decodes_pass == 0 and self.decode_passes &gt; 2:                iteration = 2            if iteration == 2:                block_size = 4                max_drift = 0                min_sync_2 = WSPR_MIN_SYNC_1            decodes_pass = 0        ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h2>\u0423\u0441\u0440\u0435\u0434\u043d\u0435\u043d\u0438\u0435 \u0441\u043f\u0435\u043a\u0442\u0440\u0430<\/h2>\n<p>\u0412 WSPR \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u043c\u044b\u0435 \u0441\u0438\u0433\u043d\u0430\u043b\u044b \u043c\u043e\u0433\u0443\u0442 \u0438\u043c\u0435\u0442\u044c \u043e\u0447\u0435\u043d\u044c \u043d\u0438\u0437\u043a\u0438\u0439 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c SNR, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0438\u0445 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435\u0432\u0438\u0434\u0438\u043c\u044b\u043c\u0438. \u0412 WSPR \u0434\u043b\u044f \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0441\u043b\u0430\u0431\u044b\u0445 \u0441\u0438\u0433\u043d\u0430\u043b\u043e\u0432 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0443\u0441\u0440\u0435\u0434\u043d\u0435\u043d\u0438\u044f \u0441\u043f\u0435\u043a\u0442\u0440\u0430 \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445. \u0422\u0430\u043a \u043a\u0430\u043a \u0448\u0443\u043c \u0432 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u0441\u043b\u0443\u0447\u0430\u0435\u0432 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u043c, \u0441 \u043d\u0443\u043b\u0435\u0432\u044b\u043c \u043c\u0430\u0442. \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0435\u043c \u0438 \u043d\u0435 \u043a\u043e\u0440\u0440\u0435\u043b\u0438\u0440\u0443\u0435\u0442 \u0434\u0440\u0443\u0433 \u0441 \u0434\u0440\u0443\u0433\u043e\u043c, \u0430 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0439 \u0441\u0438\u0433\u043d\u0430\u043b \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u043e\u0442\u0435 \u0438 \u0438\u043c\u0435\u0435\u0442 \u043d\u0435\u0440\u0430\u0437\u0440\u044b\u0432\u043d\u0443\u044e \u0444\u0430\u0437\u0443, \u0442\u043e \u043f\u0440\u0438 \u0441\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0441\u043f\u0435\u043a\u0442\u0440\u043e\u0432 \u043c\u043e\u0449\u043d\u043e\u0441\u0442\u044c \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u0442\u0438 \u043b\u0438\u043d\u0435\u0439\u043d\u043e, \u0432 \u0442\u0430\u043a\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u0440\u0430\u0437, \u043a\u0440\u0430\u0442\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0443 \u0443\u0441\u0440\u0435\u0434\u043d\u0435\u043d\u0438\u0439, \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u0441\u043f\u0435\u043a\u0442\u0440 \u0448\u0443\u043c\u0430 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u0442\u0438 \u043f\u043e \u0437\u0430\u043a\u043e\u043d\u0443 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0445 \u0431\u043b\u0443\u0436\u0434\u0430\u043d\u0438\u0439, \u2014 \u043f\u0440\u043e\u043f\u043e\u0440\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u043d\u043e\u043c\u0443 \u043a\u043e\u0440\u043d\u044e \u0438\u0437 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0443\u0441\u0440\u0435\u0434\u043d\u0435\u043d\u0438\u0439 (<img decoding=\"async\" class=\"formula inline\" source=\"\\sqrt n\" alt=\"\\sqrt n\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/4\/43\/43b\/43b78eed6b394a9337b90c2a4cbd7f55.svg\" width=\"24\" height=\"16\" data-width=\"3.287\" data-height=\"2.581\" data-vertical-align=\"-0.725\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/4\/43\/43b\/43b78eed6b394a9337b90c2a4cbd7f55.svg 780w,&#10;       https:\/\/habrastorage.org\/getpro\/habr\/formulas\/4\/43\/43b\/43b78eed6b394a9337b90c2a4cbd7f55.svg 781w\" loading=\"lazy\" decode=\"async\"\/>).<\/p>\n<p>\u041d\u0430 \u0440\u0438\u0441\u0443\u043d\u043a\u0435 3 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u043f\u0440\u0438\u043c\u0435\u0440 \u0443\u0441\u0440\u0435\u0434\u043d\u0435\u043d\u0438\u044f \u0441\u043f\u0435\u043a\u0442\u0440\u0430 \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0432 \u043a\u0430\u043d\u0430\u043b\u0435 \u0441 \u0430\u0434\u0434\u0438\u0442\u0438\u0432\u043d\u044b\u043c \u0413\u0430\u0443\u0441\u0441\u043e\u0432\u0441\u043a\u0438\u043c \u0448\u0443\u043c\u043e\u043c \u043f\u0440\u0438 \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\/\u0448\u0443\u043c SNR=-30 \u0434\u0411. \u041d\u0430 \u043f\u0435\u0440\u0432\u043e\u043c \u0433\u0440\u0430\u0444\u0438\u043a\u0435 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0447\u0430\u0441\u0442\u043e\u0442\u043e\u0439 1.0 \u043a\u0413\u0446 (\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u0441\u043f\u0435\u043a\u0442\u0440\u0435 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043e \u043a\u0440\u0430\u0441\u043d\u044b\u043c \u043f\u0443\u043d\u043a\u0442\u0438\u0440\u043e\u043c) \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 1\u0441, \u043d\u0430 \u0432\u0442\u043e\u0440\u043e \u2014 10\u0441 \u0438 30\u0441 \u043d\u0430 \u0442\u0440\u0435\u0442\u044c\u0435\u043c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e. \u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u0438\u0437 \u0433\u0440\u0430\u0444\u0438\u043a\u043e\u0432, \u043f\u0440\u0438 \u0434\u0435\u0441\u044f\u0442\u0438\u043a\u0440\u0430\u0442\u043d\u043e\u043c \u0443\u0441\u0440\u0435\u0434\u043d\u0435\u043d\u0438\u0438 \u0441\u043f\u0435\u043a\u0442\u0440\u0430, \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0439 \u0441\u0438\u0433\u043d\u0430\u043b \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u043f\u0440\u043e\u044f\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0448\u0443\u043c\u0430, \u0442\u043e \u0435\u0441\u0442\u044c SNR \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0440\u0430\u0441\u0442\u0438. \u041f\u0440\u0438 \u0435\u0449\u0435 \u0431\u043e\u043b\u0435\u0435 \u0434\u043e\u043b\u0433\u043e\u043c \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u0438\u0438 \u0441\u043f\u0435\u043a\u0442\u0440\u0430 \u0441\u0438\u0433\u043d\u0430\u043b \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0435\u0449\u0435 \u0441\u0438\u043b\u044c\u043d\u0435\u0435 \u043f\u0440\u0435\u043e\u0431\u043b\u0430\u0434\u0430\u0442\u044c \u043d\u0430\u0434 \u0448\u0443\u043c\u043e\u043c.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/85f\/696\/bb2\/85f696bb284a70413267319d3c5e8958.png\" alt=\"\u0420\u0438\u0441\u0443\u043d\u043e\u043a 3: \u0412\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0441\u043b\u0430\u0431\u043e\u0433\u043e \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u043f\u0440\u0438 \u0443\u0441\u0440\u0435\u0434\u043d\u0435\u043d\u0438\u0438 \u0441\u043f\u0435\u043a\u0442\u0440\u0430.\" title=\"\u0420\u0438\u0441\u0443\u043d\u043e\u043a 3: \u0412\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0441\u043b\u0430\u0431\u043e\u0433\u043e \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u043f\u0440\u0438 \u0443\u0441\u0440\u0435\u0434\u043d\u0435\u043d\u0438\u0438 \u0441\u043f\u0435\u043a\u0442\u0440\u0430.\" width=\"988\" height=\"968\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/85f\/696\/bb2\/85f696bb284a70413267319d3c5e8958.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/85f\/696\/bb2\/85f696bb284a70413267319d3c5e8958.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0420\u0438\u0441\u0443\u043d\u043e\u043a 3: \u0412\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0441\u043b\u0430\u0431\u043e\u0433\u043e \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u043f\u0440\u0438 \u0443\u0441\u0440\u0435\u0434\u043d\u0435\u043d\u0438\u0438 \u0441\u043f\u0435\u043a\u0442\u0440\u0430.<\/figcaption><\/div>\n<\/figure>\n<pre><code class=\"python\">            ...            for i in range(fft_count):                start = i * fft_step                segment = iq_signal[start: start + fft_size]                if len(segment) &lt; fft_size:                    segment = np.pad(segment, (0, fft_size - len(segment)), mode=\"constant\")                cpx_spec = np.fft.fft(segment * smooth)                cpx_spec = np.fft.fftshift(cpx_spec)                pwr_spec[i, :] = np.abs(cpx_spec) ** 2            pwr_spec_avg = np.mean(pwr_spec, axis=0) * fft_count            center = fft_size \/\/ 2            span = 205            relevant_part = pwr_spec_avg[center - span: center + span + 1]            smooth_spec = np.convolve(relevant_part, WSPR_SMOOTH_KERNEL, mode=\"same\")            noise_level = np.percentile(smooth_spec, WSPR_NOISE_PERCENTILE)            min_snr = np.pow(10.0, -8.0 \/ 10.0)            smooth_spec = smooth_spec \/ noise_level - 1.0            smooth_spec[smooth_spec &lt; min_snr] = 0.1 * min_snr            ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0418\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u0442\u043e\u0433\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u044f, \u0447\u0442\u043e \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043e\u0434\u043d\u043e\u0433\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u0430 WSPR \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 0.6827 \u0441, \u0434\u0435\u043c\u043e\u0434\u0443\u043b\u044f\u0442\u043e\u0440\u0443, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0443\u0441\u0440\u0435\u0434\u043d\u0435\u043d\u0438\u0435 \u0441\u043f\u0435\u043a\u0442\u0440\u0430, \u0443\u0434\u0430\u0435\u0442\u0441\u044f \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0442\u044c \u0441\u0438\u0433\u043d\u0430\u043b\u044b \u0441 \u043d\u0438\u0437\u043a\u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c SNR.<\/p>\n<h2>\u041f\u043e\u0438\u0441\u043a \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u043e\u0432<\/h2>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u044d\u0442\u0430\u043f \u043f\u043e\u0441\u043b\u0435 \u0443\u0441\u0440\u0435\u0434\u043d\u0435\u043d\u0438\u044f \u0441\u043f\u0435\u043a\u0442\u0440\u0430 \u2014 \u0430\u043d\u0430\u043b\u0438\u0437 \u0430\u043c\u043f\u043b\u0438\u0442\u0443\u0434 \u0432 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u043c \u0441\u043f\u0435\u043a\u0442\u0440\u0435, \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u044e\u0449\u0438\u0439\u0441\u044f \u0432 \u043d\u0430\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0438 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0445 \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c\u043e\u0432 \u0441\u043f\u0435\u043a\u0442\u0440\u0430. \u041a\u0430\u0436\u0434\u044b\u0439 \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u044b\u0439 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u0437\u043d\u0430\u043a\u043e\u043c \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0438\u0441\u043a\u043e\u043c\u043e\u0433\u043e \u0441\u0438\u0433\u043d\u0430\u043b\u0430.<\/p>\n<pre><code class=\"python\">WSPR_SNR_SCALING_FACTOR = 26.3...def dB(x: float) -&gt; float:    val = -99.0    if x &gt; 1.259e-10:        x = max(x, 0.000001)        val = 10.0 * np.log10(x)    return val...@dataclassclass Candidate:    freq: float    snr: float    shift: int = 0    drift: float = 0    sync: float = 0...class WSPRMonitor(AbstractMonitor):    ...    MAX_CANDIDATES = 410    CANDIDATE_FREQ_MIN = -110    CANDIDATE_FREQ_MAX = 110    ...    def find_candidates(self, smooth_spec: npt.NDArray[np.float64]) -&gt; typing.List[Candidate]:        spec_slice = smooth_spec[:self.MAX_CANDIDATES]        is_max = (spec_slice[1:-1] &gt; spec_slice[:-2]) &amp; (spec_slice[1:-1] &gt; spec_slice[2:])        indices = np.where(is_max)[0] + 1        freqs = (indices - 205) * self.df2        mask = (freqs &gt;= self.CANDIDATE_FREQ_MIN) &amp; (freqs &lt;= self.CANDIDATE_FREQ_MAX)        cand_indices = indices[mask]        cand_freqs = freqs[mask]        snrs = [dB(ss) - WSPR_SNR_SCALING_FACTOR for ss in smooth_spec[cand_indices]]        heap = [Candidate(freq=freq, snr=snr) for freq, snr in zip(cand_freqs, snrs)]        heap.sort(key=lambda it: it.snr, reverse=True)        return heap<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>find_candidates<\/code> \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0441\u043f\u0435\u043a\u0442\u0440\u0435 <code>smooth_spec<\/code>, \u043d\u0430\u0445\u043e\u0434\u0438\u0442 \u0432 \u043d\u0435\u043c \u0447\u0430\u0441\u0442\u043e\u0442\u043d\u044b\u0435 \u0431\u0438\u043d\u044b, \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u044f\u044e\u0449\u0438\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0443, \u0447\u0442\u043e \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0435 \u0441\u043b\u0435\u0432\u0430 \u0438 \u0441\u043f\u0440\u0430\u0432\u0430 \u043e\u0442 \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c\u043e\u0433\u043e \u0431\u0438\u043d\u044b \u0438\u043c\u0435\u044e\u0442 \u043c\u0435\u043d\u044c\u0448\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0430\u043c\u043f\u043b\u0438\u0442\u0443\u0434\u044b. \u041c\u0430\u0441\u0441\u0438\u0432 <code>is_max<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0438\u0435 \u043a\u0430\u043a\u043e\u0439 \u0438\u0437 \u0431\u0438\u043d\u043e\u0432 \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u044f\u0435\u0442 \u0443\u0441\u043b\u043e\u0432\u0438\u044e. \u0412 \u043c\u0430\u0441\u0441\u0438\u0432\u044b <code>indices<\/code> \u0438 <code>freqs<\/code> \u043d\u0430\u043a\u0430\u043f\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0447\u0430\u0441\u0442\u043e\u0442 \u0431\u0438\u043d\u043e\u0432-\u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u043e\u0432.\u00a0<\/p>\n<p>\u0414\u043b\u044f <code>cand_indices<\/code> \u0438 <code>cand_freqs<\/code> \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f, \u0438\u0441\u043a\u043b\u044e\u0447\u0430\u044e\u0449\u0430\u044f \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u043e\u0432, \u0447\u0430\u0441\u0442\u043e\u0442\u044b \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u0438\u043b\u044c\u043d\u043e \u043e\u0442\u043a\u043b\u043e\u043d\u044f\u044e\u0442\u0441\u044f \u043e\u0442 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u043e\u0439; \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 <code>cand_indices<\/code> <code>cand_freqs<\/code> \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0434\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u0430 \u0434\u043b\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0421\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d \u043f\u043e \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u0430\u043d\u0438\u044e SNR.<\/p>\n<p>\u0422\u0430\u043a, \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e WSPR \u0441\u0438\u0433\u043d\u0430\u043b\u0430, \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 <a href=\"https:\/\/habr.com\/en\/articles\/1017728\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0447\u0430\u0441\u0442\u0438<\/a>, \u0444\u0443\u043d\u043a\u0446\u0438\u044f find_candidates \u0432\u044b\u0434\u0430\u0441\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:<\/p>\n<pre><code>[Candidate(freq=np.float64(2.197265625), snr=np.float64(43.2654156005124), shift=0, drift=0, sync=0)].<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c\u044b\u0439 \u0441\u0438\u0433\u043d\u0430\u043b \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0448\u0443\u043c\u043e\u0432, \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 SNR \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432\u044b\u0441\u043e\u043a\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435.<\/p>\n<h2>\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f<\/h2>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043d\u0430\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0447\u0430\u0441\u0442\u043e\u0442 \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u043e\u0432 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f. \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0433\u0440\u0443\u0431\u044b\u0439 \u043f\u043e\u0438\u0441\u043a \u043f\u043e \u0447\u0430\u0441\u0442\u043e\u0442\u0435 \u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043a\u0440\u043e\u0441\u0441-\u043a\u043e\u0440\u0440\u0435\u043b\u044f\u0446\u0438\u0438 \u0441 \u0432\u0435\u043a\u0442\u043e\u0440\u043e\u043c \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 <code>WSPR_PR3_SIG<\/code>.<\/p>\n<p>\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d \u043d\u0430 2 \u0441\u0442\u0430\u0434\u0438\u0438: \u0433\u0440\u0443\u0431\u0430\u044f \u0438 \u0442\u043e\u0447\u043d\u0430\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f.<\/p>\n<h3>\u0413\u0440\u0443\u0431\u0430\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f<\/h3>\n<pre><code class=\"python\">class WSPRMonitor(AbstractMonitor):    ...    def decode(self, **kwargs) -&gt; typing.Iterator[WSPRLogItem]:        ...        candidates = self.find_candidates(smooth_spec)        for cand in candidates:            smax = -1e30            if0 = int(cand.freq \/ self.df2 + self.symbol_len)            for ifr in range(if0 - 2, if0 + 2 + 1):                for k0 in range(-10, 22):                    for drift in range(-max_drift, max_drift + 1):                        ss = 0.0                        pow = 0.0                        for k in range(WSPR_ND):                            ifd = int(ifr + (k - WSPR_NUM_BITS) \/ WSPR_NUM_BITS * drift \/ (2.0 * self.df2))                            k_idx = k0 + 2 * k                            if k_idx &gt;= 0 and k_idx &lt; fft_count:                                pwrs = pwr_spec[k_idx, ifd - 3: ifd + 4: 2]                                pwrs_sqrt = np.sqrt(pwrs)                                ss += WSPR_PR3_SIG[k] * pwrs_sqrt.dot([-1, 1, -1, 1])                                pow += np.sum(pwrs_sqrt)                        sync1 = ss \/ pow                        if sync1 &gt; smax:                            smax = sync1                            cand.shift = 128 * (k0 + 1)                            cand.drift = drift                            cand.freq = (ifr - self.symbol_len) * self.df2                            cand.sync = sync1        ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u043b\u0443\u0447\u0438\u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u043e\u0432, \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0433\u0440\u0443\u0431\u044b\u0439 \u043f\u043e\u0438\u0441\u043a \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u043f\u043e \u0447\u0430\u0441\u0442\u043e\u0442\u0435 (\u0446\u0438\u043a\u043b <code>ifr<\/code>), \u0432\u0440\u0435\u043c\u0435\u043d\u0438 (<code>k0<\/code>) \u0438 \u0434\u0440\u0435\u0439\u0444\u0443 (<code>drift<\/code>) \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043a\u043e\u0440\u0440\u0435\u043b\u044f\u0446\u0438\u0438 \u0441 \u0432\u0435\u043a\u0442\u043e\u0440\u043e\u043c \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 <code>WSPR_PR3_SIG<\/code>. \u041f\u0435\u0440\u0435\u0431\u043e\u0440 \u0447\u0430\u0441\u0442\u043e\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0435 \u043e\u0442 -2 \u0434\u043e +2 \u0413\u0446 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u043e\u0439; \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u043f\u0435\u0440\u0435\u0431\u043e\u0440\u0430 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 8 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432, \u0447\u0442\u043e \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e 5.4 \u0441\u0435\u043a; \u0434\u0440\u0435\u0439\u0444 (\u043f\u043b\u0430\u0432\u043d\u043e\u0435 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0447\u0430\u0441\u0442\u043e\u0442\u044b \u0442\u043e\u043d\u043e\u0432 \u043d\u0430 \u0432\u0441\u0435\u043c \u043f\u0440\u043e\u0442\u044f\u0436\u0435\u043d\u0438\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u0430, \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u0432\u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u0430 \u043e\u043f\u043e\u0440\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u043e\u0442\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u0447\u0438\u043a\u0430 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0431\u043e\u0442\u044b, \u043f\u0440\u0438 \u043d\u0430\u0433\u0440\u0435\u0432\u0435) \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u043e\u0442 -4 \u0434\u043e +4 \u0413\u0446.<\/p>\n<p>\u0412\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u043a\u043e\u0440\u0440\u0435\u043b\u044f\u0446\u0438\u0438 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043a\u0430\u043b\u044f\u0440\u043d\u044b\u043c \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435\u043c \u0432\u0435\u043a\u0442\u043e\u0440\u0430 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0441\u043f\u0435\u043a\u0442\u0440\u0430 <code>pwr_spec (ss += WSPR_PR3_SIG[k] * pwrs_sqrt.dot([-1, 1, -1, 1]))<\/code> \u043f\u043e \u0441\u0445\u0435\u043c\u0435 <code>(b+d)-(a+c)<\/code>. \u0414\u043b\u044f \u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043a\u043e\u0440\u0440\u0435\u043b\u044f\u0446\u0438\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u0435\u043b\u0438\u0442\u0441\u044f \u043d\u0430 \u043e\u0431\u0449\u0443\u044e \u043c\u043e\u0449\u043d\u043e\u0441\u0442\u044c <code>pwrs_sqrt<\/code>.<\/p>\n<p>\u041d\u0430\u0438\u0431\u043e\u043b\u044c\u0448\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a\u043e\u0440\u0440\u0435\u043b\u044f\u0446\u0438\u0438 \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0441\u0430\u043c\u044b\u043c \u043b\u0443\u0447\u0448\u0438\u043c \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0435\u043c, \u043f\u0440\u0438 \u0434\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0437\u0430\u043f\u0438\u0441\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 <code>shift<\/code>, <code>drift<\/code>, <code>freq<\/code> \u0438 <code>sync<\/code>.<\/p>\n<p>\u041a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u044b, \u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0447\u0430\u0441\u0442\u043e\u0442 \u0438 \u043b\u0430\u0433\u043e\u0432, \u0441\u0447\u0438\u0442\u0430\u044e\u0442\u0441\u044f \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u043c\u0438, \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u044b \u0443\u0434\u0430\u043b\u044f\u044e\u0442\u0441\u044f.<\/p>\n<pre><code class=\"python\">        ...          cands = 0          for j in range(len(candidates)):              dupe = False              for k in range(cands):                  if abs(candidates[j].freq - candidates[k].freq) &lt; 0.05 and abs(               candidates[j].shift - candidates[k].shift) &lt; 16:                      dupe = True                      break              if dupe:                  if candidates[j].sync &gt; candidates[k].sync:           candidates[k] = candidates[j]              elif candidates[j].sync &gt; min_sync_2:                  candidates[cands] = candidates[j]                  cands += 1        ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h3>\u0422\u043e\u0447\u043d\u0430\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f<\/h3>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0433\u0440\u0443\u0431\u043e\u0439 \u043e\u0446\u0435\u043d\u043a\u0438 \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u043f\u043e \u043a\u043e\u0440\u0440\u0435\u043b\u044f\u0446\u0438\u0438 \u0441 \u0432\u0435\u043a\u0442\u043e\u0440\u043e\u043c \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0442\u043e\u0447\u043d\u043e\u0439 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0441 \u0441\u0438\u0433\u043d\u0430\u043b\u043e\u043c.<\/p>\n<p>\u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0437 \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u043e\u0432 \u043f\u043e\u044d\u0442\u0430\u043f\u043d\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0443\u0442\u043e\u0447\u043d\u0435\u043d\u0438\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0443\u0442\u043e\u0447\u043d\u044f\u0435\u0442\u0441\u044f \u0447\u0430\u0441\u0442\u043e\u0442\u0430.<\/p>\n<pre><code class=\"python\">...WSPR_MIN_SYNC_1 = 0.10WSPR_MIN_SYNC_2 = 0.12WSPR_ND = 162...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<pre><code class=\"python\">        ...          for cand in candidates:              f1 = cand.freq              drift1 = cand.drift              shift1 = cand.shift              f_step = 0.0              f_min = 0              f_max = 0              lag_min = shift1 - 128              lag_max = shift1 + 128              lag_step = 64              sync1, shift1, f1 = self.sync(iq_signal, f1, f_min, f_max, f_step, shift1, lag_min, lag_max, lag_step,                                            drift1, 0)              f_step = 0.25              f_min = -2              f_max = 2              sync1, shift1, f1 = self.sync(iq_signal, f1, f_min, f_max, f_step, shift1, lag_min, lag_max, lag_step,                                            drift1, 1)              if iteration &lt; 2:                  f_step = 0.0                  f_min = 0                  f_max = 0                  driftp = drift1 + 0.5                  syncp, shift1, f1 = self.sync(iq_signal, f1, f_min, f_max, f_step, shift1, lag_min, lag_max,                                                lag_step, driftp, 1)                  driftm = drift1 - 0.5                  syncm, shift1, f1 = self.sync(iq_signal, f1, f_min, f_max, f_step, shift1, lag_min, lag_max,                                                lag_step, driftm, 1)                  if syncp &gt; sync1:                      drift1 = driftp                      sync1 = syncp                  elif syncm &gt; sync1:                      drift1 = driftm                      sync1 = syncm              if sync1 &gt; WSPR_MIN_SYNC_1:                  lag_min = shift1 - 32                  lag_max = shift1 + 32                  lag_step = 16                  sync1, shift1, f1 = self.sync(iq_signal, f1, f_min, f_max, f_step, shift1, lag_min, lag_max,                                                lag_step, drift1, 0)                  f_step = 0.05                  f_min = -2                  f_max = 2                  sync1, shift1, f1 = self.sync(iq_signal, f1, f_min, f_max, f_step, shift1, lag_min, lag_max,                                                lag_step, drift1, 1)                  cand.freq = f1                  cand.shift = shift1                  cand.drift = drift1                  cand.sync = sync1        ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u044f cand.shift \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0443\u0442\u043e\u0447\u043d\u0435\u043d\u0438\u0435 (<code>lag_step<\/code>) \u0432 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0435 \u043e\u0442 -128 \u0434\u043e 128 \u0441\u0435\u043c\u043f\u043b\u043e\u0432 \u0441 \u0448\u0430\u0433\u0430\u043c\u0438 \u0432 64.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043d\u0430\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u044f \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0443\u0442\u043e\u0447\u043d\u0435\u043d\u0438\u0435 \u0447\u0430\u0441\u0442\u043e\u0442\u044b \u0441\u0438\u0433\u043d\u0430\u043b\u0430 (<code>f_step<\/code>) \u0441 \u0448\u0430\u0433\u0430\u043c\u0438 0.25 \u0432 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0435 -2 +2 \u0413\u0446 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0440\u0430\u043d\u0435\u0435 \u0437\u0430\u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u043e\u0442\u044b cand.freq.<\/p>\n<p>\u0423\u0442\u043e\u0447\u043d\u0435\u043d\u0438\u0435 \u0434\u0440\u0435\u0439\u0444\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0435 \u043e\u0442 -0.5 \u0434\u043e +0.5 \u0413\u0446.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0443\u0442\u043e\u0447\u043d\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f <code>sync1<\/code> \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u0440\u043e\u0433\u043e\u0432\u044b\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c <code>WSPR_MIN_SYNC_1<\/code>, \u043f\u0440\u0438 \u043f\u0440\u0435\u0432\u044b\u0448\u0435\u043d\u0438\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u044d\u0442\u0430\u043f \u0442\u043e\u043d\u043a\u043e\u0439 \u043f\u043e\u0434\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438, \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u043e\u0442 -32 \u0434\u043e 32 \u0441\u0435\u043c\u043f\u043b\u043e\u0432 \u0441 \u0448\u0430\u0433\u043e\u043c 16 \u0441\u0435\u043c\u043f\u043b\u043e\u0432 \u0434\u043b\u044f \u043f\u043e\u0434\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438 \u043e\u0442 -2 \u0434\u043e +2 \u0413\u0446 \u0441 \u0448\u0430\u0433\u043e\u043c 0.05 \u0413\u0446 \u0434\u043b\u044f \u0447\u0430\u0441\u0442\u043e\u0442\u044b.<\/p>\n<p>\u0422\u043e\u0447\u043d\u0430\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>sync<\/code>, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0435\u0433\u043e \u0447\u0430\u0441\u0442\u043d\u044b\u0439 \u0441\u043b\u0443\u0447\u0430\u0439 \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0444\u0438\u043b\u044c\u0442\u0440\u0430.<\/p>\n<pre><code class=\"python\">WSPR_TONES_COUNT = 4...class WSPRMonitor(AbstractMonitor):    ...    def sync(            self,            iq_signal: npt.NDArray[np.complex128],            f1: float,            f_min: int, f_max: int, f_step: float,            shift1: int,            lag_min: int, lag_max: int, lag_step: int,            drift1: float,            mode: int     ) -&gt; typing.Tuple[float, int, float]:        df_offsets = np.array([-1.5, -0.5, 0.5, 1.5]) * self.df        two_pi_dt = 2 * np.pi * self.dt        sync_max = -1e30        best_shift = shift1        f_best = f1        if mode == 0:            f_min, f_max, f_step = 0, 0, 0.0        if mode == 1:            lag_min, lag_max = shift1, shift1        tone_pwr = np.zeros(WSPR_TONES_COUNT, dtype=np.float64)        for freq in range(f_min, f_max + 1):            f0 = f1 + freq * f_step            for lag in range(lag_min, lag_max + lag_step, lag_step):                ss = 0.0                total_pwr = 0.0                for sym in range(WSPR_ND):                    fp = f0 + (drift1 \/ 2.0) * (sym - WSPR_NUM_BITS) \/ WSPR_NUM_BITS                    tone_pwr.fill(0)                    freqs = fp + df_offsets                    t_indices = np.arange(self.symbol_len)                    phasors = np.exp(-1j * two_pi_dt * np.outer(freqs, t_indices))                    for tone in range(WSPR_TONES_COUNT):                        start = lag + sym * self.symbol_len                        end = start + self.symbol_len                        segment = iq_signal[max(0, start): min(len(iq_signal), end)]                        current_phasors = phasors[tone, :len(segment)]                        acc = np.dot(current_phasors, segment)                        tone_pwr[tone] = np.abs(acc)                    total_pwr += np.sum(tone_pwr)                    channel_metric = np.sum(tone_pwr[1::2]) - np.sum(tone_pwr[0::2])                    ss += channel_metric * WSPR_PR3_SIG[sym]                if total_pwr &gt; 0:                    ss \/= total_pwr                if ss &gt; sync_max:                    sync_max = ss                    best_shift = lag                    f_best = f0        return (sync_max, best_shift, f_best)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f sync \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442 \u043f\u0435\u0440\u0435\u0431\u043e\u0440 \u0447\u0430\u0441\u0442\u043e\u0442 \u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043b\u0430\u0433\u043e\u0432; \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0437 162 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 (<code>WSPR_ND<\/code>), \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0445 \u0432 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0435, \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043c\u0430\u0441\u0441\u0438\u0432 \u043a\u043e\u043c\u043f\u043b\u0435\u043a\u0441\u043d\u044b\u0445 \u0430\u043c\u043f\u043b\u0438\u0442\u0443\u0434 <code>phasors<\/code>, \u044f\u0432\u043b\u044f\u044e\u0449\u0438\u043c\u0438\u0441\u044f \u044d\u0442\u0430\u043b\u043e\u043d\u043d\u044b\u043c\u0438 (\u043e\u043f\u043e\u0440\u043d\u044b\u043c\u0438) \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438 FSK-\u0442\u043e\u043d\u043e\u0432. \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u043f\u043b\u0435\u043a\u0441\u043d\u044b\u0445 \u0430\u043c\u043f\u043b\u0438\u0442\u0443\u0434 (\u0440\u0438\u0441\u0443\u043d\u043e\u043a 4) \u2014 \u0444\u0430\u0437\u043e\u0440\u043e\u0432 \u2014 \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043a\u0440\u043e\u0441\u0441-\u043a\u043e\u0440\u0440\u0435\u043b\u044f\u0446\u0438\u0438 \u0441 \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c\u044b\u043c \u0441\u0438\u0433\u043d\u0430\u043b\u043e\u043c \u0432 I\/Q-\u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0438.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435, \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0437 4 (<code>WSPR_TONES_COUNT<\/code>) \u0442\u043e\u043d\u043e\u0432 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u043a\u043e\u0440\u0440\u0435\u043b\u044f\u0446\u0438\u0438 \u043f\u0440\u0438\u043d\u044f\u0442\u043e\u0433\u043e \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0438\u0437 <code>segment<\/code> \u0441 \u044d\u0442\u0430\u043b\u043e\u043d\u043d\u044b\u043c \u0438\u0437 \u0444\u0430\u0437\u043e\u0440\u0430. \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0447\u0430\u0441\u0442\u043e\u0442 \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u0446\u0435\u043d\u0442\u0440\u043e\u0430\u043b\u044c\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u043e\u0442\u044b \u043d\u0430 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0443 \u0438\u0437 <code>df_offsets<\/code>. \u0412 \u043c\u0430\u0441\u0441\u0438\u0432 <code>total_pwr<\/code> \u043d\u0430\u043a\u0430\u043f\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u0443\u043c\u043c\u0430\u0440\u043d\u0430\u044f \u043c\u043e\u0449\u043d\u043e\u0441\u0442\u044c \u0441\u0438\u0433\u043d\u0430\u043b\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0434\u0430\u043b\u0435\u0435 \u043d\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 ss. \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 ss \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0441\u0443\u043c\u043c\u0430\u0440\u043d\u044b\u0439 \u043e\u0442\u043a\u043b\u0438\u043a \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0444\u0438\u043b\u044c\u0442\u0440\u0430.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3c2\/ca2\/0f0\/3c2ca20f061f7709a82df2177b791b68.png\" alt=\"\u0420\u0438\u0441\u0443\u043d\u043e\u043a 4: \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u043f\u043b\u0435\u043a\u0441\u043d\u044b\u0445 \u0430\u043c\u043f\u043b\u0438\u0442\u0443\u0434.\" title=\"\u0420\u0438\u0441\u0443\u043d\u043e\u043a 4: \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u043f\u043b\u0435\u043a\u0441\u043d\u044b\u0445 \u0430\u043c\u043f\u043b\u0438\u0442\u0443\u0434.\" width=\"1150\" height=\"485\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/3c2\/ca2\/0f0\/3c2ca20f061f7709a82df2177b791b68.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3c2\/ca2\/0f0\/3c2ca20f061f7709a82df2177b791b68.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0420\u0438\u0441\u0443\u043d\u043e\u043a 4: \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u043f\u043b\u0435\u043a\u0441\u043d\u044b\u0445 \u0430\u043c\u043f\u043b\u0438\u0442\u0443\u0434.<\/figcaption><\/div>\n<\/figure>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u2014 \u0442\u0440\u043e\u0439\u043a\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439: \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u0442\u043a\u043b\u0438\u043a\u0430 (<code>sync_max<\/code>) \u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0447\u0430\u0441\u0442\u043e\u0442\u044b (<code>f_best<\/code>) \u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 (<code>best_shift<\/code>), \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u044d\u0442\u043e\u0442 \u043e\u0442\u043a\u043b\u0438\u043a \u0431\u044b\u043b \u0434\u043e\u0441\u0442\u0438\u0433\u043d\u0443\u0442.<\/p>\n<p>\u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442 <code>mode<\/code> \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0442\u0438\u043f \u043f\u0435\u0440\u0435\u0431\u043e\u0440\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432, 0 \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e \u0447\u0430\u0441\u0442\u043e\u0442\u0435, 1 \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438.<\/p>\n<h2>\u041d\u0435\u043a\u043e\u0433\u0435\u0440\u0435\u043d\u0442\u043d\u044b\u0439 \u0434\u0435\u0442\u0435\u043a\u0442\u043e\u0440<\/h2>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0442\u043e\u0447\u043d\u043e\u0439 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0441 \u0441\u0438\u0433\u043d\u0430\u043b\u043e\u043c \u0432 \u043f\u043e\u043b\u043e\u0441\u0435, \u0432 WSPR \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432. \u0414\u0435\u0442\u0435\u043a\u0442\u043e\u0440 \u043d\u0430\u0437\u0432\u0430\u043d \u043d\u0435\u043a\u043e\u0433\u0435\u0440\u0435\u043d\u0442\u043d\u044b\u043c, \u0442\u0430\u043a \u043a\u0430\u043a \u0444\u0430\u0437\u0430 \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0430.<\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>noncoherent_sequence_detection<\/code> \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0434\u0435\u0442\u0435\u043a\u0442\u043e\u0440 \u0441\u0438\u0433\u043d\u0430\u043b\u0430. \u041d\u0430 \u0432\u0445\u043e\u0434 \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u0435\u0442 I\/Q-\u0441\u0438\u0433\u043d\u0430\u043b (<code>iq_signal<\/code>), \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u043e\u0442\u044b \u0441\u0438\u0433\u043d\u0430\u043b\u0430 (<code>f1<\/code>), \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043b\u0430\u0433\u0430 (<code>shift1<\/code>) \u0438 \u0447\u0430\u0441\u0442\u043e\u0442\u043d\u043e\u0433\u043e \u0434\u0440\u0435\u0439\u0444\u0430 (<code>drift1<\/code>).<\/p>\n<pre><code class=\"python\">class WSPRMonitor(AbstractMonitor):    ...    def noncoherent_sequence_detection(            self,            iq_signal: npt.NDArray[np.complex128],            symbols: npt.NDArray[np.uint8],            f1: float,            shift1: int,            drift1: float,            sym_fac: int,            block_size: int,            bit_metric: bool    ):        df15 = self.df * 1.5        df05 = self.df * 0.5        ref_tones = np.zeros((WSPR_TONES_COUNT, WSPR_ND), dtype=np.complex128)        phasor_ends = np.zeros((WSPR_TONES_COUNT, WSPR_ND), dtype=np.complex128)        symb = np.zeros(WSPR_ND, dtype=np.float64)        two_pi_dt = 2 * np.pi * self.dt        f0 = f1        fp = f0 + (drift1 \/ 2.0) * (np.arange(WSPR_ND) - WSPR_NUM_BITS) \/ WSPR_NUM_BITS        d_phi = two_pi_dt * np.array([fp - df15, fp - df05, fp + df05, fp + df15])        phases = d_phi[:, :, np.newaxis] * np.arange(self.symbol_len + 1)        phasors = np.exp(1j * phases)        ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0412\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0442\u043e\u043d\u043e\u0432 \u0438\u0437 \u043e\u0431\u0449\u0435\u0433\u043e \u0441\u043f\u0435\u043a\u0442\u0440\u0430 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0444\u0438\u043b\u044c\u0442\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f 3-\u0445 \u043c\u0435\u0440\u043d\u043e\u0439 \u043c\u0430\u0442\u0440\u0438\u0446\u0435\u0439 <code>phases<\/code>, \u0433\u0434\u0435 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0445 \u0442\u043e\u043d\u043e\u0432 \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u044d\u0442\u0430\u043b\u043e\u043d\u043d\u044b\u0435 (\u043e\u043f\u043e\u0440\u043d\u044b\u0435) \u0441\u0438\u0433\u043d\u0430\u043b\u044b \u043d\u0430 \u0432\u0441\u0435\u0439 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0446\u0438\u043a\u043b\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438; \u0442.\u0435. (4, 162, 257), \u0433\u0434\u0435 257 \u2014 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u044d\u043c\u043f\u043b\u043e\u0432 \u043d\u0430 1 \u0442\u043e\u043d.<\/p>\n<pre><code class=\"python\">        ...        lag = int(shift1)        indices = lag + np.arange(WSPR_ND)[:, np.newaxis] * self.symbol_len + np.arange(self.symbol_len)        indices = np.clip(indices, 0, len(iq_signal) - 1)        segments = iq_signal[indices]        segments[indices &gt;= len(iq_signal)].fill(0)        ref_tones[:, :WSPR_ND] += np.einsum('tfj,fj-&gt;tf', np.conj(phasors[:, :, :self.symbol_len]), segments)        ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041e\u0442\u043a\u043b\u0438\u043a \u0444\u0438\u043b\u044c\u0442\u0440\u0430 \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0441\u0443\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0430\u0442\u0440\u0438\u0446 \u044d\u0442\u0430\u043b\u043e\u043d\u043e\u0432 \u0441 \u0441\u0438\u0433\u043d\u0430\u043b\u043e\u043c. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043c\u043d\u043e\u0433\u043e\u043c\u0435\u0440\u043d\u043e\u0435 \u0441\u0443\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 \u043d\u043e\u0442\u0430\u0446\u0438\u044e \u042d\u0439\u043d\u0448\u0442\u0435\u0439\u043d\u0430 \u2014 <code>einsum<\/code>, (\u0437\u0430\u043f\u0438\u0441\u044c <code>tfj,fj-&gt;tf<\/code> \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u0435 \u043c\u043d\u043e\u0433\u043e\u043c\u0435\u0440\u043d\u044b\u0445 \u043c\u0430\u0442\u0440\u0438\u0446 \u0438 \u043f\u043e \u043a\u0430\u043a\u0438\u043c \u043e\u0441\u044f\u043c \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441\u0443\u043c\u043c\u0443 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430. \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 <code>t<\/code> \u2014 \u043e\u0441\u044c \u0442\u043e\u043d\u043e\u0432, <code>f<\/code> \u2014 \u043e\u0441\u044c \u0447\u0430\u0441\u0442\u043e\u0442, <code>j<\/code> \u2014 \u043a\u043e\u043c\u043f\u043b\u0435\u043a\u0441\u043d\u044b\u0435 \u0430\u043c\u043f\u043b\u0438\u0442\u0443\u0434\u044b \u0441\u0438\u0433\u043d\u0430\u043b\u043e\u0432) \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0442\u043e\u043d\u043e\u0432 \u0441\u0440\u0430\u0437\u0443, \u0432 \u043e\u0434\u043d\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435. \u0422\u0430\u043a \u043a\u0430\u043a \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u043a\u043e\u043c\u043f\u043b\u0435\u043a\u0441\u043d\u043e \u0441\u043e\u043f\u0440\u044f\u0436\u0435\u043d\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f (<img decoding=\"async\" class=\"formula inline\" source=\"e^{j\\omega t}\" alt=\"e^{j\\omega t}\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/0\/04\/041\/0413d9971cc7883057811438f065b554.svg\" width=\"24\" height=\"16\" data-width=\"3.474\" data-height=\"2.557\" data-vertical-align=\"-0.713\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/0\/04\/041\/0413d9971cc7883057811438f065b554.svg 780w,&#10;       https:\/\/habrastorage.org\/getpro\/habr\/formulas\/0\/04\/041\/0413d9971cc7883057811438f065b554.svg 781w\" loading=\"lazy\" decode=\"async\"\/>-&gt;<img decoding=\"async\" class=\"formula inline\" source=\"e^{-j\\omega t}\" alt=\"e^{-j\\omega t}\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/8\/8c\/8c1\/8c1fe5286c23f1a750dd369a60cb760a.svg\" width=\"32\" height=\"16\" data-width=\"4.718\" data-height=\"2.557\" data-vertical-align=\"-0.713\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/8\/8c\/8c1\/8c1fe5286c23f1a750dd369a60cb760a.svg 780w,&#10;       https:\/\/habrastorage.org\/getpro\/habr\/formulas\/8\/8c\/8c1\/8c1fe5286c23f1a750dd369a60cb760a.svg 781w\" loading=\"lazy\" decode=\"async\"\/>), \u0442\u043e \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u043c \u0433\u0435\u0442\u0435\u0440\u043e\u0434\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0438\u0433\u043d\u0430\u043b\u0430.<\/p>\n<blockquote>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u043d\u043e\u0433\u043e\u043c\u0435\u0440\u043d\u044b\u0445 \u043c\u0430\u0442\u0440\u0438\u0446 \u0438 \u0438\u0445 \u0441\u0443\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 python \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f, \u0442.\u043a. numpy \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442 \u044d\u0442\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043a\u043e\u0434.<\/em><\/p>\n<\/blockquote>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u0430\u043f\u0430 \u0433\u0435\u0442\u0435\u0440\u043e\u0434\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u043e\u043d\u043e\u0432 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u0435\u0439 \u0433\u0438\u043f\u043e\u0442\u0435\u0437 \u043e \u0442\u043e\u043c \u043a\u0430\u043a\u0438\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u0441\u0438\u0433\u043d\u0430\u043b\u0435.<\/p>\n<pre><code class=\"python\">        ...        phasor_ends[:, :WSPR_ND] = phasors[:, :, -1]        seq = 1 &lt;&lt; block_size        seq_weights = np.zeros(seq, dtype=np.float64)        bit_mask = np.arange(seq)        bit_exp = np.arange(block_size - 1, -1, -1)        phases = np.ones(block_size, dtype=np.complex128)        for i in range(0, WSPR_ND, block_size):            time_block = np.arange(i, i + block_size)            pr3_block = WSPR_PR3[i: i + block_size]        ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0441\u0438\u0433\u043d\u0430\u043b \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0431\u043b\u043e\u043a\u0438, \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u0430 WSPR, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442 \u0432\u0435\u043a\u0442\u043e\u0440 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 <code>WSPR_PR3<\/code> \u043a \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0438\u0437 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0447\u0430\u0441\u0442\u043e\u0442\u044b \u0442\u043e\u043d\u043e\u0432, \u0433\u0434\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u0442\u044c\u0441\u044f \u0441\u0438\u043c\u0432\u043e\u043b.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0431\u043e\u0440 \u0433\u0438\u043f\u043e\u0442\u0435\u0437 \u043e \u0442\u043e\u043c \u043a\u0430\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0431\u044b\u043b\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u044b \u0432 \u0441\u0438\u043c\u0432\u043e\u043b\u0435. \u0410\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043c\u0435\u0442\u043e\u0434 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u0430\u0432\u0434\u043e\u043f\u043e\u0434\u043e\u0431\u0438\u044f, \u043f\u0435\u0440\u0435\u0431\u0438\u0440\u0430\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0431\u0438\u0442, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u043c 4-FSK-\u0441\u0438\u043c\u0432\u043e\u043b\u0430\u043c.<\/p>\n<pre><code class=\"python\">        ...            for j in range(seq):                bits = (j &gt;&gt; bit_exp) &amp; 1                tones = pr3_block + 2 * bits                phasor_proj = ref_tones[tones, time_block]                phasor_shifts = phasor_ends[tones, time_block]                phases.fill(1 + 0j)                phases[1:] = np.cumprod(phasor_shifts[:-1])        ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0433\u0438\u043f\u043e\u0442\u0435\u0437\u044b \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0444\u0430\u0437\u043e\u0432\u0430\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0446\u0438\u044f (<code>phasor_ends<\/code>) \u0434\u043b\u044f \u043a\u043e\u0433\u0435\u0440\u0435\u043d\u0442\u043d\u043e\u0433\u043e \u0441\u0443\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0431\u0449\u0435\u0433\u043e \u043e\u0442\u043a\u043b\u0438\u043a\u0430; \u0442\u043e \u0435\u0441\u0442\u044c, \u0435\u0441\u043b\u0438 \u0434\u043b\u044f \u0433\u0438\u043f\u043e\u0442\u0435\u0437\u044b \u0432\u044b\u0431\u0440\u0430\u043d \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0441\u0438\u043c\u0432\u043e\u043b, \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043e\u0442\u043a\u043b\u0438\u043a\u0430 \u0443\u0441\u0438\u043b\u0438\u0442\u0441\u044f \u043c\u043d\u043e\u0433\u043e\u043a\u0440\u0430\u0442\u043d\u043e. \u041a\u043e\u0440\u0440\u0435\u043a\u0446\u0438\u044f \u0444\u0430\u0437\u044b \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0432\u044b\u0441\u0438\u0442\u044c \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438 \u043f\u043e\u043c\u0435\u0445\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c \u0434\u0435\u0442\u0435\u043a\u0442\u043e\u0440\u0430.<\/p>\n<pre><code class=\"python\">        ...                res = np.sum(phasor_proj * phases)                seq_weights[j] = np.abs(res)        ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0432\u0435\u0441\u0430 \u0433\u0438\u043f\u043e\u0442\u0435\u0437\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043c\u043e\u0434\u0443\u043b\u044c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0439 \u0441\u0443\u043c\u043c\u044b.<\/p>\n<pre><code class=\"python\">        ...            for ib in range(block_size):                mask = (bit_mask &amp; (1 &lt;&lt; (block_size - 1 - ib))) == 0                xm0 = seq_weights[:seq][mask].max()                xm1 = seq_weights[:seq][~mask].max()                metric = xm1 - xm0                if bit_metric:                    metric \/= np.max(xm0, xm1)                symb[i + ib] = metric        ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0433\u0438\u043f\u043e\u0442\u0435\u0437\u044b \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u0430 \u0433\u0440\u0443\u043f\u043f\u044b \u043d\u0443\u043b\u0435\u0439 (<code>xm0<\/code>) \u0438 \u0435\u0434\u0438\u043d\u0438\u0446 (<code>xm1<\/code>), \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u043d\u043e\u0441\u0442\u043d\u0430\u044f \u043c\u0435\u0442\u0440\u0438\u043a\u0430 (<code>metric<\/code>), \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0430\u044f \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0447\u0438\u0441\u043b\u0435\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0431\u0438\u0442.<\/p>\n<pre><code class=\"python\">        ...        std = np.std(symb)        symb *= sym_fac \/ std        symbols[:] = np.clip(symb, -128.0, 127.0) + 128<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u0435\u0439 \u0447\u0435\u0440\u0435\u0437 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0435 \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d\u0438\u0435 \u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0443\u044e\u0442\u0441\u044f \u0432 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d -128..127 (\u0447\u0442\u043e\u0431\u044b \u0443\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432 \u043e\u0434\u043d\u043e\u0431\u0430\u0439\u0442\u043e\u0432\u043e\u0435 \u0446\u0435\u043b\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435), \u0434\u043b\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u043e\u043c \u043a\u043e\u0440\u0440\u0435\u043a\u0446\u0438\u0438 \u043e\u0448\u0438\u0431\u043e\u043a.<\/p>\n<p>\u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442 <code>bit_metric<\/code> \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0437\u0430\u0434\u0430\u0435\u0442 \u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043c\u0435\u0442\u0440\u0438\u043a\u0438, \u0434\u0435\u043b\u0430\u044f \u0435\u0435 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044f \u043a\u043e\u043c\u043f\u0435\u043d\u0441\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0444\u0444\u0435\u043a\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0430\u043c\u043f\u043b\u0438\u0442\u0443\u0434\u044b \u0441\u0438\u0433\u043d\u0430\u043b\u0430 (\u0410\u0420\u0423\/AGC).<\/p>\n<p>\u0414\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 \u0438\u0437 <a href=\"https:\/\/habr.com\/en\/articles\/1017728\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0430\u0442\u044c\u0438<\/a>, \u0434\u0435\u0442\u0435\u043a\u0442\u043e\u0440 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432 \u0442\u0430\u043a\u043e\u0439 \u0444\u043e\u0440\u043c\u0435:<\/p>\n<pre><code>184, 71, 86, 182, 176, 167, 87, 181, 70, 85, 90, 88, 184, 70, 183, 88, 184, 87, 70, 177, 86, 70, 86, 184, 70, 71, 185, 175, 167, 87, 89, 185, 87, 177, 70, 173, 86, 69, 87, 184, 89, 90, 85, 169, 182, 86, 70, 174, 185, 71, 178, 178, 70, 70, 85, 70, 86, 174, 179, 185, 71, 86, 70, 86, 173, 178, 179, 185, 71, 87, 184, 87, 70, 179, 70, 86, 70, 179, 178, 183, 87, 88, 69, 85, 70, 185, 177, 87, 175, 185, 71, 87, 184, 87, 70, 179, 176, 88, 184, 88, 174, 181, 87, 172, 185, 179, 86, 70, 175, 177, 185, 185, 185, 179, 185, 71, 173, 88, 185, 71, 178, 185, 167, 87, 87, 70, 70, 70, 172, 87, 181, 89, 88, 184, 179, 70, 87, 176, 185, 183, 88, 90, 85, 166, 174, 177, 178, 70, 70, 85, 70, 178, 70, 70, 87, 86, 170, 71, 185, 179, 178, 91.<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h2>\u0414\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u043e\u0432<\/h2>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u0435\u0439 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u044d\u0442\u0430\u043f \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<pre><code class=\"python\">WSPR_SOFT_SYM_FAC = 50WSPR_MIN_RMS = 52 * (WSPR_SOFT_SYM_FAC \/ 64)WSPR_IIFAC = 8...class WSPRMonitor(AbstractMonitor):    ...    def decode(self, **kwargs) -&gt; typing.Iterator[WSPRLogItem]:    ...        for cand in candidates:            f1 = cand.freq            shift1 = cand.shift            drift1 = cand.drift            decoded = None            ib = 1            while ib &lt;= block_size and decoded is None:                if ib &lt; 4:                    block_size = ib                    bit_metric = False                else:                    block_size = 1                    bit_metric = True                  idt = 0                  while decoded is None and idt &lt;= (128 \/ WSPR_IIFAC):                      ii = (idt + 1) \/ 2                      if idt % 2 == 1:                          ii = -ii                      ii = WSPR_IIFAC * ii                      jittered_shift = shift1 + ii                      self.noncoherent_sequence_detection(                          iq_signal, symbols, f1, jittered_shift, drift1, WSPR_SOFT_SYM_FAC, block_size, bit_metric                     )    ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0445 \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u043e\u0432 \u043d\u0430 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u0446\u0438\u043a\u043b \u043d\u0435\u043a\u043e\u0433\u0435\u0440\u0435\u043d\u0442\u043d\u043e\u0433\u043e \u0434\u0435\u0442\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0438\u0433\u043d\u0430\u043b\u0430, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u043e\u0434\u0431\u043e\u0440 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0434\u0436\u0438\u0442\u0442\u0435\u0440\u0430 \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0442\u043e\u0447\u043d\u043e\u0433\u043e \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432. \u041f\u0435\u0440\u0435\u0431\u043e\u0440 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0442\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e, \u043e\u0441\u043d\u043e\u0432\u044b\u0432\u0430\u044f\u0441\u044c \u043d\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u0445 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0440\u0435\u0447\u044c \u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u043e\u0439\u0434\u0435\u0442 \u0434\u0430\u043b\u044c\u0448\u0435.<\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>noncoherent_sequence_detection<\/code> \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u0442 \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u0438 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432.<\/p>\n<pre><code class=\"python\">    ...                      rms = np.sqrt(np.mean(np.square(symbols.astype(np.float32) - 128)))                      if rms &gt; WSPR_MIN_RMS:    ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0440\u0435\u0434\u043d\u0435\u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0438\u0447\u043d\u043e\u0435 \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d\u0438\u0435, \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0435 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0435\u0442 \u043f\u043e\u0440\u043e\u0433\u043e\u0432\u043e\u0435, \u0442\u043e \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u0434\u0431\u043e\u0440\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0438 \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u0442\u0441\u044f; \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043f\u043e\u0434\u0432\u0435\u0440\u0433\u0430\u044e\u0442\u0441\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u2014 \u0434\u0435\u0438\u043d\u0442\u0435\u0440\u043b\u0438\u0432\u0438\u043d\u0433\u0443 \u0438 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e. <\/p>\n<h2>\u0414\u0435\u0438\u043d\u0442\u0435\u0440\u043b\u0438\u0432\u0438\u043d\u0433<\/h2>\n<p>\u041d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438, \u0434\u043b\u044f \u043f\u043e\u0432\u044b\u0448\u0435\u043d\u0438\u044f \u043f\u043e\u043c\u0435\u0445\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u0438 \u0438 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043e\u0448\u0438\u0431\u043e\u043a \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u043b\u0441\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0438\u043d\u0442\u0435\u0440\u043b\u0438\u0432\u0438\u043d\u0433\u0430, \u043f\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u043b\u0430 \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432; \u043f\u043e\u0441\u043b\u0435 \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u0435\u0439 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432, \u043d\u0430 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0435\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u2014 \u0434\u0435\u0438\u043d\u0442\u0435\u0440\u043b\u0438\u0432\u0438\u043d\u0433, \u0437\u0430\u0434\u0430\u0447\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u0443\u044e \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u0434\u043b\u044f \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<pre><code class=\"python\">class WSPRMonitor(AbstractMonitor):    ...    @staticmethod    def deinterleave(sym: npt.NDArray[np.uint8]):        tmp = np.zeros(WSPR_ND, dtype=np.uint8)        p = 0        i = 0        while p &lt; WSPR_ND:            j = (((i * 0x80200802) &amp; 0x0884422110) * 0x0101010101 &gt;&gt; 32) &amp; 0xff            if j &lt; WSPR_ND:                tmp[p] = sym[j]                p = p + 1            i += 1        sym[:] = tmp[:]    def decode(self, **kwargs) -&gt; typing.Iterator[WSPRLogItem]:    ...                          self.deinterleave(symbols)    ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>deinterleave<\/code> \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0434\u0435\u0438\u043d\u0442\u0435\u0440\u043b\u0438\u0432\u0438\u043d\u0433 WSPR. \u0412 WSPR \u0432 \u0443\u0433\u043e\u0434\u0443 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0432\u043e\u0440\u043e\u0442 \u0431\u0438\u0442 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0434\u0432\u043e\u0438\u0447\u043d\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u043d\u0430\u0434 \u043d\u0438\u043c\u0438 (Bit Reverse in 3 operations); \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b <code>0x80200802<\/code>, <code>0x0884422110<\/code> \u0438 <code>0x0101010101<\/code> \u043f\u043e\u0434\u043e\u0431\u0440\u0430\u043d\u044b \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0440\u0430\u0437\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u0435 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0445 \u0431\u0438\u0442 \u043d\u0430 64 \u0431\u0438\u0442\u043d\u043e\u0435 \u0441\u043b\u043e\u0432\u043e, \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u0431\u0438\u0442\u043e\u0432\u0443\u044e \u043c\u0430\u0441\u043a\u0443 \u0434\u043b\u044f \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043d\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0449\u0438\u0445 \u0431\u0438\u0442 \u0438 \u0441\u0443\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435\u043c \u0431\u0438\u0442 \u0432 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435.<\/p>\n<p>\u0412 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e <code>j<\/code> \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0438\u0440\u0443\u044e\u0449\u0435\u0433\u043e \u043c\u0430\u0441\u0441\u0438\u0432\u0430 <code>tmp<\/code> \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0430\u043c. \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u0434\u0430\u043d\u043d\u044b\u0445 \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0432 \u043c\u0430\u0441\u0441\u0438\u0432 <code>sym<\/code>.<\/p>\n<p>\u0412\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043f\u043e\u0434\u0432\u0435\u0440\u0433\u0430\u0435\u0442\u0441\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c\u0443 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u043a\u043e\u0434\u043e\u043c \u043a\u043e\u0440\u0440\u0435\u043a\u0446\u0438\u0438 \u043e\u0448\u0438\u0431\u043e\u043a.<\/p>\n<p>\u0420\u0430\u043d\u0435\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u0441\u043b\u0435 \u0434\u0435\u0438\u043d\u0442\u0435\u0440\u043b\u0438\u0432\u0438\u043d\u0433\u0430 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0442 \u0432\u0438\u0434:<\/p>\n<pre><code>184, 172, 173, 87, 178, 176, 184, 174, 87, 185, 185, 70, 87, 70, 89, 185, 70, 70, 175, 86, 178, 176, 88, 71, 86, 174, 86, 70, 70, 70, 173, 184, 88, 70, 182, 175, 167, 170, 184, 71, 87, 86, 181, 179, 70, 184, 70, 178, 69, 178, 185, 90, 185, 70, 85, 86, 185, 87, 71, 179, 167, 87, 179, 184, 87, 87, 86, 70, 177, 85, 185, 183, 85, 178, 70, 185, 89, 185, 70, 70, 70, 71, 87, 178, 177, 91, 88, 87, 177, 88, 71, 179, 85, 176, 179, 90, 179, 71, 70, 185, 174, 185, 167, 184, 87, 69, 181, 70, 85, 185, 70, 88, 70, 90, 179, 86, 177, 87, 71, 87, 86, 70, 182, 89, 185, 173, 88, 177, 70, 85, 178, 71, 88, 183, 86, 169, 70, 175, 86, 87, 185, 87, 181, 70, 87, 184, 172, 184, 178, 87, 70, 71, 88, 166, 183, 174, 185, 185, 179, 179, 86, 70.<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h2>\u0414\u0435\u043a\u043e\u0434\u0435\u0440 \u0424\u0430\u043d\u043e<\/h2>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0434\u0435\u0442\u0435\u043a\u0446\u0438\u0438, \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u0438 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0439 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0434\u0435\u0438\u043d\u0442\u0435\u0440\u043b\u0438\u0432\u0438\u043d\u0433\u0430, \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043f\u043e\u0434\u0432\u0435\u0440\u0433\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0443 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430\u043c\u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0446\u0438\u0438 \u043e\u0448\u0438\u0431\u043e\u043a.<\/p>\n<p>\u041a\u043b\u0430\u0441\u0441 \u043a\u043e\u0434\u043e\u0432 \u043a\u043e\u0440\u0440\u0435\u043a\u0446\u0438\u0438 \u043e\u0448\u0438\u0431\u043e\u043a \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0441\u0432\u0435\u0440\u0442\u043e\u0447\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 (\u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043d\u044b\u0439 \u0432 <a href=\"https:\/\/habr.com\/en\/articles\/1017728\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0430\u0442\u044c\u0438<\/a>) \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0442\u0430\u043a\u0438\u043c\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430\u043c\u0438 \u043a\u0430\u043a: \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0412\u0438\u0442\u0435\u0440\u0431\u0438, \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0415\u043b\u0438\u043d\u0435\u043a\u0430, \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0424\u0430\u043d\u043e \u0438 \u0442.\u0434..<\/p>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0438 \u0441\u0438\u043b\u044c\u043d\u044b\u0435 \u0438 \u0441\u043b\u0430\u0431\u044b\u0435 \u0441\u0442\u043e\u0440\u043e\u043d\u044b, \u0442\u0430\u043a, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0412\u0438\u0442\u0435\u0440\u0431\u0438 (\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u043a\u0430\u043a \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442 \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0447 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0432\u0435\u0440\u0442\u043e\u0447\u043d\u044b\u0445 \u043a\u043e\u0434\u043e\u0432) \u043f\u0435\u0440\u0435\u0431\u0438\u0440\u0430\u0435\u0442 \u0432\u0441\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u043f\u0443\u0442\u0438 \u0432 \u0440\u0435\u0448\u0435\u0442\u043a\u0435 \u043a\u043e\u0434\u0430, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0437\u0430 \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f, \u043d\u043e \u0438\u043c\u0435\u0435\u0442 \u044d\u043a\u0441\u043f\u043e\u043d\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u043e\u0441\u0442 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u0438 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0438 \u0434\u043b\u0438\u043d\u044b \u043a\u043e\u0434\u043e\u0432\u043e\u0433\u043e \u0441\u043b\u043e\u0432\u0430. \u0410\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0424\u0430\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0434\u0435\u0440\u0435\u0432\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0439 (\u0440\u0438\u0441\u0443\u043d\u043e\u043a 5), \u043e\u0431\u043b\u0430\u0434\u0430\u0435\u0442 \u043d\u0438\u0437\u043a\u0438\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u0435\u043c \u043f\u0430\u043c\u044f\u0442\u0438, \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043e\u0447\u0435\u043d\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u043a\u043e\u0434\u043e\u0432\u044b\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438, \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u044f \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u0438 \u043e\u0448\u0438\u0431\u043e\u043a, \u043d\u043e \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0438\u043c\u0435\u0435\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0438 \u043d\u0430 \u0437\u0430\u0448\u0443\u043c\u043b\u0435\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u043e\u0436\u0435\u0442 \u0443\u0439\u0442\u0438 \u0432 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0446\u0438\u043a\u043b. \u0410\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0415\u043b\u0438\u043d\u0435\u043a\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0439\u0434\u0435\u043d\u043d\u044b\u0445 \u043f\u0443\u0442\u0435\u0439 \u0441\u0442\u0435\u043a \u0441 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u043e\u0439 \u043f\u043e \u043c\u0435\u0442\u0440\u0438\u043a\u0435, \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u0424\u0430\u043d\u043e, \u043d\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043f\u0430\u043c\u044f\u0442\u0438 \u0438 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u044b \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u0442\u0430\u043a\u0436\u0435 \u0441\u0438\u043b\u044c\u043d\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0437\u0430\u0448\u0443\u043c\u043b\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0412 WSPR \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0424\u0430\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432, \u0445\u043e\u0442\u044f \u043f\u0440\u0438 \u044d\u0442\u043e\u043c, \u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 K9AN \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u0415\u043b\u0438\u043d\u0435\u043a\u0430.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1ae\/391\/b77\/1ae391b77417c209aa41daccf048be66.png\" alt=\"\u0420\u0438\u0441\u0443\u043d\u043e\u043a 5: \u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u043f\u043e \u0434\u0435\u0440\u0435\u0432\u0443 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u0424\u0430\u043d\u043e.\" title=\"\u0420\u0438\u0441\u0443\u043d\u043e\u043a 5: \u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u043f\u043e \u0434\u0435\u0440\u0435\u0432\u0443 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u0424\u0430\u043d\u043e.\" width=\"512\" height=\"292\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/1ae\/391\/b77\/1ae391b77417c209aa41daccf048be66.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1ae\/391\/b77\/1ae391b77417c209aa41daccf048be66.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0420\u0438\u0441\u0443\u043d\u043e\u043a 5: \u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u043f\u043e \u0434\u0435\u0440\u0435\u0432\u0443 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u0424\u0430\u043d\u043e.<\/figcaption><\/div>\n<\/figure>\n<pre><code class=\"python\">LL_POLY1 = 0xf2d05351LL_POLY2 = 0xe4613c47<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0414\u043b\u044f \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0442\u0435 \u0436\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c \u043f\u043e\u043b\u0438\u043d\u043e\u043c\u043e\u0432, \u0447\u0442\u043e \u0438 \u043f\u0440\u0438 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u2014 \u041b\u0435\u0439\u043b\u0430\u043d\u0434\u0430-\u041b\u0430\u0448\u0431\u043e (Layland-Lushbaugh).<\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>fano<\/code> \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0434\u0435\u043a\u043e\u0434\u0435\u0440\u0430 \u0424\u0430\u043d\u043e. \u0424\u0445\u043e\u0434\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b: \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u0438 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 <code>symbols<\/code>, \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0431\u0438\u0442 \u0432 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u0443\u0435\u043c\u043e\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0438 <code>bits<\/code>, \u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u043c\u0435\u0442\u0440\u0438\u043a \u043f\u0440\u0430\u0432\u0434\u043e\u043f\u043e\u0434\u043e\u0431\u0438\u044f \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 <code>metric_table<\/code>, \u0448\u0430\u0433 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u0440\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f <code>delta<\/code> (\u043c\u0430\u043b\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0432\u044b\u0441\u043e\u043a\u0443\u044e \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c, \u043d\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0435\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0439), \u043f\u043e\u0440\u043e\u0433 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0439 <code>max_iter<\/code>.<\/p>\n<pre><code class=\"python\">@njitdef fano(        symbols: npt.NDArray[np.uint8],        bits: int,        metric_table: npt.NDArray[np.int64],        delta: int,        max_iter: int,        poly1: int = LL_POLY1,        poly2: int = LL_POLY2,) -&gt; typing.Optional[typing.Tuple[int, int, npt.NDArray[np.uint8]]]:    s0 = symbols[0::2]    s1 = symbols[1::2]    metrics_all = np.empty((bits, 4), dtype=np.int64)    metrics_all[:, 0] = metric_table[0, s0] + metric_table[0, s1]    metrics_all[:, 1] = metric_table[0, s0] + metric_table[1, s1]    metrics_all[:, 2] = metric_table[1, s0] + metric_table[0, s1]    metrics_all[:, 3] = metric_table[1, s0] + metric_table[1, s1]    ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0414\u043b\u044f \u0432\u0441\u0435\u0445 \u043f\u0430\u0440 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 (<code>00<\/code>, <code>01<\/code>, <code>10<\/code>, <code>11<\/code>, \u0442\u0430\u043a \u043a\u0430\u043a \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u00bd, \u0442\u043e \u0435\u0441\u0442\u044c \u043e\u0434\u043d\u043e\u043c\u0443 \u0432\u0445\u043e\u0434\u043d\u043e\u043c\u0443 \u0431\u0438\u0442\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0434\u0432\u0430 \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0445) \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043c\u0435\u0442\u0440\u0438\u043a\u0438 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043b\u043e\u0433\u0430\u0440\u0438\u0444\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u0435\u0439 \u0438\u0437 <code>metric_table<\/code>.<\/p>\n<pre><code class=\"python\">    ...    encstates = np.zeros(bits + 1, dtype=np.uint64)    gammas = np.zeros(bits + 1, dtype=np.int64)    ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041c\u0430\u0441\u0441\u0438\u0432 <code>encstates<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u0441\u0434\u0432\u0438\u0433\u043e\u0432\u043e\u0433\u043e \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435, \u043f\u043e \u0441\u0443\u0442\u0438, \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438. \u041c\u0430\u0441\u0441\u0438\u0432 <code>gammas<\/code> \u043d\u0430\u043a\u0430\u043f\u043b\u0438\u0432\u0430\u0435\u0442 \u043c\u0435\u0442\u0440\u0438\u043a\u0443 \u043f\u0443\u0442\u0438 \u0434\u043e \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0443\u0437\u043b\u0430.<\/p>\n<pre><code class=\"python\">    ...    tms = np.zeros((bits, 2), dtype=np.int64)    current_i = np.zeros(bits, dtype=np.uint8)    node_id = 0    node_id_max = bits - 1    node_id_tail = bits - 31    lsym = 0    m0 = metrics_all[0, lsym]    m1 = metrics_all[0, 3 ^ lsym]    if m0 &gt;= m1:        tms[0, 0] = m0        tms[0, 1] = m1    else:        tms[0, 0] = m1        tms[0, 1] = m0        encstates[0] = 1    threshold = 0    total_iters = max_iter * bits    for cycle in range(1, total_iters + 1):        current_gamma = gammas[node_id] + (tms[node_id, 0] if current_i[node_id] == 0 else tms[node_id, 1])    ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0426\u0438\u043a\u043b \u043f\u043e <code>total_iters<\/code> \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u043f\u043e \u0434\u0435\u0440\u0435\u0432\u0443 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0412 \u043a\u0430\u0436\u0434\u043e\u043c \u0443\u0437\u043b\u0435 <code>node_id<\/code> \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0431\u0438\u0442\u0430 0 \u0438\u043b\u0438 1 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u044d\u043d\u043a\u043e\u0434\u0435\u0440\u0430 <code>encstates<\/code> \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043f\u043e\u043b\u0438\u043d\u043e\u043c\u043e\u0432 <code>poly1<\/code>, <code>poly2<\/code>.<\/p>\n<pre><code class=\"python\">    ...        if current_gamma &gt;= threshold:            if gammas[node_id] &lt; threshold + delta:                if current_gamma &gt;= threshold + delta:                    threshold += ((current_gamma - threshold) \/\/ delta) * delta            node_id += 1            gammas[node_id] = current_gamma    ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u0440\u043e\u0433\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>threshold<\/code> \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u0438\u044f \u043c\u0435\u0442\u0440\u0438\u043a\u0438 <code>current_gamma<\/code>, \u0435\u0441\u043b\u0438 \u043c\u0435\u0442\u0440\u0438\u043a\u0430 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0435\u0442 \u043f\u043e\u0440\u043e\u0433, \u0442\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u0442\u0441\u044f, \u043d\u043e \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u0440\u0438\u043a\u0438 \u0432\u043e \u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0437 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0435\u0442 \u043f\u043e\u0440\u043e\u0433\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0442\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 <code>delta<\/code>.<\/p>\n<pre><code class=\"python\">    ...            if node_id &gt; node_id_max:                data = np.zeros(bits \/\/ 8, dtype=np.uint8)                for j in range(bits \/\/ 8):                    data[j] = encstates[(j + 1) * 8 - 1] &amp; 0xff                return current_gamma, cycle, data    ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u0442\u0441\u044f \u0443\u0441\u043f\u0435\u0448\u043d\u043e, \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>node_id<\/code> \u0434\u043e\u0441\u0442\u0438\u0433\u043b\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f <code>bits<\/code>, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044f \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f <code>current_gamma<\/code>, <code>cycle<\/code> \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0431\u0438\u0442 \u0434\u0430\u043d\u043d\u044b\u0445 data \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f <code>encstates<\/code>.<\/p>\n<pre><code class=\"python\">    ...            next_state = (encstates[node_id - 1] &lt;&lt; 1)            encstates[node_id] = next_state            tmp = next_state &amp; poly1            tmp ^= tmp &gt;&gt; 16            lsym = PARITY_TAB[(tmp ^ (tmp &gt;&gt; 8)) &amp; 0xff] &lt;&lt; 1            tmp = next_state &amp; poly2            tmp ^= tmp &gt;&gt; 16            lsym |= PARITY_TAB[(tmp ^ (tmp &gt;&gt; 8)) &amp; 0xff]    ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u0431\u0438\u0442\u043e\u0432\u043e\u0435 \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441 <code>poly1<\/code> \u0438 <code>poly2<\/code> \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u0442 \u0431\u0438\u0442\u044b, \u0443\u0447\u0430\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0432 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u0430. \u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u0442\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u0431\u0438\u0442\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0441\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u043e \u043c\u043e\u0434\u0443\u043b\u044e 2 (xor) \u043c\u0435\u0436\u0434\u0443 \u0432\u0441\u0435\u043c\u0438 \u0431\u0438\u0442\u0430\u043c\u0438 <code>tmp<\/code>.<\/p>\n<p>\u0414\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0447\u0435\u0442\u043d\u043e\u0441\u0442\u0438 \u0431\u0438\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f xor \u0441\u0434\u0432\u0438\u0433 \u0431\u0438\u0442.<\/p>\n<p>\u0422\u0430\u0431\u043b\u0438\u0446\u0430 \u0447\u0435\u0442\u043d\u043e\u0441\u0442\u0438 <code>PARITY_TAB<\/code> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0447\u0435\u0442\u043d\u043e\u0441\u0442\u0438 \u0431\u0438\u0442\u0430.<\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0433\u0438\u043f\u043e\u0442\u0435\u0437 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u043f\u0440\u0438 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438.<\/p>\n<pre><code class=\"python\">    ...            if node_id &gt;= node_id_tail:                tms[node_id, 0] = metrics_all[node_id, lsym]                tms[node_id, 1] = -1000000            else:                m0 = metrics_all[node_id, lsym]                m1 = metrics_all[node_id, 3 ^ lsym]                if m0 &gt;= m1:                    tms[node_id, 0] = m0                    tms[node_id, 1] = m1                else:                    tms[node_id, 0] = m1                    tms[node_id, 1] = m0                    encstates[node_id] |= 1            current_i[node_id] = 0            continue    ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0425\u0432\u043e\u0441\u0442\u043e\u0432\u044b\u0435 \u0431\u0438\u0442\u044b <code>node_id_tail<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u043d\u0443\u043b\u0438 \u0434\u043b\u044f \u0441\u0431\u0440\u043e\u0441\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430, \u0434\u043b\u044f \u043d\u0438\u0445 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0432\u044b\u0431\u043e\u0440\u0430 \u043f\u0443\u0442\u0435\u043c \u043f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043c\u0435\u0442\u0440\u0438\u043a\u0438 \u043d\u0430 \u043e\u0447\u0435\u043d\u044c \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 -1000000.<\/p>\n<pre><code class=\"python\">    ...        else:            while True:                if node_id == 0 or gammas[node_id - 1] &lt; threshold:                    threshold -= delta                    if current_i[node_id] != 0:                        current_i[node_id] = 0                        encstates[node_id] ^= 1                    break                node_id -= 1                if node_id &lt; node_id_tail and current_i[node_id] != 1:                    current_i[node_id] = 1                    encstates[node_id] ^= 1                    break<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u043f\u0440\u0438 \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0438 \u0432\u043f\u0435\u0440\u0435\u0434 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u0440\u0438\u043a\u0438 <code>current_gamma<\/code> \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043c\u0435\u043d\u044c\u0448\u0435 \u043f\u043e\u0440\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f <code>threshold<\/code>, \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0435 \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u043f\u043e \u0434\u0435\u0440\u0435\u0432\u0443, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u043d\u0430 \u0434\u0440\u0443\u0433\u0443\u044e \u0432\u0435\u0442\u043a\u0443 \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u0443\u0437\u043b\u0435, \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u044b\u043b\u0430 \u043d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u2014 <code>current_i[node_id] = 1<\/code>.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u043d\u0430 \u0432\u0441\u0435\u0445 \u0443\u0437\u043b\u0430\u0445 \u0432\u0435\u0442\u043a\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u0440\u0438\u043a\u0438 \u043d\u0435 \u0434\u043e\u0441\u0442\u0438\u0433\u043b\u043e \u043f\u043e\u0440\u043e\u0433\u043e\u0432\u043e\u0433\u043e, \u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u043d\u0430 \u043e\u0434\u0438\u043d \u0443\u0437\u0435\u043b \u043d\u0430\u0437\u0430\u0434 \u2014 <code>node_id -= 1<\/code>.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u043f\u043e\u0440\u043e\u0433\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432\u0441\u0451 \u0435\u0449\u0451 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0431\u043e\u043b\u044c\u0448\u043e\u0435, \u0438\u043b\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0432\u0435\u0440\u043d\u0443\u043b\u0441\u044f \u0432 \u0441\u0430\u043c\u043e\u0435 \u043d\u0430\u0447\u0430\u043b\u043e \u0434\u0435\u0440\u0435\u0432\u0430, \u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u0440\u043e\u0433\u0430 \u0441\u043d\u0438\u0436\u0430\u0435\u0442\u0441\u044f \u043d\u0430 delta \u0438 \u0446\u0438\u043a\u043b \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u0442\u0441\u044f \u0441 \u0441\u0430\u043c\u043e\u0433\u043e \u043d\u0430\u0447\u0430\u043b\u0430.<\/p>\n<p>\u0422\u0430\u0431\u043b\u0438\u0446\u0430 \u0447\u0435\u0442\u043d\u043e\u0441\u0442\u0438 \u0431\u0438\u0442:<\/p>\n<pre><code class=\"python\">PARITY_TAB = np.array([    0, 1, 1, 0, 1, 0, 0, 1,    1, 0, 0, 1, 0, 1, 1, 0,    1, 0, 0, 1, 0, 1, 1, 0,    0, 1, 1, 0, 1, 0, 0, 1,    1, 0, 0, 1, 0, 1, 1, 0,    0, 1, 1, 0, 1, 0, 0, 1,    0, 1, 1, 0, 1, 0, 0, 1,    1, 0, 0, 1, 0, 1, 1, 0,    1, 0, 0, 1, 0, 1, 1, 0,    0, 1, 1, 0, 1, 0, 0, 1,    0, 1, 1, 0, 1, 0, 0, 1,    1, 0, 0, 1, 0, 1, 1, 0,    0, 1, 1, 0, 1, 0, 0, 1,    1, 0, 0, 1, 0, 1, 1, 0,    1, 0, 0, 1, 0, 1, 1, 0,    0, 1, 1, 0, 1, 0, 0, 1,    1, 0, 0, 1, 0, 1, 1, 0,    0, 1, 1, 0, 1, 0, 0, 1,    0, 1, 1, 0, 1, 0, 0, 1,    1, 0, 0, 1, 0, 1, 1, 0,    0, 1, 1, 0, 1, 0, 0, 1,    1, 0, 0, 1, 0, 1, 1, 0,    1, 0, 0, 1, 0, 1, 1, 0,    0, 1, 1, 0, 1, 0, 0, 1,    0, 1, 1, 0, 1, 0, 0, 1,    1, 0, 0, 1, 0, 1, 1, 0,    1, 0, 0, 1, 0, 1, 1, 0,    0, 1, 1, 0, 1, 0, 0, 1,    1, 0, 0, 1, 0, 1, 1, 0,    0, 1, 1, 0, 1, 0, 0, 1,    0, 1, 1, 0, 1, 0, 0, 1,    1, 0, 0, 1, 0, 1, 1, 0,])<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0422\u0430\u0431\u043b\u0438\u0446\u044b \u043c\u0435\u0442\u0440\u0438\u043a, \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u043d\u043d\u044b\u0445 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u043e\u0434\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f 2-FSK \u0442\u043e\u043d\u043e\u0432, \u043f\u0440\u0438 \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f\u0445 Es\/No=0,3,6,9 \u0434\u0411 \u0438 \u0441\u0440\u0435\u0434\u043d\u0435\u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0438\u0447\u043d\u043e\u043c \u0443\u0440\u043e\u0432\u043d\u0435 \u0448\u0443\u043c\u0430 \u0432 50:<\/p>\n<pre><code class=\"python\">WSPR_METRIC_TABLES = np.array([    [0.9782, 0.9695, 0.9689, 0.9669, 0.9666, 0.9653, 0.9638, 0.9618, 0.9599, 0.9601,     0.9592, 0.9570, 0.9556, 0.9540, 0.9525, 0.9527, 0.9486, 0.9477, 0.9450, 0.9436,     0.9424, 0.9400, 0.9381, 0.9360, 0.9340, 0.9316, 0.9301, 0.9272, 0.9254, 0.9224,     0.9196, 0.9171, 0.9154, 0.9123, 0.9076, 0.9061, 0.9030, 0.9000, 0.8965, 0.8934,     0.8903, 0.8874, 0.8834, 0.8792, 0.8760, 0.8726, 0.8685, 0.8639, 0.8599, 0.8550,     0.8504, 0.8459, 0.8422, 0.8364, 0.8320, 0.8262, 0.8215, 0.8159, 0.8111, 0.8052,     0.7996, 0.7932, 0.7878, 0.7812, 0.7745, 0.7685, 0.7616, 0.7550, 0.7479, 0.7405,     0.7336, 0.7255, 0.7184, 0.7102, 0.7016, 0.6946, 0.6860, 0.6769, 0.6687, 0.6598,     0.6503, 0.6416, 0.6325, 0.6219, 0.6122, 0.6016, 0.5920, 0.5818, 0.5711, 0.5606,     0.5487, 0.5374, 0.5266, 0.5142, 0.5020, 0.4908, 0.4784, 0.4663, 0.4532, 0.4405,     0.4271, 0.4144, 0.4006, 0.3865, 0.3731, 0.3594, 0.3455, 0.3304, 0.3158, 0.3009,     0.2858, 0.2708, 0.2560, 0.2399, 0.2233, 0.2074, 0.1919, 0.1756, 0.1590, 0.1427,     0.1251, 0.1074, 0.0905, 0.0722, 0.0550, 0.0381, 0.0183, 0.0000, -0.0185, -0.0391,     -0.0571, -0.0760, -0.0966, -0.1160, -0.1370, -0.1584, -0.1787, -0.1999, -0.2214, -0.2423,    ...     -14.1653, -14.4348, -14.7983, -14.7807, -15.2349, -15.3536, -15.3026, -15.2739, -15.7170, -16.2161,     -15.9185, -15.9490, -16.6258, -16.5568, -16.4318, -16.7999, -16.4101, -17.6393, -17.7643, -17.2644,     -17.5973, -17.0403, -17.7039, -18.0073, -18.1840, -18.3848, -18.6286, -20.7063, 1.43370769e-019,     2.64031087e-006, 6.6908396e+031, 1.77537994e+028, 2.79322819e+020, 1.94326e-019,     0.00019371575, 2.80722121e-041]])WSPR_METRIC_TABLE = np.zeros((2, 256), dtype=np.int64)WSPR_METRIC_TABLE[0, :] = 10 * (WSPR_METRIC_TABLES[2] - WSPR_DECODER_BIAS)WSPR_METRIC_TABLE[1, :] = WSPR_METRIC_TABLE[0, ::-1]<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u043b\u043d\u044b\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043f\u043e <a href=\"https:\/\/github.com\/bashkirtsevich\/ftx\/blob\/master\/consts\/wspr.py#L55\" rel=\"noopener noreferrer nofollow\">\u044d\u0442\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0435<\/a>.<\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>decode<\/code> \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 \u0432 \u0434\u0435\u043a\u043e\u0434\u0435\u0440 \u0424\u0430\u043d\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432, \u043f\u043e\u043b\u0443\u0447\u0430\u044f \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u0431\u0430\u0439\u0442\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u0438\u043d\u044f\u0442\u043e\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 <code>decoded<\/code>.<\/p>\n<pre><code class=\"python\">WSPR_NUM_BITS = 81WSPR_FANO_THRESHOLD = 60WSPR_DECODER_LIM = 10000class WSPRMonitor(AbstractMonitor):    ...    def decode(self, **kwargs) -&gt; typing.Iterator[WSPRLogItem]:    ...                          decoded = fano(                              symbols, WSPR_NUM_BITS, WSPR_METRIC_TABLE, WSPR_FANO_THRESHOLD, WSPR_DECODER_LIM                          )                          idt += 1                          if self.quick_mode:                              break                      ib += 1                  if decoded is not None:                      metric, cycles, dec_data = decoded                      decodes_pass += 1                      payload = dec_data.tobytes()    ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f <code>payload<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432 \u0441\u0435\u0431\u0435 \u0431\u0430\u0439\u0442\u044b WSPR \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f.<\/p>\n<h2>\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u0438\u0433\u043d\u0430\u043b\u0430<\/h2>\n<p>\u041f\u0440\u0438 \u043c\u043d\u043e\u0433\u043e\u043f\u0440\u043e\u0445\u043e\u0434\u043d\u043e\u043c \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438, \u043f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u0434\u0435\u0442\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0438\u0437 \u0441\u0438\u0433\u043d\u0430\u043b\u0430, \u0432 WSPR \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f \u0441\u043f\u0435\u043a\u0442\u0440\u0430, \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u043d\u044f\u0442\u044b\u0445 \u0442\u043e\u043d\u043e\u0432 \u043f\u043e\u0434\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u0447\u0430\u0441\u0442\u043e\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438, \u2014 \u044d\u0442\u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u044b\u0434\u0435\u043b\u044f\u0442\u044c \u0441\u043b\u0430\u0431\u044b\u0435 \u0441\u0438\u0433\u043d\u0430\u043b\u044b \u0432 \u0441\u043f\u0435\u043a\u0442\u0440\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u043f\u0435\u0440\u0435\u043a\u0440\u044b\u0432\u0430\u043b\u0438\u0441\u044c \u0441\u0438\u043b\u044c\u043d\u044b\u043c\u0438.<\/p>\n<p>\u0424\u0438\u043b\u044c\u0442\u0440 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 <code>subtract_signal<\/code>:<\/p>\n<pre><code class=\"python\">class WSPRMonitor(AbstractMonitor):    ...    def subtract_signal(self, signal: npt.NDArray[np.complex128], f0, shift0: int, drift0,                       channel_symbols: npt.NDArray[np.uint8]):        filtr = 360        samples = WSPR_ND * self.symbol_len        cs_rep = np.repeat(channel_symbols - 1.5, self.symbol_len)        ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041c\u0430\u0441\u0441\u0438\u0432 <code>cs_rep<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043c\u0430\u0441\u0441\u0438\u0432 \u0442\u043e\u043d\u043e\u0432 \u0441\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0445 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u043e\u0442\u044b, \u0434\u043b\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f \u0442\u043e\u043d\u0430\u043c 4-FSK.<\/p>\n<pre><code class=\"python\">        ...        idx = np.repeat(np.arange(WSPR_ND), self.symbol_len)        drift_eff = (drift0 \/ 2.0) * (idx - WSPR_ND \/ 2.0) \/ (WSPR_ND \/ 2.0)        freq = f0 + drift_eff + cs_rep * self.df        phase = 2.0 * np.pi * np.cumsum(freq) * self.dt        ref = np.exp(1j * phase)        ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0412 phase \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0440\u0435\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f \u0444\u0430\u0437\u044b \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0447\u0430\u0441\u0442\u043e\u0442 \u0442\u043e\u043d\u043e\u0432 <code>freq<\/code> (\u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u043e\u0442\u044b <code>f0<\/code>), \u043c\u0430\u0441\u0441\u0438\u0432 <code>ref<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u044d\u0442\u0430\u043b\u043e\u043d\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u043b\u0435\u043a\u0441\u043d\u044b\u0439 \u0441\u0438\u0433\u043d\u0430\u043b.<\/p>\n<pre><code class=\"python\">        ...        start = max(shift0, 0)        end = min(start + samples, len(signal))        segment = signal[start:end]        env = segment * np.conj(ref)        ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0414\u0435\u0442\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0433\u0438\u0431\u0430\u044e\u0449\u0435\u0439 \u0441\u0438\u0433\u043d\u0430\u043b\u0430 (\u043c\u0430\u0441\u0441\u0438\u0432 <code>env<\/code>).<\/p>\n<pre><code class=\"python\">        ...        weights = np.sin(np.pi * np.arange(filtr) \/ (filtr - 1))        weights \/= weights.sum()        ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0424\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0433\u043b\u0430\u0436\u0438\u0432\u0430\u044e\u0449\u0435\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0441\u0438\u043d\u0443\u0441\u0430, \u0434\u043b\u044f \u043f\u043e\u0434\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u044b\u0441\u043e\u043a\u043e\u0447\u0430\u0441\u0442\u043e\u0442\u043d\u044b\u0445 \u0444\u043b\u0443\u043a\u0442\u0443\u0430\u0446\u0438\u0439, \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0449\u0438\u0445 \u043f\u0440\u0438 \u0434\u0435\u0442\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u043e\u0433\u0438\u0431\u0430\u044e\u0449\u0435\u0439.<\/p>\n<pre><code class=\"python\">        ...        env_sm = np.convolve(env, weights, mode=\"same\")        partial_sum = np.cumsum(weights)        filtr_half = filtr \/\/ 2        corr_f = np.ones(samples)        corr_f[:filtr_half] = partial_sum[filtr_half: filtr]        corr_f[-filtr_half:] = np.flip(partial_sum[filtr_half: filtr])        ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0421\u0432\u0435\u0440\u0442\u043a\u0430 \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0441\u043e \u0441\u0433\u043b\u0430\u0436\u0438\u0432\u0430\u044e\u0449\u0435\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0444\u0438\u043b\u044c\u0442\u0440 \u043d\u0438\u0436\u043d\u0438\u0445 \u0447\u0430\u0441\u0442\u043e\u0442 (<code>env_sm<\/code>). \u0414\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0446\u0438\u0438 \u043a\u0440\u0430\u0435\u0432\u044b\u0445 \u044d\u0444\u0444\u0435\u043a\u0442\u043e\u0432 \u043f\u043e\u0441\u043b\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043e\u043a\u043d\u0430, \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u0444\u0430\u043a\u0442\u043e\u0440 <code>corr_f<\/code> \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043a\u0443\u043c\u0443\u043b\u044f\u0442\u0438\u0432\u043d\u043e\u0439 \u0441\u0443\u043c\u043c\u044b \u0432\u0435\u0441\u043e\u0432 \u0444\u0438\u043b\u044c\u0442\u0440\u0430 (<code>partial_sum<\/code>). \u041a\u043e\u0440\u0440\u0435\u043a\u0446\u0438\u044f \u043a\u0440\u0430\u0435\u0432\u044b\u0445 \u044d\u0444\u0444\u0435\u043a\u0442\u043e\u0432 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u043a\u043e\u043c\u043f\u0435\u043d\u0441\u0430\u0446\u0438\u0438 \u043f\u043e\u0442\u0435\u0440\u0438 \u044d\u043d\u0435\u0440\u0433\u0438\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u043d\u0430 \u043a\u0440\u0430\u044f\u0445 \u0444\u0438\u043b\u044c\u0442\u0440\u0430.<\/p>\n<pre><code class=\"python\">        ...        reconstruction = (env_sm \/ corr_f) * ref        signal[start:end] -= reconstruction[start:end]<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0412 \u043c\u0430\u0441\u0441\u0438\u0432\u0435 <code>reconstruction<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u044d\u0442\u0430\u043b\u043e\u043d\u043d\u044b\u0439 \u0441\u0438\u0433\u043d\u0430\u043b, \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0439 \u043f\u043e \u0444\u0430\u0437\u0435 \u0438 \u0430\u043c\u043f\u043b\u0438\u0442\u0443\u0434\u0435 \u0441 \u0441\u0438\u0433\u043d\u0430\u043b\u0430\u043c\u0438 \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u043c \u0441\u043f\u0435\u043a\u0442\u0440\u0435. \u0418\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0440\u0435\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0438\u0437 \u043e\u0431\u0449\u0435\u0433\u043e \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0435\u0439 \u0440\u0430\u0437\u043d\u043e\u0441\u0442\u0438 \u043c\u0435\u0436\u0434\u0443 signal \u0438 reconstruction.<\/p>\n<p>\u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0444\u0438\u043b\u044c\u0442\u0440\u0430 <code>subtract_signal<\/code> \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0430\u0434\u0430\u043f\u0442\u0438\u0432\u043d\u043e\u0439 \u043e\u0433\u0438\u0431\u0430\u044e\u0449\u0435\u0439, \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u044e\u0449\u0435\u0439 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0442\u043e\u0447\u043d\u0443\u044e \u0440\u0435\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044e \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u0441\u0438\u0433\u043d\u0430\u043b\u0430, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0442\u043e\u0447\u043d\u043e\u0439 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u0430.<\/p>\n<h2>\u041f\u043e\u0434\u0441\u0447\u0435\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043e\u0448\u0438\u0431\u043e\u043a \u0432 \u043f\u0440\u0438\u043d\u044f\u0442\u043e\u043c \u0441\u0438\u0433\u043d\u0430\u043b\u0435<\/h2>\n<p>\u0414\u043b\u044f \u043e\u0446\u0435\u043d\u043a\u0438 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u043f\u0440\u0438\u043d\u044f\u0442\u043e\u0433\u043e \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0432 WSPR \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0434\u0441\u0447\u0435\u0442 \u043e\u0448\u0438\u0431\u043e\u043a \u043c\u0435\u0436\u0434\u0443 \u0441\u044b\u0440\u044b\u043c\u0438 \u043f\u0440\u0438\u043d\u044f\u0442\u044b\u043c\u0438 \u0441\u0438\u043c\u0432\u043e\u043b\u0430\u043c\u0438 \u0438 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u043c\u0438 \u043a\u043e\u0434\u0430\u043c\u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0446\u0438\u0438 \u043e\u0448\u0438\u0431\u043e\u043a \u0441\u0438\u043c\u0432\u043e\u043b\u0430\u043c\u0438.<\/p>\n<pre><code class=\"python\">class WSPRMonitor(AbstractMonitor):    ...    @staticmethod    def count_sym_err(symbols: npt.NDArray[np.uint8], channel_symbols: npt.NDArray[np.uint8]) -&gt; int:        cw = (channel_symbols &gt;= 2).astype(np.uint8)        WSPRMonitor.deinterleave(cw)        sym_bin = (symbols &gt; 127).astype(np.uint8)        err_count = int(np.sum(sym_bin != cw))        return err_count<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>count_sym_err<\/code> \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434 \u044d\u0442\u0430\u043b\u043e\u043d\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b <code>symbols<\/code> \u0438 \u0441\u044b\u0440\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 <code>channel_symbols<\/code>. \u041f\u0440\u0438\u043d\u044f\u0442\u044b\u0435 \u0438\u0437 \u044d\u0444\u0438\u0440\u0430 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u043f\u043e\u0434\u0432\u0435\u0440\u0433\u0430\u044e\u0442\u0441\u044f \u0434\u0435\u0438\u043d\u0442\u0435\u0440\u043b\u0438\u0432\u0438\u043d\u0433\u0443 \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u043e\u0434\u0441\u0447\u0435\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432, \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442.<\/p>\n<h2>\u0414\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439<\/h2>\n<p>\u0424\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u044d\u0442\u0430\u043f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0432 WSPR. \u041f\u043e\u0441\u043b\u0435 \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0438\u0437 <code>dec_data<\/code>, \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0430\u043c\u043e\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u0440\u0438\u043a \u043e \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u0438\u0433\u043d\u0430\u043b\u0430, \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f \u043f\u0440\u0438\u043d\u044f\u0442\u043e\u0433\u043e \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0438 \u0432\u044b\u0432\u043e\u0434 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430.<\/p>\n<pre><code class=\"python\">class WSPRMonitor(AbstractMonitor):    ...    def decode(self, **kwargs) -&gt; typing.Iterator[WSPRLogItem]:        ...        payload = dec_data.tobytes()        msg = WSPRMessage.decode(payload)        ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0412 <code>msg<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\u043c WSPR. \u0414\u0435\u043a\u043e\u0434\u0435\u0440 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0431\u044b\u043b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b \u0432 <a href=\"https:\/\/habr.com\/en\/articles\/1017728\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0430\u0442\u044c\u0438<\/a>.<\/p>\n<pre><code class=\"python\">        ...        dt_print = shift1 * self.dt - 1.0        freq_print = (WSPR_CENTER_FREQ + f1) \/ 1e6        payload = msg.encode()        tones = wspr_encode(payload)        chan_sym = np.fromiter(tones, dtype=np.uint8)        self.subtract_signal(iq_signal, f1, shift1, drift1, chan_sym)        sym_err = self.count_sym_err(symbols, chan_sym)        yield WSPRLogItem(            snr=cand.snr,            dT=dt_print,            dF=freq_print,            payload=payload,            crc=0,            BER=sym_err,            drift=drift1,            decode_pass=decodes_pass        )<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0414\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043f\u043e\u0434\u0432\u0435\u0440\u0433\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u043c\u0443 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u043c\u0443 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 WSPR \u0441\u0438\u0433\u043d\u0430\u043b, \u0434\u043b\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0438 \u043f\u043e\u0434\u0441\u0447\u0435\u0442\u0430 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043e\u0448\u0438\u0431\u043e\u043a \u0432 \u043f\u0440\u0438\u043d\u044f\u0442\u044b\u0445 \u0441\u0438\u043c\u0432\u043e\u043b\u0430\u0445.<\/p>\n<p><code>WSPRLogItem<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0438 \u043e\u0446\u0435\u043d\u043a\u0438 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u0441\u0438\u0433\u043d\u0430\u043b\u0430:<\/p>\n<pre><code class=\"python\">@dataclassclass LogItem:   snr: float   dT: float   dF: float   payload: typing.ByteString   crc: int@dataclassclass WSPRLogItem(LogItem):   BER: int   drift: float   decode_pass: int<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u043b\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0434\u0435\u043a\u043e\u0434\u0435\u0440\u0430 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043a\u043b\u0430\u0441\u0441\u0430 <code>WSPRMonitor<\/code>:<\/p>\n<pre><code class=\"python\">import timefrom scipy.io.wavfile import readfrom decoders.wspr import WSPRMonitorfrom msg.message import WSPRMsgServerdef main():    sample_rate, data = read(\"examples\/signal.wav\")    msg_svr = WSPRMsgServer()    mon = WSPRMonitor(        sample_rate=sample_rate    )    mon.monitor_process(data)    for it in mon.decode():        msg = msg_svr.decode(it.payload)        print(            f\"dB: {it.snr:.3f}\\t\"            f\"T: {it.dT:.3f}\\t\"            f\"DF: {it.dF:.3f}\\t\"            f\"BER: {it.BER}\\t\"            f\"drift: {it.drift}\\t\"            f\"pass: {it.decode_pass}\\t\"            f\"Message text: {msg}\"        )if __name__ == '__main__':    main()<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f WSPR:<\/p>\n<pre><code>dB: 43.265T: -1.000DF: 0.002BER: 0drift: 0pass: 1Message text: R9FEU LO87 50<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0412 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u044e\u0449\u0435\u0439 \u0446\u0438\u043a\u043b \u0441\u0442\u0430\u0442\u044c\u0435, \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u043d\u043e\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 WSPR \u0431\u044b\u043b\u0438 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u044b \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0438 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u044b \u0446\u0438\u0444\u0440\u043e\u0432\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u043e\u0432, \u043f\u0435\u0440\u0435\u043d\u043e\u0441 \u0441\u043f\u0435\u043a\u0442\u0440\u0430, \u0434\u0435\u0442\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0441\u043b\u0430\u0431\u044b\u0445 \u0441\u0438\u0433\u043d\u0430\u043b\u043e\u0432 \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u043d\u044b\u043c\u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u043c\u0438 \u043f\u0440\u0438 \u043e\u0447\u0435\u043d\u044c \u043d\u0438\u0437\u043a\u0438\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u0445 SNR, \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u043a\u043e\u0440\u0440\u0435\u043a\u0446\u0438\u0438 \u043e\u0448\u0438\u0431\u043e\u043a \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0441\u0432\u0435\u0440\u0442\u043e\u0447\u043d\u044b\u0445 \u043a\u043e\u0434\u043e\u0432.<\/p>\n<p>\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b WSPR \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441 \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u043e\u0432 \u0441\u0432\u044f\u0437\u0438, \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u044b\u0445 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u0438 \u043c\u0430\u043b\u044b\u0445 \u043c\u043e\u0449\u043d\u043e\u0441\u0442\u044f\u0445 \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u0447\u0438\u043a\u043e\u0432, \u043f\u0440\u0438 \u043e\u0447\u0435\u043d\u044c \u043d\u0438\u0437\u043a\u0438\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u0445 SNR, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043e\u0431\u043b\u0430\u0434\u0430\u044f \u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c\u044e \u043a \u043f\u043e\u043c\u0435\u0445\u0430\u043c. \u041e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u0437\u0430\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u044e\u0442 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u0446\u0438\u0444\u0440\u043e\u0432\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u043e\u0432 \u0438 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u044b, \u043b\u0435\u0436\u0430\u0449\u0438\u0435 \u0432 \u0438\u0445 \u043e\u0441\u043d\u043e\u0432\u0435.<\/p>\n<details class=\"spoiler\">\n<summary>\u041e\u0442 \u0430\u0432\u0442\u043e\u0440\u0430 \u0441\u0442\u0430\u0442\u044c\u0438:<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f WSPR \u0434\u0435\u043a\u043e\u0434\u0435\u0440\u0430 \u043d\u0430 Python \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u0430 \u0432\u043e \u043c\u043d\u043e\u0433\u043e\u043c \u043e\u0449\u0443\u0442\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 numpy, \u043f\u0435\u0440\u0435\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432\u043e\u0441\u043f\u0440\u0438\u044f\u0442\u0438\u0435 \u0441\u0438\u0433\u043d\u0430\u043b\u043e\u0432, \u0442\u0430\u043a \u043a\u0430\u043a \u0432\u0441\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u0438\u0433\u043d\u0430\u043b\u043e\u0432 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 I\/Q-\u0444\u043e\u0440\u043c\u0435, \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043a\u043e\u043c\u043f\u043b\u0435\u043a\u0441\u043d\u044b\u0445 \u044d\u043a\u0441\u043f\u043e\u043d\u0435\u043d\u0442, \u0447\u0442\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u043e \u043f\u0440\u0435\u043e\u0434\u043e\u043b\u0435\u043d\u0438\u044f \u043d\u0435\u043a\u043e\u0435\u0433\u043e \u043f\u043e\u0440\u043e\u0433\u0430 \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f.<\/p>\n<p>\u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 Python \u043f\u0440\u043e\u0438\u0433\u0440\u044b\u0432\u0430\u0435\u0442 \u043f\u043e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u043d\u0430 \u0421\u0438, \u0445\u043e\u0442\u044c \u0438 \u0431\u044b\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u044b \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 numpy \u0438 jit-\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u0435 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439.<\/p>\n<p>\u041f\u043e \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u0438, \u043d\u0430\u0447\u0430\u0432\u0448\u0435\u0439\u0441\u044f \u0441 Q65, \u0430\u0432\u0442\u043e\u0440 \u0432\u044b\u0440\u0430\u0436\u0430\u0435\u0442 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u043d\u043e\u0441\u0442\u044c \u0432\u0441\u0435\u043c \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044f\u043c \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430 \u0441\u0442\u0430\u0442\u0435\u0439 \u0438 \u043b\u0438\u0446\u0430\u043c, \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0432 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 WSPR.<\/p>\n<\/div>\n<\/details>\n<h2>\u0421\u0441\u044b\u043b\u043a\u0438<\/h2>\n<ul>\n<li>\n<p><a href=\"https:\/\/github.com\/bashkirtsevich\/ftx\/tree\/master\" rel=\"noopener noreferrer nofollow\">\u041e\u0431\u0449\u0438\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 WSPR, Q65, FTX \u0438 MSKX Python<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/wsjt.sourceforge.io\/\" rel=\"noopener noreferrer nofollow\">\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 WSJT, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0430\u044f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b WSPR<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.wsprnet.org\/drupal\/wsprnet\/map\" rel=\"noopener noreferrer nofollow\">WSPR-\u0430\u0433\u0440\u0435\u0433\u0430\u0442\u043e\u0440<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/k9an\/old_wsprcan\" rel=\"noopener noreferrer nofollow\">\u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 K9AN \u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0434\u0435\u043a\u043e\u0434\u0435\u0440\u0430 \u043d\u0430 \u0421\u0438<\/a><\/p>\n<\/li>\n<\/ul>\n<\/div>\n<p>\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/1027722\/\">https:\/\/habr.com\/ru\/articles\/1027722\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>WSPR \u2014 \u0446\u0438\u0444\u0440\u043e\u0432\u043e\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b\u0439 \u0414\u0436\u043e \u0422\u0435\u0439\u043b\u043e\u0440\u043e\u043c (K1JT) \u0432 2008-2009 \u0433\u043e\u0434\u0430\u0445, \u0441 \u0446\u0435\u043b\u044c\u044e \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0440\u0430\u0434\u0438\u043e\u0441\u0438\u0433\u043d\u0430\u043b\u043e\u0432 \u043e\u0442 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0432\u043e\u043b\u043d\u043e\u0432\u044b\u0445 \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u0447\u0438\u043a\u043e\u0432 \u043c\u0430\u043b\u043e\u0439 \u0438 \u0441\u0432\u0435\u0440\u0445\u043c\u0430\u043b\u043e\u0439 \u043c\u043e\u0449\u043d\u043e\u0441\u0442\u0438. \u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u0431\u044b\u043b\u0438 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u044b \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u043f\u043e\u043c\u0435\u0445\u043e\u0437\u0430\u0449\u0438\u0449\u0435\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0435\u0433\u043e \u0432 \u044d\u0444\u0438\u0440. \u0412 \u044d\u0442\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0430\u0442\u044c\u0438 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0434\u0435\u0442\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u043c\u043e\u0433\u043e \u0438\u0437 \u0441\u0438\u0433\u043d\u0430\u043b\u0430.\u0421\u0442\u0430\u0442\u044c\u044f \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430 \u0440\u0430\u0434\u0438\u043e\u043b\u044e\u0431\u0438\u0442\u0435\u043b\u044f\u043c, \u043a\u0430\u043a \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u043c, \u0442\u0430\u043a \u0438 \u043d\u0435 \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u043c \u0441 WSPR, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0442\u0435\u043c, \u043a\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442\u0441\u044f \u0442\u0435\u043c\u043e\u0439 \u0446\u0438\u0444\u0440\u043e\u0432\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u043e\u0432 \u0438 \u0445\u043e\u0447\u0435\u0442 \u043f\u043e\u043d\u044f\u0442\u044c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430.\u041e\u0431\u0449\u0435\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0431\u044b\u043b\u0438 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u044b \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u044b \u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b, \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u0430.\u0420\u0438\u0441\u0443\u043d\u043e\u043a 1: \u041e\u0431\u0449\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 (\u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u044f \u043f\u043e \u0443\u0440\u043e\u0432\u043d\u044f\u043c OSI \u0443\u0441\u043b\u043e\u0432\u043d\u0430\u044f).\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0434\u0435\u0442\u0435\u043a\u0446\u0438\u0438 \u0438 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e \u0441\u0432\u043e\u0435\u0439 \u0441\u0443\u0442\u0438 \u0434\u0438\u0430\u043c\u0435\u0442\u0440\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0442\u0438\u0432\u043e\u043f\u043e\u043b\u043e\u0436\u0435\u043d \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0443 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u041e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u044b\u0439 \u0441\u0438\u0433\u043d\u0430\u043b \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0432\u0435\u0440\u0433\u0430\u0435\u0442\u0441\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438 \u0434\u0430\u0443\u043d\u0441\u0435\u043c\u043f\u043b\u0438\u043d\u0433\u0443 \u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438 \u0432 \u0447\u0430\u0441\u0442\u043e\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0432\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 (\u0434\u043b\u044f \u0447\u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u044b), \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0437\u0432\u043b\u0435\u0447\u044c \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u0434\u0430\u043d\u043d\u044b\u0445; \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u0437\u0430\u0442\u0435\u043c \u043f\u043e\u0434\u0432\u0435\u0440\u0433\u0430\u044e\u0442\u0441\u044f \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u0441 \u043a\u043e\u0440\u0440\u0435\u043a\u0446\u0438\u0435\u0439 \u043e\u0448\u0438\u0431\u043e\u043a, \u0447\u0442\u043e \u0443\u0436\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u043e\u0435 WSPR-\u043c\u0430\u044f\u043a\u043e\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435.\u041f\u0435\u0440\u0435\u043d\u043e\u0441 \u0441\u043f\u0435\u043a\u0442\u0440\u0430 \u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f\u0412\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0437\u0432\u0443\u043a\u043e\u0432\u043e\u0439 \u0441\u0438\u0433\u043d\u0430\u043b \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432 WSPR \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u0441 \u0447\u0430\u0441\u0442\u043e\u0442\u043e\u0439 \u0434\u0438\u0441\u043a\u0440\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u0438 12.0 \u043a\u0413\u0446, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u043e\u0442\u0430 \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f \u0432 \u0437\u043e\u043d\u0435 1.5 \u043a\u0413\u0446; \u0442\u0430\u043a \u043a\u0430\u043a \u0441\u0438\u0433\u043d\u0430\u043b \u043d\u0430\u043a\u0430\u043f\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0438 110 \u0441\u0435\u043a\u0443\u043d\u0434, \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043e\u0431\u044a\u0435\u043c \u0437\u0432\u0443\u043a\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0443\u0436\u043d\u0430 \u043f\u043e\u043b\u043e\u0441\u0430 \u0448\u0438\u0440\u0438\u043d\u043e\u0439 self.sample_rate \/ WSPR_DECIMATION = 12000 \/ 32 = 375 \u0413\u0446, \u0432\u0441\u0451 \u0447\u0442\u043e \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u043c\u0438 \u044d\u0442\u043e\u0439 \u043f\u043e\u043b\u043e\u0441\u044b \u2014 \u0431\u0435\u0441\u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0439 \u0448\u0443\u043c.\u0414\u0430\u0443\u043d\u0441\u0435\u043c\u043f\u043b\u0438\u043d\u0433 \u0438 \u0434\u0435\u0446\u0438\u043c\u0430\u0446\u0438\u044f \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0432 WSPR \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432 \u0447\u0430\u0441\u0442\u043e\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u044f\u043c\u043e\u0435 \u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0424\u0443\u0440\u044c\u0435.WSPR_DECIMATION = 32WSPR_CENTER_FREQ = 1500class WSPRMonitor(AbstractMonitor):    __slots__ = [        &#171;sample_rate&#187;,        &#171;signal&#187;,        &#8230;    ]    def __init__(self, sample_rate: int):        self.signal = np.zeros(0, dtype=np.float64)        self.sample_rate = sample_rate        &#8230;    def downsample(self) -&gt; npt.NDArray[np.complex128]:        fft_target = 46080        fft_src = fft_target * WSPR_DECIMATION        frame = np.pad(self.signal[:fft_src], (0, max(0, fft_src &#8212; len(self.signal))))        spec = np.fft.rfft(frame)        df = self.sample_rate \/ fft_src        i0 = int(WSPR_CENTER_FREQ \/ df + 0.5)        sub_spec = spec[i0: i0 + fft_target]        signal = np.fft.ifft(sub_spec) * (fft_target \/ fft_src) * 2        return signal.astype(np.complex128)    &#8230;    def monitor_process(self, frame: npt.NDArray[np.int16]) -&gt; None:        frame_float = frame.astype(np.float32) \/ np.iinfo(np.int16).max        self.signal = np.concat([self.signal, frame_float])    &#8230;\u041f\u043e\u043b\u0435 sample_rate \u0445\u0440\u0430\u043d\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0447\u0430\u0441\u0442\u043e\u0442\u0435 \u0434\u0438\u0441\u043a\u0440\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u0441\u0438\u0433\u043d\u0430\u043b\u0430, \u0432 signal \u043d\u0430\u043a\u0430\u043f\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u0430\u043c\u043e\u0433\u043e \u0441\u0438\u0433\u043d\u0430\u043b\u0430.\u0424\u0443\u043d\u043a\u0446\u0438\u044f downsample \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442 \u043f\u0435\u0440\u0435\u043d\u043e\u0441 \u0441\u043f\u0435\u043a\u0442\u0440\u0430 \u0438\u0437 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0432\u044b\u0441\u043e\u043a\u0438\u0445 \u0447\u0430\u0441\u0442\u043e\u0442 \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u043d\u0438\u0437\u043a\u0438\u0445, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044f \u0434\u0435\u0446\u0438\u043c\u0430\u0446\u0438\u044e \u0441\u0438\u0433\u043d\u0430\u043b\u0430.\u0412 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e spec \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0424\u0443\u0440\u044c\u0435 \u0434\u043b\u044f \u0432\u0435\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u0430.\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435: \u0442\u043e \u0435\u0441\u0442\u044c \u0432 \u0441\u043f\u0435\u043a\u0442\u0440\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u043e\u0442\u044b, \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0441 \u043e\u0442\u0440\u0438\u0446\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u0447\u0430\u0441\u0442\u043e\u0442\u0430\u043c\u0438 \u0437\u0435\u0440\u043a\u0430\u043b\u044c\u043d\u043e \u0441\u0438\u043c\u043c\u0435\u0442\u0440\u0438\u0447\u043d\u0430 \u0438 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f (\u0440\u0438\u0441\u0443\u043d\u043e\u043a 2).\u0420\u0438\u0441\u0443\u043d\u043e\u043a 2: \u043e\u0442\u043b\u0438\u0447\u0438\u0435 FFT \u0438 RFFT\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f df \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0446\u0435\u043b\u0435\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u043e\u0442\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0424\u0443\u0440\u044c\u0435-\u0431\u0438\u043d\u043e\u0432 \u043f\u043e\u0441\u043b\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f.\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f i0 \u0437\u0430\u0434\u0430\u0435\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0444\u0438\u043b\u044c\u0442\u0440\u0430 \u0432 \u0447\u0430\u0441\u0442\u043e\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438, \u2014 \u0438\u043d\u0434\u0435\u043a\u0441 \u0447\u0430\u0441\u0442\u043e\u0442\u043d\u043e\u0433\u043e \u0431\u0438\u043d\u0430 \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u043c \u0441\u043f\u0435\u043a\u0442\u0440\u0435, \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u043e\u0441\u0430 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u043d\u0438\u044f; \u043f\u043e\u043b\u043e\u0441\u0430 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u043d\u0438\u044f \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c fft_target.\u041c\u0430\u0441\u0441\u0438\u0432 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 sub_spec \u2014 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u043d\u043d\u044b\u0439 \u0438 \u043e\u0442\u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u043e \u0447\u0430\u0441\u0442\u043e\u0442\u0435 \u0441\u043f\u0435\u043a\u0442\u0440 \u0441\u0438\u0433\u043d\u0430. \u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u0438\u0437 \u0447\u0430\u0441\u0442\u043e\u0442\u043d\u043e\u0439 \u0432\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u044b\u043c \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0424\u0443\u0440\u044c\u0435; \u0441\u0438\u0433\u043d\u0430\u043b \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0432\u0435\u0440\u0433\u0430\u0435\u0442\u0441\u044f \u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0430\u043c\u043f\u043b\u0438\u0442\u0443\u0434 (AGC).\u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0424\u0443\u0440\u044c\u0435, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0441\u0438\u0433\u043d\u0430\u043b \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u043a\u043e\u043c\u043f\u043b\u0435\u043a\u0441\u043d\u044b\u0445 \u0447\u0438\u0441\u0435\u043b, \u2014 \u0442\u043e \u0435\u0441\u0442\u044c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0441\u0438\u0433\u043d\u0430\u043b \u0432 I\/Q \u0444\u043e\u0440\u043c\u0435  (\u0447\u0442\u043e \u044d\u043a\u0432\u0438\u0432\u0430\u043b\u0435\u043d\u0442\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u0438 \u042d\u0439\u043b\u0435\u0440\u0430 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 \u043a\u043e\u043c\u043f\u043b\u0435\u043a\u0441\u043d\u043e\u0439 \u044d\u043a\u0441\u043f\u043e\u043d\u0435\u043d\u0442\u044b ).\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043f\u0435\u0440\u0435\u043d\u043e\u0441 \u0441\u043f\u0435\u043a\u0442\u0440\u0430 \u0438 \u0434\u0430\u0443\u043d\u0441\u0435\u043c\u043f\u043b\u0438\u043d\u0433 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0438\u0442\u044c \u0434\u0435\u0446\u0438\u043c\u0430\u0446\u0438\u044e \u0431\u0435\u0437 \u043f\u043e\u0442\u0435\u0440\u044c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u043d\u044c\u0448\u0443\u044e \u0447\u0430\u0441\u0442\u043e\u0442\u0443 \u0434\u0438\u0441\u043a\u0440\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u0438, \u0447\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u0442 \u043e\u0431\u044a\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0445, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u043c\u0435\u043d\u044c\u0448\u0435\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0438 \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u0441\u0438\u0433\u043d\u0430\u043b\u0430; \u0442\u0430\u043a\u0436\u0435 \u0432 \u0447\u0430\u0441\u0442\u043e\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0432\u044b\u0441\u043e\u043a\u043e\u0447\u0430\u0441\u0442\u043e\u0442\u043d\u044b\u0445 \u0438 \u0432\u043d\u0435\u043f\u043e\u043b\u043e\u0441\u043d\u044b\u0445 \u0448\u0443\u043c\u043e\u0432, \u0447\u0442\u043e \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u043b\u0438\u044f\u0435\u0442 \u043d\u0430 SNR.\u0414\u0435\u0442\u0435\u043a\u0446\u0438\u044f \u0441\u0438\u0433\u043d\u0430\u043b\u0430\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 \u0435\u0433\u043e \u0434\u0435\u0442\u0435\u043a\u0446\u0438\u0438. \u0424\u0443\u043d\u043a\u0446\u0438\u044f decode \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u00a0 I\/Q \u0441\u0438\u0433\u043d\u0430\u043b \u043f\u043e\u0441\u043b\u0435 \u0434\u0430\u0443\u043d\u0441\u0435\u043c\u043f\u043b\u0438\u043d\u0433\u0430.class WSPRMonitor(AbstractMonitor):    __slots__ = [        &#8230;        &#171;symbol_len&#187;,        &#171;df&#187;,        &#171;df2&#187;,        &#171;dt&#187;,        &#171;decode_passes&#187;,        &#8230;    ]    &#8230;    def __init__(self, sample_rate: int):        &#8230;        down_sample_rate = self.sample_rate \/ WSPR_DECIMATION        self.symbol_len = int(down_sample_rate * WSPR_SYMBOL_PERIOD)        self.df = down_sample_rate \/ self.symbol_len        self.df2 = self.df \/ 2        self.dt = 1 \/ down_sample_rate        self.decode_passes = 3        &#8230;    def decode(self, **kwargs) -&gt; typing.Iterator[WSPRLogItem]:        iq_signal = self.downsample()        symbols = np.zeros(WSPR_NUM_BITS * 2, dtype=np.uint8)        fft_step = 128        fft_size = fft_step * 4        fft_count = 4 * (len(iq_signal) \/\/ fft_size) &#8212; 1        smooth = np.sin((np.pi \/ fft_size) * np.arange(fft_size))        pwr_spec = np.zeros((fft_count, fft_size))        block_size = 1        max_drift = 4        min_sync_2 = WSPR_MIN_SYNC_2        decodes_pass = 0        &#8230;\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442\u0441\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0441\u043f\u0435\u043a\u0442\u0440\u0430 I\/Q \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u2014 fft_step, fft_size, fft_count. \u041f\u043e\u0434\u0433\u043e\u0442\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u0433\u043b\u0430\u0436\u0438\u0432\u0430\u044e\u0449\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043e\u043a\u043e\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0424\u0443\u0440\u044c\u0435.\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435: \u0432\u043c\u0435\u0441\u0442\u043e \u043e\u043a\u043d\u0430 \u0425\u0430\u043d\u043d\u0430 \u0421\u0442\u0438\u0432 \u0424\u0440\u0430\u043d\u043a\u0438 (K9AN) \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043b \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u043b\u0443\u043f\u0435\u0440\u0438\u043e\u0434 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0441\u0438\u043d\u0443\u0441. \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0425\u0430\u043d\u043d\u0430, \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0441\u0438\u043d\u0443\u0441 \u0447\u0443\u0442\u044c \u0445\u0443\u0436\u0435 \u043f\u043e\u0434\u0430\u0432\u043b\u044f\u0435\u0442 \u0431\u043e\u043a\u043e\u0432\u044b\u0435 \u043b\u0435\u043f\u0435\u0441\u0442\u043a\u0438 \u0432 \u0441\u043f\u0435\u043a\u0442\u0440\u0435.WSPR_MIN_SYNC_1 = 0.10WSPR_MIN_SYNC_2 = 0.12&#8230;\u041a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b WSPR_MIN_SYNC_1, WSPR_MIN_SYNC_2 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d\u0438\u044f \u0447\u0430\u0441\u0442\u043e\u0442\u044b \u043f\u0440\u0438 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438.\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0446\u0438\u043a\u043b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u0430:        &#8230;        for iteration in range(self.decode_passes):            if iteration == 1 and decodes_pass == 0 and self.decode_passes &gt; 2:                iteration = 2            if iteration == 2:                block_size = 4                max_drift = 0                min_sync_2 = WSPR_MIN_SYNC_1            decodes_pass = 0        &#8230;\u0423\u0441\u0440\u0435\u0434\u043d\u0435\u043d\u0438\u0435 \u0441\u043f\u0435\u043a\u0442\u0440\u0430\u0412 WSPR \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u043c\u044b\u0435 \u0441\u0438\u0433\u043d\u0430\u043b\u044b \u043c\u043e\u0433\u0443\u0442 \u0438\u043c\u0435\u0442\u044c \u043e\u0447\u0435\u043d\u044c \u043d\u0438\u0437\u043a\u0438\u0439 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c SNR, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0438\u0445 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435\u0432\u0438\u0434\u0438\u043c\u044b\u043c\u0438. \u0412 WSPR \u0434\u043b\u044f \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0441\u043b\u0430\u0431\u044b\u0445 \u0441\u0438\u0433\u043d\u0430\u043b\u043e\u0432 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0443\u0441\u0440\u0435\u0434\u043d\u0435\u043d\u0438\u044f \u0441\u043f\u0435\u043a\u0442\u0440\u0430 \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445. \u0422\u0430\u043a \u043a\u0430\u043a \u0448\u0443\u043c \u0432 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u0441\u043b\u0443\u0447\u0430\u0435\u0432 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u043c, \u0441 \u043d\u0443\u043b\u0435\u0432\u044b\u043c \u043c\u0430\u0442. \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0435\u043c \u0438 \u043d\u0435 \u043a\u043e\u0440\u0440\u0435\u043b\u0438\u0440\u0443\u0435\u0442 \u0434\u0440\u0443\u0433 \u0441 \u0434\u0440\u0443\u0433\u043e\u043c, \u0430 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0439 \u0441\u0438\u0433\u043d\u0430\u043b \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u043e\u0442\u0435 \u0438 \u0438\u043c\u0435\u0435\u0442 \u043d\u0435\u0440\u0430\u0437\u0440\u044b\u0432\u043d\u0443\u044e \u0444\u0430\u0437\u0443, \u0442\u043e \u043f\u0440\u0438 \u0441\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0441\u043f\u0435\u043a\u0442\u0440\u043e\u0432 \u043c\u043e\u0449\u043d\u043e\u0441\u0442\u044c \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u0442\u0438 \u043b\u0438\u043d\u0435\u0439\u043d\u043e, \u0432 \u0442\u0430\u043a\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u0440\u0430\u0437, \u043a\u0440\u0430\u0442\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0443 \u0443\u0441\u0440\u0435\u0434\u043d\u0435\u043d\u0438\u0439, \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u0441\u043f\u0435\u043a\u0442\u0440 \u0448\u0443\u043c\u0430 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u0442\u0438 \u043f\u043e \u0437\u0430\u043a\u043e\u043d\u0443 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0445 \u0431\u043b\u0443\u0436\u0434\u0430\u043d\u0438\u0439, \u2014 \u043f\u0440\u043e\u043f\u043e\u0440\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u043d\u043e\u043c\u0443 \u043a\u043e\u0440\u043d\u044e \u0438\u0437 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0443\u0441\u0440\u0435\u0434\u043d\u0435\u043d\u0438\u0439 ().\u041d\u0430 \u0440\u0438\u0441\u0443\u043d\u043a\u0435 3 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u043f\u0440\u0438\u043c\u0435\u0440 \u0443\u0441\u0440\u0435\u0434\u043d\u0435\u043d\u0438\u044f \u0441\u043f\u0435\u043a\u0442\u0440\u0430 \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0432 \u043a\u0430\u043d\u0430\u043b\u0435 \u0441 \u0430\u0434\u0434\u0438\u0442\u0438\u0432\u043d\u044b\u043c \u0413\u0430\u0443\u0441\u0441\u043e\u0432\u0441\u043a\u0438\u043c \u0448\u0443\u043c\u043e\u043c \u043f\u0440\u0438 \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\/\u0448\u0443\u043c SNR=-30 \u0434\u0411. \u041d\u0430 \u043f\u0435\u0440\u0432\u043e\u043c \u0433\u0440\u0430\u0444\u0438\u043a\u0435 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0447\u0430\u0441\u0442\u043e\u0442\u043e\u0439 1.0 \u043a\u0413\u0446 (\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u0441\u043f\u0435\u043a\u0442\u0440\u0435 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043e \u043a\u0440\u0430\u0441\u043d\u044b\u043c \u043f\u0443\u043d\u043a\u0442\u0438\u0440\u043e\u043c) \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 1\u0441, \u043d\u0430 \u0432\u0442\u043e\u0440\u043e \u2014 10\u0441 \u0438 30\u0441 \u043d\u0430 \u0442\u0440\u0435\u0442\u044c\u0435\u043c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e. \u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u0438\u0437 \u0433\u0440\u0430\u0444\u0438\u043a\u043e\u0432, \u043f\u0440\u0438 \u0434\u0435\u0441\u044f\u0442\u0438\u043a\u0440\u0430\u0442\u043d\u043e\u043c \u0443\u0441\u0440\u0435\u0434\u043d\u0435\u043d\u0438\u0438 \u0441\u043f\u0435\u043a\u0442\u0440\u0430, \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0439 \u0441\u0438\u0433\u043d\u0430\u043b \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u043f\u0440\u043e\u044f\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0448\u0443\u043c\u0430, \u0442\u043e \u0435\u0441\u0442\u044c SNR \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0440\u0430\u0441\u0442\u0438. \u041f\u0440\u0438 \u0435\u0449\u0435 \u0431\u043e\u043b\u0435\u0435 \u0434\u043e\u043b\u0433\u043e\u043c \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u0438\u0438 \u0441\u043f\u0435\u043a\u0442\u0440\u0430 \u0441\u0438\u0433\u043d\u0430\u043b \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0435\u0449\u0435 \u0441\u0438\u043b\u044c\u043d\u0435\u0435 \u043f\u0440\u0435\u043e\u0431\u043b\u0430\u0434\u0430\u0442\u044c \u043d\u0430\u0434 \u0448\u0443\u043c\u043e\u043c.\u0420\u0438\u0441\u0443\u043d\u043e\u043a 3: \u0412\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0441\u043b\u0430\u0431\u043e\u0433\u043e \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u043f\u0440\u0438 \u0443\u0441\u0440\u0435\u0434\u043d\u0435\u043d\u0438\u0438 \u0441\u043f\u0435\u043a\u0442\u0440\u0430.            &#8230;            for i in range(fft_count):                start = i * fft_step                segment = iq_signal[start: start + fft_size]                if len(segment) &lt; fft_size:                    segment = np.pad(segment, (0, fft_size &#8212; len(segment)), mode=&#187;constant&#187;)                cpx_spec = np.fft.fft(segment * smooth)                cpx_spec = np.fft.fftshift(cpx_spec)                pwr_spec[i, :] = np.abs(cpx_spec) ** 2            pwr_spec_avg = np.mean(pwr_spec, axis=0) * fft_count            center = fft_size \/\/ 2            span = 205            relevant_part = pwr_spec_avg[center &#8212; span: center + span + 1]            smooth_spec = np.convolve(relevant_part, WSPR_SMOOTH_KERNEL, mode=&#187;same&#187;)            noise_level = np.percentile(smooth_spec, WSPR_NOISE_PERCENTILE)            min_snr = np.pow(10.0, -8.0 \/ 10.0)            smooth_spec = smooth_spec \/ noise_level &#8212; 1.0            smooth_spec[smooth_spec &lt; min_snr] = 0.1 * min_snr            &#8230;\u0418\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u0442\u043e\u0433\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u044f, \u0447\u0442\u043e \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043e\u0434\u043d\u043e\u0433\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u0430 WSPR \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 0.6827 \u0441, \u0434\u0435\u043c\u043e\u0434\u0443\u043b\u044f\u0442\u043e\u0440\u0443, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0443\u0441\u0440\u0435\u0434\u043d\u0435\u043d\u0438\u0435 \u0441\u043f\u0435\u043a\u0442\u0440\u0430, \u0443\u0434\u0430\u0435\u0442\u0441\u044f \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0442\u044c \u0441\u0438\u0433\u043d\u0430\u043b\u044b \u0441 \u043d\u0438\u0437\u043a\u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c SNR.\u041f\u043e\u0438\u0441\u043a \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u043e\u0432\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u044d\u0442\u0430\u043f \u043f\u043e\u0441\u043b\u0435 \u0443\u0441\u0440\u0435\u0434\u043d\u0435\u043d\u0438\u044f \u0441\u043f\u0435\u043a\u0442\u0440\u0430 \u2014 \u0430\u043d\u0430\u043b\u0438\u0437 \u0430\u043c\u043f\u043b\u0438\u0442\u0443\u0434 \u0432 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u043c \u0441\u043f\u0435\u043a\u0442\u0440\u0435, \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u044e\u0449\u0438\u0439\u0441\u044f \u0432 \u043d\u0430\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0438 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0445 \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c\u043e\u0432 \u0441\u043f\u0435\u043a\u0442\u0440\u0430. \u041a\u0430\u0436\u0434\u044b\u0439 \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u044b\u0439 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u0437\u043d\u0430\u043a\u043e\u043c \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0438\u0441\u043a\u043e\u043c\u043e\u0433\u043e \u0441\u0438\u0433\u043d\u0430\u043b\u0430.WSPR_SNR_SCALING_FACTOR = 26.3&#8230;def dB(x: float) -&gt; float:    val = -99.0    if x &gt; 1.259e-10:        x = max(x, 0.000001)        val = 10.0 * np.log10(x)    return val&#8230;@dataclassclass Candidate:    freq: float    snr: float    shift: int = 0    drift: float = 0    sync: float = 0&#8230;class WSPRMonitor(AbstractMonitor):    &#8230;    MAX_CANDIDATES = 410    CANDIDATE_FREQ_MIN = -110    CANDIDATE_FREQ_MAX = 110    &#8230;    def find_candidates(self, smooth_spec: npt.NDArray[np.float64]) -&gt; typing.List[Candidate]:        spec_slice = smooth_spec[:self.MAX_CANDIDATES]        is_max = (spec_slice[1:-1] &gt; spec_slice[:-2]) &amp; (spec_slice[1:-1] &gt; spec_slice[2:])        indices = np.where(is_max)[0] + 1        freqs = (indices &#8212; 205) * self.df2      &#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-477322","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/477322","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=477322"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/477322\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=477322"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=477322"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=477322"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}