Ejemplo n.º 1
0
        private static void PreprocessParsedWaveforms(XElement root, Version schemaVersion)
        {
            // Retrieve parsedwaveforms element and check if the data is encoded
            var parsedWaveforms = root.Descendants(XEParsedWaveforms)
                                  .SingleOrDefault();

            if (parsedWaveforms != null)
            {
                object decoded = null;

                //SierraECGSchema_1_04_01:
                // @dataencoding: how the data is encoded: eg., "Base64".
                // Use "Plain" for sample values in ascii: "10 20 35...." .
                var encoding = (string)parsedWaveforms.Attribute("dataencoding");
                switch (encoding)
                {
                case "Plain":
                    decoded = parsedWaveforms.Value;
                    break;

                case "Base64":
                    decoded = Convert.FromBase64String(parsedWaveforms.Value);
                    parsedWaveforms.SetAttributeValue("dataencoding", "Plain");
                    break;

                default:
                    // no can decode boss man
                    throw new InvalidOperationException("Unknown data encoding: " + encoding);
                }

                bool   isCompressed;
                string compression;
                if (schemaVersion < new Version("1.04"))
                {
                    isCompressed = (bool)parsedWaveforms.Attribute("compressflag");
                    compression  = (string)parsedWaveforms.Attribute("compressmethod");
                }
                else
                {
                    compression  = (string)parsedWaveforms.Attribute("compression");
                    isCompressed = compression == "XLI";
                }

                if (isCompressed)
                {
                    var signalCharacteristics = root.Element(ns + "dataacquisition")
                                                .Element(ns + "signalcharacteristics");
                    var leadsUsed    = (string)signalCharacteristics.Element(ns + "acquisitiontype");
                    var goodChannels = (int)signalCharacteristics.Element(ns + "numberchannelsallocated");

                    if (compression == "XLI" && decoded is byte[])
                    {
                        List <DecodedLead> leads;
                        using (var xli = new XliDecompressor((byte[])decoded))
                        {
                            var decodedData = new List <int[]>();

                            int[] payload;
                            while (null != (payload = xli.ReadLeadPayload()))
                            {
                                decodedData.Add(payload);

                                // the DXL algorithm can interpret 16 channels, so often all 16
                                // will be in the file, but the last 4 will be 0's besides
                                // their calibration marks at the end. This is a quick check to skip
                                // what we don't care about.
                                if (decodedData.Count >= goodChannels)
                                {
                                    break;
                                }
                            }

                            leads = DecodedLead.ReinterpretLeads(leadsUsed, decodedData).ToList();
                        }

                        if (schemaVersion < new Version("1.04"))
                        {
                            // CAW: "False" must be used as the "false" is not recognized by many of the tools
                            parsedWaveforms.SetAttributeValue("compressflag", "False");
                        }
                        else
                        {
                            //SierraECGSchema_1_04_01:
                            // @compression: name the type of compression if the data is compressed
                            // (e.g., "XLI" for standard Philips cardiograph compression; if not compressed, omit this attribute).
                            parsedWaveforms.SetAttributeValue("compression", null);
                        }

                        // CAW: the default is 25 data points per line
                        decoded = String.Join(
                            Environment.NewLine,
                            leads.SelectMany(
                                lead => lead.Select((vv, ix) => new { I = ix, V = vv })
                                .GroupBy(xx => xx.I / 25)
                                .Select(gg => String.Join(" ", gg.Select(xx => xx.V)))));
                    }
                    else
                    {
                        // no can decompress boss man
                        throw new InvalidOperationException("Unknown compression method: " + compression);
                    }
                }

                // handle the case where we've decoded Base64 only data
                if (decoded is byte[])
                {
                    var bytes = (byte[])decoded;
                    var lead  = new short[bytes.Length / 2];
                    Buffer.BlockCopy(bytes, 0, lead, 0, bytes.Length);
                    decoded = String.Join(
                        Environment.NewLine,
                        lead.Select((vv, ix) => new { I = ix, V = vv })
                        .GroupBy(xx => xx.I / 25)
                        .Select(gg => String.Join(" ", gg.Select(xx => xx.V))));
                }

                parsedWaveforms.SetValue(decoded);
            }
        }
Ejemplo n.º 2
0
        private static DecodedLead[] ExtractLeads(XElement root)
        {
            Debug.Assert(root != null);

            // Retrieve parsedwaveforms element and check if the data is encoded
            var parsedWaveforms = root.Descendants(XEParsedWaveforms)
                                  .SingleOrDefault();

            if (parsedWaveforms != null)
            {
                var signalCharacteristics = root.Element(ns + "dataacquisition")
                                            .Element(ns + "signalcharacteristics");
                var leadsUsed    = (string)signalCharacteristics.Element(ns + "acquisitiontype");
                var goodChannels = (int)signalCharacteristics.Element(ns + "numberchannelsallocated");
                var sampleRate   = (int)signalCharacteristics.Element(ns + "samplerate");
                var duration     = (int)parsedWaveforms.Element(ns + "durationperchannel");

                var samples = duration * (sampleRate / 1000);

                object decoded  = null;
                var    encoding = (string)parsedWaveforms.Attribute("dataencoding");
                switch (encoding)
                {
                case "Plain":
                    return(parsedWaveforms.Value
                           .Split(new[] { ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
                           .Select((vv, ix) => new { I = ix, V = Int32.Parse(vv) })
                           .GroupBy(xx => xx.I / samples)
                           .Select(gg => new DecodedLead(gg.Key + 1, gg.Select(xx => xx.V).ToArray()))
                           .ToArray());

                case "Base64":
                    decoded = Convert.FromBase64String(parsedWaveforms.Value);
                    break;

                default:
                    // no can decode boss man
                    throw new InvalidOperationException("Unknown data encoding: " + encoding);
                }

                var isCompressed = (bool)parsedWaveforms.Attribute("compressflag");
                var compression  = (string)parsedWaveforms.Attribute("compressmethod");
                if (isCompressed)
                {
                    if (compression == "XLI" && decoded is byte[])
                    {
                        using (var xli = new XliDecompressor((byte[])decoded))
                        {
                            var decodedData = new List <int[]>();

                            int[] payload;
                            while (null != (payload = xli.ReadLeadPayload()))
                            {
                                decodedData.Add(payload);

                                // the DXL algorithm can interpret 16 channels, so often all 16
                                // will be in the file, but the last 4 will be 0's besides
                                // their calibration marks at the end. This is a quick check to skip
                                // what we don't care about.
                                if (decodedData.Count >= goodChannels)
                                {
                                    break;
                                }
                            }

                            return(DecodedLead.ReinterpretLeads(leadsUsed, decodedData).ToArray());
                        }
                    }
                    else
                    {
                        // no can decompress boss man
                        throw new InvalidOperationException("Unknown compression method: " + compression);
                    }
                }

                // handle the case where we've decoded Base64 only data
                if (decoded is byte[])
                {
                    var bytes = (byte[])decoded;
                    var leads = new List <DecodedLead>();
                    for (int offset = 0, lead = 0; offset < bytes.Length; offset += samples * 2)
                    {
                        var data = new short[samples];
                        Buffer.BlockCopy(bytes, offset, data, 0, samples * 2);

                        leads.Add(new DecodedLead(++lead, data.Select(dd => (int)dd).ToArray()));
                    }

                    return(leads.ToArray());
                }
            }

            throw new NotSupportedException("For whatever reason this format was not supported");
        }