def socket_client(DataS, ShutDown, Connection, LockQ):

    cpr.SetPriority(1)
    PreMessage = MESSAGE_PRELOAD()
    while not ShutDown.is_set():

        try:
            CwtFreq = DataS.get(GETBLOCK, GETTIMEOUT)
            Message = sp.MessageReturn(CwtFreq.value * DB)
            ar_type = DOUBLE * CwtFreq.value
            break
        except queue.Empty:
            continue
        except EOFError:
            ShutDown.set()
            break

    i = 0
    ch = 0
    try:
        while not ShutDown.is_set():

            try:
                InputMessage = DataS.get(GETBLOCK, GETTIMEOUT)
            except queue.Empty:
                continue
            except EOFError:
                ShutDown.set()
                break

            Message.Cut = InputMessage.Cut
            Message.Timestamp = InputMessage.Timestamp
            Message.Time_Interval = InputMessage.Time_Interval
            for n in InputMessage.nChannel:
                ch += 1
            for f in Message._fields_:
                if i == ch:
                    break
                if f[1] == ar_type:
                    setattr(Message, f[0],
                            np.ctypeslib.as_ctypes(InputMessage.nChannel[i]))
                    i += 1
            #for nc in InputMessage.nChannel:
            #    Message.nChannel[i] = nc
            #    i+=1
            i = 0
            ch = 0
            try:
                Connection.sendall(
                    premessage(PreMessage, Message.Cut, sizeof(Message)))
                Message.Timestamp = DOUBLE(datetime.utcnow().timestamp())
                Connection.sendall(
                    Message
                )  # Отправка преобразованных данных через протокол Sockets
            except socket.error as e:
                print(e)
                ShutDown.set()
    finally:
        Connection.close()
