gemstone / pqdif

Gemstone PQDIF Library
https://gemstone.github.io/pqdif/
MIT License
5 stars 4 forks source link

Problem of the reading PQDIF file with the recommended code. #4

Closed pangchunhei closed 2 years ago

pangchunhei commented 2 years ago

I am new to this library, and I saw a section on saying the sample code on reading the pqdif file. But when I paste them to my ide, it has many errors on the multithreading. Also if I remove all the await, it still cannot run as Task,bool> not same as bool. May I know the correct ways to run the library to get the data from the pqdif file?

image The recommended code

image After my mod still cannot run

ContainerRecord containerRecord; List observationRecords = new List(); string filePath = args[0];

await using LogicalParser parser = new LogicalParser(filePath); await parser.OpenAsync(); containerRecord = parser.ContainerRecord;

while (await parser.HasNextObservationRecordAsync()) observationRecords.Add(await parser.NextObservationRecordAsync()); Official documentation in LogicalParser Class

pangchunhei commented 2 years ago

image That's what I have tried. I think with this code I get the file structure? image

StephenCWills commented 2 years ago

This library uses Task Parallel Library to enable asynchronous access to the file. The short answer is that you can convert your defaultLog() method into an async method and the sample should work fine.

static async Task DefaultLogAsync(string filePath) {
    ContainerRecord containerRecord;
    List<ObservationRecord> observationRecords = new List<ObservationRecord>();

    await using LogicalParser parser = new LogicalParser(filePath);
    await parser.OpenAsync();
    containerRecord = parser.ContainerRecord;

    while (await parser.HasNextObservationRecordAsync())
        observationRecords.Add(await parser.NextObservationRecordAsync());
}

For the long answer, you may want to read up on how TPL and async/await works in .NET. https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/

pangchunhei commented 2 years ago

Ok understood, thanks. Now seems all working.

pangchunhei commented 2 years ago

Also may I know if want to print the data inside the PQDIF, how to do so, I tried to use this, but seems only can print the structure, but not the actual data.

foreach(var v in observationRecords) { Console.WriteLine(v.PhysicalRecord.Body); }

StephenCWills commented 2 years ago

That is a pretty complex question, as the PQDIF standard supports many different ways of representing data. If you're struggling to understand how to reach and/or interpret the data, studying the PQDIF standard should go a long way toward gaining that understanding. You can also try out the PQDIF Explorer application, which should give you an idea of how the data gets organized in a PQDIF file.

Desktop app: https://github.com/GridProtectionAlliance/PQDIFExplorer/releases/tag/v1.0.4 Web version: https://www.gridprotectionalliance.org/pqdif-explorer/

Anyway, I think the closest you're going to get to a basic example of how to print the data is going to be something like the following.

foreach (ObservationRecord observationRecord in observationRecords)
{
    Console.WriteLine(observationRecord.StartTime);

    // Get the first channel instance
    ChannelInstance firstChannelInstance = observationRecord.ChannelInstances[0];

    foreach (SeriesInstance seriesInstance in firstChannelInstance.SeriesInstances)
    {
        // FYI, this expands StorageMethods.Increment and applies
        // scale/offset and transducer ratio fields to the values,
        // as opposed to seriesInstance.SeriesValues which returns
        // the unmodified raw values as a VectorElement
        IList<object> values = seriesInstance.OriginalValues;
        string csv = string.Join(",", values);
        Console.WriteLine(csv);
    }

    Console.WriteLine();
}

Don't expect too much from this example. It certainly does print the data (for the first channel in every observation), but you still aren't going to know what those values mean. For what it's worth, the first series instance in every channel instance is probably going to represent time--likely in seconds elapsed since the start of the observation--while the rest represent the measured values.

pangchunhei commented 2 years ago

Okkk, understood thanks a lotttt. These codes definitely helped me a lot with the understanding of this library.