Ответ 1
Это то, что я до сих пор.
Документ, который вы используете, не от реального запуска ПЦР, как это было сделано из читаемых данных. Это прогон цветокоррекции (краткий обзор, который, по-видимому, соответствует файлу) (полное обновленное руководство, стр. 250, а не как вариант). В частности, это, по-видимому, выполнение цветокоррекции для "красителя FAM/Pulsar 650".
Тип вывода, как вы указываете, это "AcquisitionTable" с 2400 "счетными", которые, по-моему, должны отличаться от вывода, который вы обычно получаете от запуска PCR. Я уверен, что вы их уже нашли, но несколько публичных примеров шаблонов PCR (не завершенных запусков) здесь, здесь, здесь и .
Согласно LCRunProgram в вашем файле, здесь был протокол:
держите 95 ° C для 0 "со скоростью 20 ° C/с
держите 40 ° C на 30 °, 20 ° C/с
удерживайте 95 ° C для 0 "при 0,1 ° C/с, режиме приема" 2 ".
Итак, мы ожидаем, что временные рамки сбора данных оценивались приблизительно (95 ° C-40 ° C)/0,1 ° C/s = 550 секунд, приблизительно; за это время должно было быть зафиксировано фиксированное количество событий приобретения в секунду.
EDIT 0 - это то, что я сделал с самого начала, поэтому я не удаляю его, но позже получил более интересную информацию (см. ниже).
Я просмотрел данные с помощью простого Python script (я парень Python) для поиска шаблонов. script хранит ваши исходные строки данных в словаре с именем values
, который слишком длинный для публикации здесь; так что вот он в сущности, как и вам.
#!/usr/bin/env python3
import base64
from collections import OrderedDict, defaultdict
from values import values
def splitme(name, sep):
splitted = base64.b64decode(values[name]+'==').split(sep)
print("{:<12} [{}; {}] separated in {} chunks: {}".format(
name,
len(values[name]), len(base64.b64decode(values[name]+'==')),
len(splitted),
[len(i) for i in splitted]))
return splitted
if __name__ == '__main__':
allchunks = defaultdict(list)
separator = b'\r'
print("separating by:", separator)
for key in values:
data = splitme(key, sep=separator)
for i, item in enumerate(data):
allchunks[item].append((key, i))
print("Common chunks:")
for location in [value for item, value in allchunks.items() if len(value)>1]:
print(location)
Позвольте получить очевидное изложение и сказать, что ProgramNo
и CycleNo
содержат одни и те же данные; и все Gain
идентичны. Поэтому я отправлю только один из них.
Теперь, попробовав script с разделителем b'\r'
(просто попробуйте один), вырезает несколько из них в кусках 272 (271 + разделителей) байтов. Остальные не аккуратны.
separating by: b'\r'
SampleNo [1536; 1152] separated in 5 chunks: [174, 271, 271, 271, 161]
ProgramNo [1531; 1148] separated in 6 chunks: [47, 271, 271, 271, 271, 12]
SegmentNo [1531; 1148] separated in 5 chunks: [169, 271, 271, 271, 162]
Разделение на b'\t'
дает похожие результаты:
separating by: b'\t'
SampleNo [1536; 1152] separated in 5 chunks: [204, 271, 271, 271, 131]
ProgramNo [1531; 1148] separated in 5 chunks: [76, 271, 271, 271, 255]
SegmentNo [1531; 1148] separated in 5 chunks: [199, 271, 271, 271, 132]
И разделение на b'\n'
разделяет выигрыши на этот раз аналогичным образом:
separating by: b'\n'
Gain1 [3046; 2284] separated in 10 chunks: [81, 271, 271, 271, 271, 271, 271, 271, 271, 26]
Поэтому я вовсе не подразумеваю, что эти "разделители" имеют какое-либо значение; Я думаю, что это редкие персонажи, которые, как представляется, режут данные в 272-байтовых фрагментах, и это значение, 272 байта, может быть важно для понимания того, как эти данные хранятся.
Начало каждой строки "BARZ" выглядит как "foo-bar"; вероятно, установлен как проверка в начале заголовка.
Интересно другое: данные gains
разделяются на 8 блоков равного размера (плюс два других меньших блока). Если эти данные из 96-луночного планшета, я бы начал изучать, может ли это быть заголовок, а затем 8 кусков (линий), которые будут разделяться в 12 элементах (colums), так что 8 * 12 = 96, копируя настройку 96-луночного планшета.
Кроме того, если гипотеза "272 байта на строку" истинна, то данные в ProgramNo
, SampleNo
и т.д., которые разделены на 272-байтовые фрагменты, могут быть объяснены, если тарелка не заполнена, а некоторые скважины имели образцы (с несколькими полными линиями), в то время как другие были пустыми. Я не уверен, что это будет иметь смысл для пластины компенсации цвета.
Time
, Temperature
, Error
и Fluor
не разделяются на куски, и вы считаете, что они представляют собой набор непрерывных значений; не обязательно плавает. Флуоресценцию можно зафиксировать как "единицы", которые могут быть положительными ints (у меня нет LightCycler, поэтому я не знаю, имеет ли это случай или нет).
И это я до сих пор. Я не уверен, что у меня будет время пойти дальше. В случае, если я не отвечу, удачи в ваших усилиях.
ИЗМЕНИТЬ 1:
Таким образом, в отношении данных SampleNo
он выглядит таким образом:
1) заголовок, который может быть или не быть разделен 0x00 как:
* заголовок BARZ
, затем 2 раза 0x00 (всего 6 байт)
* три байта, затем 0x00 (всего 4 байта)
* 17 байт, затем 0x00 (всего 18 байт)
2) ряд данных, каждый из которых состоит из 16 байтов и заканчивается 0x00 (по меньшей мере, 17 байт).
Это означает, что Samples
содержит заголовок плюс 66 наборов из 17 байтов.
ИЗМЕНИТЬ 2:
Разделение всего на 0x00 с помощью этой ужасной части кода:
def splitme(name):
data = base64.b64decode(values[name]+'==')
hit = 0
index = 0
countit = 0
splits = []
while hit >= 0 and countit < 500:
countit += 1
hit = data[index+1:].find(0)
index += hit+1
if hit >= 0:
splits.append(index)
lastindex = -1
splitted = []
if splits:
for index in splits:
splitted.append(data[lastindex+1:index])
lastindex = index
else:
splitted = [data]
Урожайность:
separating by: 0x0
SampleNo [1536; 1152] separated in 70 chunks: [4, 0, 3, 17, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16]
ProgramNo [1531; 1148] separated in 71 chunks: [4, 0, 3, 2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 12]
SegmentNo [1531; 1148] separated in 69 chunks: [4, 0, 3, 18, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16]
CycleNo [1531; 1148] separated in 71 chunks: [4, 0, 3, 2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 12]
Time [11944; 8958] separated in 63 chunks: [4, 0, 3, 45, 14, 42, 76, 46, 172, 110, 109, 15, 81, 90, 111, 108, 78, 46, 175, 141, 88, 209, 74, 117, 156, 170, 59, 107, 78, 103, 125, 171, 103, 170, 191, 333, 154, 187, 11, 257, 149, 208, 173, 156, 153, 412, 72, 55, 207, 131, 131, 274, 284, 238, 19, 241, 247, 13, 74, 558, 763, 8, 0]
Temperature [6731; 5048] separated in 14 chunks: [4, 0, 3, 394, 186, 543, 177, 173, 530, 534, 371, 714, 373, 1032]
Error [398; 298] separated in 21 chunks: [4, 0, 3, 2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 12]
Fluor1 [7539; 5654] separated in 38 chunks: [4, 0, 3, 31, 13, 7, 7, 426, 331, 218, 187, 11, 10, 13, 7, 6, 7, 48, 45, 217, 840, 6, 7, 14, 7, 6, 7, 7, 6, 1178, 8, 6, 1147, 7, 6, 141, 630, 2]
...
Gain1 [3046; 2284] separated in 145 chunks: [4, 0, 3, 9, 7, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8, 7, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8, 7, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8, 7, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8, 7, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8, 7, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8, 7, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8, 7, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8, 7, 16, 16, 16, 16]
...
So SampleNo
, ProgramNo
, SegmentNo
, Error
и Gain
все разделены блоками по 17 байт (16 байт + 0x00).
ИЗМЕНИТЬ 3:
Первые пятнадцать 17-разрядных фрагментов ProgramNo
(и копия CycleNo
) и Error
идентичны.
Просто для пояснения, "куски", которые я описываю, - это то, что вы описываете как ряд пар чисел, один из которых увеличивается на 0x12. 0x00, о котором вы упоминаете, является разделителем между кусками.
ИЗМЕНИТЬ 4:
Что касается данных Gain
, то связь между моими начальными блоками "272 байта" и блоками (16 + 0x00) -байта состоит в том, что существует повторяющийся шаблон из 16 блоков, из которых 15 - блоки "16 + 0x00" и один последний блок имеет 0x00 в середине. Итак, 17 байт (= 16 + 0x00) * 16 блоков = 272 байта для этого повтора.
Вся строка построена следующим образом: "заголовок", затем 8 таких повторов 17 байт * 16 блоков, а затем четыре 17-байтных блока в конце. Так что с одной стороны я был прав насчет 8 блоков, но, по-видимому, я ошибся, когда делал параллель с плитой ПЦР 8x12. Здесь это больше похоже на 8 * 16 (+4).
Из-за данных Fluor
и т.д. У меня нет ответа, но я бы попытался удалить заголовок и посмотреть, может ли с ним работать алгоритм сжатия (integer или float)... Сжатые данные объяснят, почему у вас разные длины для этих полей.