def file_mapping(sock, DataQ, DataS, ShutDown, LockQ):
    def _2sec(dvalue):
        return dvalue.timestamp()

    def datetime_fromdelphi(dvalue):
        return DELPHI_EPOCH + timedelta(days=dvalue)

    def readMem(mbuf,
                pos,
                bts,
                svpos,
                posret=True,
                bytesout=False,
                datetimedouble=False):
        size = sizeof(bts)
        bts_s = C.create_string_buffer(size)
        source = mbuf + pos
        length = SIZE_T(size)
        kernel32.RtlMoveMemory(bts_s, source, length)
        if svpos and posret:
            retpos = pos + size
        elif not svpos and posret:
            retpos = pos
        if bytesout:
            if posret:
                return np.array(bts_s, order='C').view(dtype=bts), retpos
            else:
                return np.array(bts_s, order='C').view(dtype=bts)
        elif datetimedouble:
            if posret:
                return (datetime_fromdelphi(
                    C.cast(bts_s,
                           POINTER(bts)).contents.value).timestamp(), retpos)
            else:
                return datetime_fromdelphi(
                    C.cast(bts_s, POINTER(bts)).contents.value).timestamp()
        else:
            if posret:
                return C.cast(bts_s, POINTER(bts)).contents.value, retpos
            else:
                return C.cast(bts_s, POINTER(bts)).contents.value

    def _getMVData(mbuf, pos, data, create):
        tpos = pos

        def _dmvmapret(data):
            nonlocal mbuf
            nonlocal create
            nonlocal tpos
            buf = readMem(mbuf,
                          tpos,
                          FLOAT,
                          False,
                          posret=False,
                          bytesout=True)
            tpos += SingleSize
            if create:
                return np.ndarray((1, ), buffer=buf, dtype=FLOAT, order='C')
            else:
                return np.concatenate(
                    (data, np.ndarray(
                        (1, ), buffer=buf, dtype=FLOAT, order='C')),
                    axis=0)

        return list(map(_dmvmapret, data)), tpos

    def _OPret(data, datalen):
        def mapret(data):
            return data[-(datalen):, ]

        return list(
            map(mapret, data)
        )  # Выделение из общего массива считанных данных окна, равного CwtFreq

    while True:
        try:
            #hmap = kernel32.CreateFileMappingW(INVALID_HANDLE_VALUE, SA, PAGE_READWRITE, 0, EXPECTED_SIZE, TAGNAME)
            hmap = kernel32.OpenFileMappingW(FILE_MAP_ALL_ACCESS, False,
                                             TAGNAME)
            handle_nonzero_success(hmap)
            if hmap == INVALID_HANDLE_VALUE:
                kernel32.CloseHandle(hmap)
                raise Exception("Ошибка создания Filemapping")
            mbuf = kernel32.MapViewOfFile(hmap, FILE_MAP_ALL_ACCESS, 0, 0,
                                          EXPECTED_SIZE)
            break
        except WindowsError:
            print(C.WinError(C.get_last_error()))
            print(
                'Перезапустите программу или запустите запись brainwin.exe...')
            time.sleep(5)
            continue
    tc = TChannel()
    while True:
        Freq, pos = readMem(mbuf, Int64Size * 3, INT64,
                            True)  # Частота оцифровки
        if Freq:
            break
    CwtFreq = int(Freq /
                  DB)  # Частота преобразования и отправки данных и длина окна
    print('\nЧастота оцифровки: ', Freq, 'Гц')
    Channels, pos = readMem(
        mbuf, pos, INT64, True)  # Фактическое количество используемых каналов
    print('Количество каналов: ', Channels)
    sock.sendall(
        first_message(FIRST_MESSAGE_PAYLOAD(), Freq, CwtFreq,
                      Channels))  # Сообщение серверу с первоначальными данными
    DataQ.put(Channels, PUTBLOCK, PUTTIMEOUT)
    LeadsAct = [0] * Channels
    LeadsPas = [0] * Channels
    Leads = [(0, 0)] * Channels
    for i in range(0, Channels):
        LeadsAct[i], pos = readMem(mbuf, pos, INT, True)
        cp = pos
        pos = (cp + IntegerSize * (ExpectedChannels - 1))
        LeadsPas[i], pos = readMem(mbuf, pos, INT, False)
        pos = cp
        Leads[i] = (tc.leads[LeadsAct[i]], tc.leads[LeadsPas[i]])
    print('Отведения: ', Leads)
    prepos1 = ((Int64Size * 5 + IntegerSize * ExpectedChannels * 2 +
                NameExpectedLength * AnsiCharSize))
    prepos2 = ((DateTimeSize + Int64Size + SingleSize * ExpectedChannels))
    Cut, pos = readMem(mbuf, Int64Size * 2, INT64, False)
    DataPayload = DATAMV_PAYLOAD()
    Datalen = 0
    DataMV = [list()] * Channels
    FlushTime = True
    FlushMVData = True
    Flow = False
    cpr.SetPriority(5)
    slpt = 1 / Freq / 1000
    try:
        while not ShutDown.is_set():
            if not Flow:
                oldCut = Cut
                with LockQ:
                    Cut = readMem(mbuf,
                                  Int64Size * 2,
                                  INT64,
                                  False,
                                  posret=False)
                acCut = Cut
                CwtCut = Cut + (SMOOTH + 50)
                if oldCut == Cut - 1:
                    Flow = True
                    print("Анализ...\n")
                else:
                    time.sleep(slpt)
                    continue
            else:
                acCut = readMem(mbuf,
                                Int64Size * 2,
                                INT64,
                                False,
                                posret=False)
                if acCut < oldCut:
                    Flow = False
                    Datalen = 0
                    continue
            """
            with LockQ:
                mvCut, pos = readMem(mbuf,
                                     Int64Size+(prepos1+prepos2*(divmod(Cut, MaxData)[1])),
                                     INT64, False)
            """
            if acCut > Cut:
                Cut += 1
            else:
                time.sleep(slpt)
                continue

            Datalen += 1

            # Чтение момента регистрации сигналов из общей памяти
            with LockQ:
                pos = prepos1 + prepos2 * (divmod(Cut, MaxData)[1])
                AstrTime, pos = readMem(mbuf, pos, DOUBLE, True, bytesout=True)
            #

            # Чтение данных из общей памяти и конкатенация биосигнала в мкВ в массив типа Float
            if FlushMVData:
                FlushMVData = False
            with LockQ:
                DataMV, pos = _getMVData(mbuf, pos + Int64Size, DataMV,
                                         FlushMVData)
            #

            # Конкатенация времени в массив типа Double
            if FlushTime:
                CwtT = np.ndarray((1, ),
                                  buffer=AstrTime,
                                  dtype=DOUBLE,
                                  order='C')
                FlushTime = False
            else:
                CwtT = np.concatenate(
                    (CwtT,
                     np.ndarray(
                         (1, ), buffer=AstrTime, dtype=DOUBLE, order='C')),
                    axis=0)
            #

            # Отправка массива данных в очередь для дальнейшей обработки с окном, равным CwtFreq
            if Cut - CwtCut >= CwtFreq:
                if Datalen > CwtFreq:
                    Datalen = CwtFreq
                CwtCut = Cut
                DataPayload.Cut = INT64(Cut)
                DataPayload.Data_Length = INT64(Datalen)
                DataPayload.nTimestamp = CwtT[-(Datalen + SMOOTH):, ]
                DataPayload.nChannel = _OPret(DataMV, Datalen + SMOOTH)
                DataQ.put(DataPayload, PUTBLOCK, PUTTIMEOUT)
                print('\nРазмер окна: ' + str(Datalen) + '\nСечение: ' +
                      str(Cut))
                Datalen = 0
            #
    finally:
        print(
            '\n---------------------------------------------------------------\nАнализ окончен.'
        )
        kernel32.CloseHandle(hmap)
        kernel32.UnmapViewOfFile(mbuf)
        while True:
            try:
                DataPayload = DataQ.get(GETBLOCK, GETTIMEOUT)
            except queue.Empty:
                continue
            except EOFError:
                break
            break
        WA = DataPayload.nWA
        print('Сохранение результатов!\n')
        timed = list(
            map(
                datetime_fromdelphi,
                CwtT[(SMOOTH_CUTRANGE + 50):(SMOOTH_CUTRANGE + 50) +
                     len(WA[0])]))
        times = np.array(list(map(_2sec, timed)))
        times = times - np.min(times)
        for i in range(Channels):
            ar1 = (DataMV[i])[(SMOOTH_CUTRANGE + 50):(SMOOTH_CUTRANGE + 50) +
                              len(WA[i])]
            ar2 = WA[i]
            plt.plot(times, ar1, linewidth=0.1)
            plt.plot(times, ar2, linewidth=0.4)
            plt.title("Результат анализа по каналу " + str(i + 1))
            plt.ylabel("Измеренные значения и мощность, мкВ")
            plt.xlabel("Длительность, сек")
            plt.xticks()
            plt.savefig('Channel_' + str(i + 1) + '_cwt.svg')
            plt.clf()
            ar = np.vstack((timed, ar1))
            ar = np.transpose(np.vstack((ar, ar2)))
            np.savetxt('Channel_' + str(i + 1) + '_cwt.csv',
                       ar,
                       header='Time,MV,CWT',
                       delimiter=",",
                       encoding='utf-8',
                       fmt='%s')
            print('Сохранено: Канал ' + str(i + 1) + '!\n')
