COMTRADE, будь он неладен!

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Offtop: Нахожусь в жёстком тильте, как следствие - дикий тупняк, главное, чтобы это было незаразно :) 

Итак, вводные:

1. Есть три выборки по току, в трёх списках длиной N, с примерно одинаковыми интервалами. Для простоты понимания, пример:

запись номер 1: [0], [500,200,100]

запись номер 2: [10], [200,1000,500]

....

выше видно, что вторая запись - через 10 миллисекунд от первой, каждая запись содержит три значения с трёх каналов АЦП.

2. Есть список времён получения импульсов штанги, простой донельзя: [0,123,432,856,...]

3. Есть список времён эталонных импульсов штанги: [0,100,400,800,...]

4. Каждый список - имеет свой размер, например, в первом списке (данные по току) - всего 20 записей, в списке импульсов штанги - 55 записей, в списке эталона - 60 записей.

Теперь - тупняк:

Формат COMTRADE подразумевает, что для КАЖДОЙ записе в файле *.dat - должны быть указаны значения ВСЕХ каналов (вот кто это придумал - тому надо пилюлю горькую, кмк). А у нас, судя по вводным - всё рваное и сходу не накладываемое друг на друга.

Задача:

Объединить эти три списка так, чтобы ни один временнОй интервал - не был потерян, и каждому временному интервалу - соответствовало бы значение из всех пяти списков. Т.е., другими словами, маленькое - растянуть до самого большого, без пропусков. При этом, поскольку в самом большом, очевидно, могут отсутствовать временнЫе метки из других маленьких списков - надо в этот большой добавить недостающие временные метки, интерпретировав данные так, чтобы сохранить функцию графика.

Вот ппц, туплю, и всё. В приложении на C# всё прекрасно делается на Chart - завёл себе отдельный график, и рисуй там, что хочешь. А вот с COMTRADE - попадос, сказывается отсутствие у меня глубокого знания комбинаторики.

Короче: если кто поделиться мыслью, как экспортировать всё это говно в COMTRADE - буду крайне признателен. Для простоты понимания - псевдокод с наборами данных, где ключевыми являются временнЫе метки, которые надо разместить на горизонтальной шкале, а все данные - растянуть БЕЗ дырок на эти временнЫе метки, с сохранением графиков функций:

uint32_t currentTimes[] = {0,250,500,1000};		 // времена получения данных по току
uint16_t currentData1[] = {200,300,400,500}; // линия тока 1
uint16_t currentData2[] = {300,200,300,200}; // линия тока 2
uint16_t currentData3[] = {100,500,200,800}; // линия тока 3

uint32_t interruptList[] = {0,5,12,85,160,400,500}; // список времён полученных прерываний

uint32_t ethalonList[] = {0,3,18,100,170,400,500,775,900, 950}; // список времён эталонных прерываний

Короче, ай нид немножко хэлп. И всех с наступающим!

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Проблема ещё в том, что я не могу ничего переделать, и сэмплировать АЦП в момент получения импульсов, например, т.к. данные по прерываниям приходят с внешнего модуля, а сэмплирование начинается чуть раньше, по факту взведения флага аварии. Плюс - частота сэмплирования настраивается юзверем, т.е. я физически не могу гарантировать хотя бы одинаковую размерность списков, не говоря уже о временнОй метке каждой записи.

Надеюсь, понятно изложил. В результирующем *.dat в каждой строке данных должны присутствовать все временнЫе метки, для каждой временнОй метки - должны быть данные со всех списков, причём, ориентируясь на самый длинный список, данные коротких, слева и справа - могут быть нулями (в случае, когда данные короткого списка начинаются не с начала отсчёта, и заканчиваются до последней временнОй метки).

sadman41
Offline
Зарегистрирован: 19.10.2016

Ничего не понял, но шампанское говорит - бей интервалы по наименьшим общим кратным и засыпай дырки нулями.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Исходя из приведённого выше псевдокода, временнЫе метки у нас должны получиться такими:

0,3,5,12,18,85,100,160,1700,250,400,500,775,900,950,1000

А интерпретированные данные, для каждой метки - вот такими:

метка,	ацп1,ацп2,ацп3,	прерывание,	эталон
0,	200,300,100,	0,		0
3,	200,300,100,	0,		3
5,	200,300,100,	5,		3
12,	200,300,100,	12,		3
18,	200,300,100,	12,		18
85,	200,300,100,	85,		18
100,	200,300,100,	85,		100
160,	200,300,100,	160,		100
170,	200,300,100,	160,		170
250,	300,200,500,	160,		170
400,	300,200,500,	400,		400
500,	400,300,200,	500,		500
775,	400,300,200,	0,		775
900,	400,300,200,	0,		900
950,	400,300,200,	0,		950
1000,	500,200,800,	0,		0

 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

sadman41 пишет:

Ничего не понял, но шампанское говорит - бей интервалы по наименьшим общим кратным и засыпай дырки нулями.

Нельзя дырки нулями засыпать, в том-то и дело ;) Нулями засыпать можно только слева и справа, чуть выше - я показал интерпретированный выхлоп для приведённого примера (при просмотре кода в всплывающем окне - всё норм с табуляциями).

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Похоже, для начала надо решать в лоб - составить список временнЫх меток, и потом тупо забивать их данными, пробежав все списки.

Алексей.
Алексей. аватар
Offline
Зарегистрирован: 02.02.2018

sadman41 пишет:
Ничего не понял, но шампанское говорит - бей интервалы по наименьшим общим кратным и засыпай дырки нулями.
IEEE Std C37.111-1999
Analog channel sample data are stored in two’s complement binary format of two bytes each. A datavalue of zero is stored as 0000 hexadecimal, –1 is recorded as FFFF. The maximum positive value is7FFF, and the maximum negative value is 8001. The hexadecimal 8000 is reserved to mark missingdata.
В стандарте 99-го года для отсутствующих выборок аналогового сигнала зарезервирована константа, разве её нельзя использовать?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Ну так и есть. Сначала метки. Здесь  обычная сортировка от меньшего к большему. Потом заполнение известных значений. Ну а потом уже заполнения неизвестных величин зная крайние известные и расстояние между метками. Можно кусочно линейным , можно методом наименьших квадратов.

ПС:https://math.semestr.ru/corel/linepar.php  ну здесь три соседние ближайшие к неизвестной.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Всем спасибо, вопрос закрыт, сделал. Графики функций сохраняют свой вид, учитываются все временнЫе интервалы, чтобы не париться с общим кратным. Сделал, очевидно - тупо в лоб, созданием списка уникальных временнЫх меток из входящего набора данных, ну и потом отражением каждого списка с данными на список меток времени.

Как обычно - стоило формализовать мысли на форуме - как пришло понимание, что и как надо делать :) Ещё раз всем спасибо.