Esempio n. 1
0
        /// <summary>
        /// Function to subtract median data to residual data.
        /// </summary>
        /// <remarks>both signals must have the same sample rate and AVM</remarks>
        /// <param name="definition">Data structure containing information about length of rhythm data.</param>
        /// <param name="rhythm">2D array containing rhythm data for each lead. On succes will contain residual data.</param>
        /// <param name="median">2D array containing median data for each lead.</param>
        /// <returns>error:
        /// 0x001) given data makes no sense.
        /// 0x002) Fault in Lead nr 0.
        /// 0x004) Fault in Lead nr 1.
        /// 0x008) Fault in Lead nr 2.
        /// 0x010) Fault in Lead nr 3.
        /// 0x020) Fault in Lead nr 4.
        /// 0x040) Fault in Lead nr 5.
        /// 0x080) Fault in Lead nr 6.
        /// 0x100) Fault in Lead nr 7.
        /// ...</returns>
        public int SubtractMedians(SCPSection3 definition, short[][] rhythm, short[][] median)
        {
            // Check if given data makes sense
            if (Works() &&
                (definition != null)
                & (rhythm != null) &&
                (median != null) &&
                (definition.Works()) &&
                (median.Length == definition.getNrLeads()) &&
                (rhythm.Length == median.Length))
            {
                int err = 0;
                for (int qrsnr = 0; qrsnr < _NrQRS; qrsnr++)
                {
                    if ((_Subtraction[qrsnr].Type != 0))
                    {
                        continue;
                    }

                    for (int channel = 0; channel < median.Length; channel++)
                    {
                        if ((rhythm[channel] == null) ||
                            (median[channel] == null) ||
                            (rhythm[channel].Length < definition.getLeadLength(channel)))
                        {
                            err |= (0x2 << channel);
                            continue;
                        }

                        int loperResidual = _Subtraction[qrsnr].Start - definition.getLeadStart(channel);
                        int loperMedian   = (_FirstFiducial - _Subtraction[qrsnr].Fiducial + _Subtraction[qrsnr].Start - 1);
                        int endResidual   = _Subtraction[qrsnr].End - definition.getLeadStart(channel);

                        if ((loperResidual >= 0) &&
                            (loperMedian >= 0))
                        {
                            while ((loperResidual <= endResidual) &&
                                   (loperMedian < median[channel].Length))
                            {
                                rhythm[channel][loperResidual++] -= median[channel][loperMedian++];
                            }
                        }
                    }
                }
                return(err);
            }
            return(-1);
        }