def analysis(DataQ, DataS, ShutDown, LockQ, Fltr):
    def getCwt(pool, data, dt, datalen):

        s0 = 2 * dt / EST_WAVELET.flambda()
        j = np.int(np.round(np.log2((datalen) * dt / s0) / DJ))
        func = partial(mv2cwt, dt, s0, j, datalen, Fltr)
        return pool.map(func, data)

    Message = DATACWT_PAYLOAD()
    while not ShutDown.is_set():
        # Чтение данных из очереди
        try:
            Channels = DataQ.get(GETBLOCK, GETTIMEOUT)
            break
        except queue.Empty:
            continue
        except EOFError:
            ShutDown.set()
            break
        #
    pool = Pool(processes=Channels)
    DataPayload = None
    cpr.SetPriority(1)
    WA = list()
    CwtD = [np.array([], dtype=DOUBLE, order='C')] * ExpectedChannels
    CwtCut = 1
    FirstTime = True
    try:
        FlushCwt = True
        while not ShutDown.is_set():
            # Чтение данных из очереди
            try:
                DataPayload = DataQ.get(GETBLOCK, GETTIMEOUT)
            except queue.Empty:
                continue
            except EOFError:
                ShutDown.set()
                break
            #

            # Отправка данных на анализ и преобразование
            #start = datetime.now()
            CwtDT = np.diff(DataPayload.nTimestamp).mean(
            )  # Вычисление интервала между точками
            CwtD = getCwt(pool, DataPayload.nChannel, CwtDT,
                          DataPayload.Data_Length.value + SMOOTH)
            #print('Time spent '+str(datetime.now()-start))
            #

            #
            if FirstTime:
                FirstTime = False
                DataS.put(DataPayload.Data_Length, PUTBLOCK, PUTTIMEOUT)
            #

            # Отправка данных в очередь на формирование пакета Sockets
            Message.Cut = INT64(CwtCut)
            Message.Datalen = DataPayload.Data_Length
            Message.Time_Interval = FLOAT(CwtDT)
            Message.nChannel = CwtD
            DataS.put(Message, PUTBLOCK, PUTTIMEOUT)
            #

            #
            if FlushCwt:
                WA = CwtD
                FlushCwt = False
            else:
                WA = np.concatenate((WA, CwtD), axis=1)
            CwtCut += 1
            #

    finally:
        if DataPayload != None:
            DataPayload.nWA = WA
            DataQ.put(DataPayload, PUTBLOCK, PUTTIMEOUT)
        pool.close()
        pool.join()