Esempio n. 2
0
        /// <summary>
        /// Function to encode data in this section.
        /// </summary>
        /// <param name="data">Rhythm data to encode</param>
        /// <param name="tables">Huffman table to use during enconding</param>
        /// <param name="leadDefinition">Lead Definitions to use for encoding</param>
        /// <param name="difference">difference to use durring decoding</param>
        /// <returns>0 on succes</returns>
        public int EncodeData(short[][] data, SCPSection2 tables, SCPSection3 leadDefinition, SCPSection4 qrsLocations, int medianFreq, byte difference)
        {
            int localFreq = getSamplesPerSecond();

            if ((data != null) &&
                (tables != null) &&
                (leadDefinition != null) &&
                (localFreq > 0))
            {
                if ((medianFreq <= 0) ||
                    (medianFreq == localFreq))
                {
                    medianFreq = 1;
                    localFreq  = 1;
                }

                if ((_Bimodal == 0x1) &&
                    (qrsLocations == null))
                {
                    return(2);
                }

                ushort nrleads = leadDefinition.getNrLeads();
                _Data       = new byte[nrleads][];
                _DataLength = new ushort[nrleads];
                for (int loper = 0; loper < nrleads; loper++)
                {
                    if (data[loper] == null)
                    {
                        return(4);
                    }

                    short[] temp = data[loper];

                    int time = (leadDefinition.getLeadLength(loper) * localFreq) / medianFreq;
                    if (localFreq != medianFreq)
                    {
                        int rate = (medianFreq / localFreq);
                        // Bimodal part might be buggy unable to test.
                        if ((_Bimodal == 0x1) &&
                            ((medianFreq % localFreq) == 0) &&
                            (rate > 0) &&
                            (rate < 5))
                        {
                            // Calculate nr of samples stored in section.
                            time = 0;

                            int nrzones = qrsLocations.getNrProtectedZones();
                            for (int zone = 0; zone < nrzones; zone++)
                            {
                                int begin = (qrsLocations.getProtectedStart(zone) >= leadDefinition.getLeadStart(loper) ? qrsLocations.getProtectedStart(zone) : leadDefinition.getLeadStart(loper));
                                int end   = (qrsLocations.getProtectedEnd(zone) <= leadDefinition.getLeadEnd(loper) ? qrsLocations.getProtectedEnd(zone) : leadDefinition.getLeadEnd(loper));

                                begin = (end > begin ? end - begin + 1 : 0);

                                time += begin + (rate - (begin % rate));
                            }

                            time += ((leadDefinition.getLeadLength(loper) - time) * localFreq) / medianFreq;

                            int leadLength = leadDefinition.getLeadLength(loper);

                            time += ((leadLength - time) * localFreq) / medianFreq;

                            // Restructure bimodal data to length set in Section3.
                            temp = new short[time];

                            int time2Offset = leadDefinition.getLeadStart(loper);
                            int time1       = 0;
                            int time2       = 0;

                            while ((time1 < temp.Length) &&
                                   (time2 <= leadLength) &&
                                   (time2 < data[loper].Length))
                            {
                                int zone = 0;
                                int end  = qrsLocations.getNrProtectedZones();
                                for (; zone < end; zone++)
                                {
                                    if ((qrsLocations.getProtectedLength(zone) > 0) &&
                                        (time2 + time2Offset >= qrsLocations.getProtectedStart(zone)) &&
                                        (time2 + time2Offset <= qrsLocations.getProtectedEnd(zone)))
                                    {
                                        break;
                                    }
                                }

                                if (zone < end)
                                {
                                    temp[time1] = data[loper][time2++];
                                }
                                else
                                {
                                    int Sum = 0;
                                    for (int sumLoper = 0; sumLoper < rate; sumLoper++)
                                    {
                                        Sum += data[loper][time2 + sumLoper];
                                    }
                                    temp[time1] = (short)(Sum / rate);
                                    time2      += rate;
                                }

                                time1++;
                            }
                        }
                        else
                        {
                            _Bimodal = 0;
                            ECGTool.ResampleLead(temp, medianFreq, localFreq, out temp);
                        }
                    }

                    _Difference  = difference;
                    _Data[loper] = tables.Encode(temp, time, 0, _Difference);
                    if (_Data[loper] == null)
                    {
                        _Data       = null;
                        _DataLength = null;
                        return(8);
                    }
                    _DataLength[loper] = (ushort)_Data[loper].Length;
                    if ((_DataLength[loper] & 0x1) == 0x1)
                    {
                        _DataLength[loper]++;
                    }
                }
                return(0);
            }
            return(1);
        }
Esempio n. 3
0
        /// <summary>
        /// Function to decode data in this section.
        /// </summary>
        /// <param name="tables">Huffman table to use during deconding</param>
        /// <param name="leadDefinition"></param>
        /// <returns>decoded leads</returns>
        public short[][] DecodeData(SCPSection2 tables, SCPSection3 leadDefinition, SCPSection4 qrsLocations, int medianFreq)
        {
            int localFreq = getSamplesPerSecond();

            if (Works() &&
                (tables != null) &&
                (tables.Works()) &&
                (leadDefinition != null) &&
                (leadDefinition.Works()) &&
                (leadDefinition.getNrLeads() == _Data.Length) &&
                (localFreq > 0))
            {
                if ((medianFreq <= 0) ||
                    (medianFreq == localFreq))
                {
                    medianFreq = 1;
                    localFreq  = 1;
                }

                if ((medianFreq < localFreq) &&
                    !leadDefinition.isMediansUsed() &&
                    (_Bimodal == 0x0))
                {
                    medianFreq = localFreq;
                }

                if (((medianFreq % localFreq) != 0) ||
                    ((medianFreq / localFreq) < 1) ||
                    ((medianFreq / localFreq) > 4))
                {
                    // make an exception for ECGs that don't use compression (like corpuls ECGs that are in violation of this rule).
                    if (_Bimodal == 0x0)
                    {
                        medianFreq = localFreq;
                    }
                    else
                    {
                        return(null);
                    }
                }

                if ((_Bimodal == 0x1) &&
                    (qrsLocations == null))
                {
                    return(null);
                }

                // Reset selected table.
                tables.ResetSelect();

                short[][] leads = new short[_Data.Length][];
                for (int loper = 0; loper < _Data.Length; loper++)
                {
                    int time = (leadDefinition.getLeadLength(loper) * localFreq) / medianFreq;

                    // Bimodal part might be buggy unable to test.
                    if ((localFreq != medianFreq) &&
                        (_Bimodal == 0x1))
                    {
                        int rate = medianFreq / localFreq;

                        // Calculate nr of samples stored in section.
                        time = 0;

                        int nrzones = qrsLocations.getNrProtectedZones();
                        for (int zone = 0; zone < nrzones; zone++)
                        {
                            int begin = (qrsLocations.getProtectedStart(zone) >= leadDefinition.getLeadStart(loper) ? qrsLocations.getProtectedStart(zone) : leadDefinition.getLeadStart(loper));
                            int end   = (qrsLocations.getProtectedEnd(zone) <= leadDefinition.getLeadEnd(loper) ? qrsLocations.getProtectedEnd(zone) : leadDefinition.getLeadEnd(loper));

                            begin = (end > begin ? end - begin + 1 : 0);

                            time += begin + (rate - (begin % rate));
                        }

                        time += ((leadDefinition.getLeadLength(loper) - time) * localFreq) / medianFreq;
                    }

                    leads[loper] = tables.Decode(_Data[loper], 0, _Data[loper].Length, time, _Difference);
                    // Check if lead was decoded
                    if (leads[loper] == null)
                    {
                        // return if lead decode failed.
                        return(null);
                    }

                    if (localFreq != medianFreq)
                    {
                        int rate = medianFreq / localFreq;
                        if (_Bimodal == 0x1)
                        {
                            int beginNonProtected = 0;
                            int endNonProtected   = qrsLocations.getProtectedStart(0);
                            // Restructure bimodal data to length set in Section3.
                            short[] temp = new short[leadDefinition.getLeadLength(loper)];

                            int time1Offset = leadDefinition.getLeadStart(loper);
                            int time1       = 0;
                            int time2       = 0;

                            int zone = 0;

                            while ((time1 < temp.Length) &&
                                   (time2 < leads[loper].Length))
                            {
                                if (((time1 + time1Offset) >= beginNonProtected) &&
                                    ((time1 + time1Offset) < endNonProtected))
                                {
                                    for (int begin = 0; begin < (rate >> 1); begin++)
                                    {
                                        temp[time1++] = leads[loper][time2];
                                    }

                                    if ((time2 + ((endNonProtected - (time1 + time1Offset)) / rate)) >= leads[loper].Length)
                                    {
                                        endNonProtected -= ((time2 + ((endNonProtected - (time1 + time1Offset)) / rate)) - leads[loper].Length) * rate;
                                    }

                                    endNonProtected -= rate + (rate >> 1);

                                    while ((time1 + time1Offset) < endNonProtected)
                                    {
                                        for (int i = 0; (i < rate) && (time1 < temp.Length); i++)
                                        {
                                            temp[time1++] = (short)(((leads[loper][time2 + 1] - leads[loper][time2]) / rate) * i + leads[loper][time2]);
                                        }
                                        time2++;
                                    }

                                    endNonProtected += rate + (rate >> 1);

                                    for (int end = 0; end < (rate >> 1); end++)
                                    {
                                        temp[time1++] = leads[loper][time2];
                                    }

                                    time2++;

                                    beginNonProtected = (zone == qrsLocations.getNrProtectedZones() ? temp.Length : qrsLocations.getProtectedEnd(zone));
                                }
                                else
                                {
                                    // This should never happen!!
                                    if (zone == qrsLocations.getNrProtectedZones())
                                    {
                                        break;
                                    }

                                    while (((time1 + time1Offset) < qrsLocations.getProtectedEnd(zone)) &&
                                           (time1 < temp.Length) &&
                                           (time2 < leads[loper].Length))
                                    {
                                        temp[time1++] = leads[loper][time2++];
                                    }
                                    zone++;
                                    endNonProtected = (zone == qrsLocations.getNrProtectedZones() ? temp.Length : qrsLocations.getProtectedStart(zone));
                                }
                            }

                            leads[loper] = temp;
                        }
                        else
                        {
                            ECGTool.ResampleLead(leads[loper], localFreq, medianFreq, out leads[loper]);
                        }
                    }
                }
                return(leads);
            }
            return(null);
        }