Finnigan
view release on metacpan or search on metacpan
t/Finnigan.t view on Meta::CPAN
# to it anywhere in the file. The instrument log address in
# SampleInfo points at the first instrument log record following
# the header.
my $inst_log_header = Finnigan::GenericDataHeader->decode(\*INPUT);
is( $inst_log_header->n, 158, "GenericDataHeader->n (Instrument Log)" );
# only types 0, 3, 4, 6, 9, 10, 13 in this file
is( $inst_log_header->fields->[0]->type, 0, "GenericDataHeader->fields, GenericDataDescriptor->type 0" );
is( $inst_log_header->fields->[0]->length, 0, "GenericDataHeader->fields, GenericDataDescriptor->lenth 0" );
is( $inst_log_header->fields->[0]->label, "API SOURCE", "GenericDataHeader->fields, GenericDataDescriptor->label 0" );
is( $inst_log_header->fields->[3]->type, 3, "GenericDataHeader->fields, GenericDataDescriptor->type 3" );
is( $inst_log_header->fields->[3]->length, 0, "GenericDataHeader->fields, GenericDataDescriptor->lenth 3" );
is( $inst_log_header->fields->[3]->label, "Vaporizer Thermocouple OK:", "GenericDataHeader->fields, GenericDataDescriptor->label 3" );
is( $inst_log_header->fields->[16]->type, 4, "GenericDataHeader->fields, GenericDataDescriptor->type 4" );
is( $inst_log_header->fields->[16]->length, 0, "GenericDataHeader->fields, GenericDataDescriptor->lenth 4" );
is( $inst_log_header->fields->[16]->label, "Ion Gauge Status:", "GenericDataHeader->fields, GenericDataDescriptor->label 4" );
is( $inst_log_header->fields->[31]->type, 6, "GenericDataHeader->fields, GenericDataDescriptor->type 6" );
is( $inst_log_header->fields->[31]->length, 0, "GenericDataHeader->fields, GenericDataDescriptor->lenth 6" );
is( $inst_log_header->fields->[31]->label, "Power (Watts):", "GenericDataHeader->fields, GenericDataDescriptor->label 6" );
is( $inst_log_header->fields->[29]->type, 9, "GenericDataHeader->fields, GenericDataDescriptor->type 9" );
is( $inst_log_header->fields->[29]->length, 0, "GenericDataHeader->fields, GenericDataDescriptor->lenth 9" );
is( $inst_log_header->fields->[29]->label, "Life (hours):", "GenericDataHeader->fields, GenericDataDescriptor->label 9" );
is( $inst_log_header->fields->[53]->type, 10, "GenericDataHeader->fields, GenericDataDescriptor->type 10" );
is( $inst_log_header->fields->[53]->length, 2, "GenericDataHeader->fields, GenericDataDescriptor->lenth 10" );
is( $inst_log_header->fields->[53]->label, "Multipole 00 Offset (V):", "GenericDataHeader->fields, GenericDataDescriptor->label 10" );
is( $inst_log_header->fields->[28]->type, 13, "GenericDataHeader->fields, GenericDataDescriptor->type 13" );
is( $inst_log_header->fields->[28]->length, 14, "GenericDataHeader->fields, GenericDataDescriptor->lenth 13" );
is( $inst_log_header->fields->[28]->label, "Status:", "GenericDataHeader->fields, GenericDataDescriptor->label 13" );
is( tell INPUT, $inst_log_addr, "should have arrived at the start of the instrument log" );
# read the last log record (almost a guarantee that all prior records are intact)
my $inst_log_record;
foreach my $i (0 .. $inst_log_length - 1) {
$inst_log_record = Finnigan::InstrumentLogRecord->decode(\*INPUT, $inst_log_header->ordered_field_templates);
}
ok( num_equal($inst_log_record->time, 0.269295006990433), "InstrumentLogRecord->time (Instrument Log, 17.0, type 11)" );
is( $inst_log_record->data->{"1|API SOURCE"}->{value}, "", "InstrumentLogRecord->decode (Instrument Log, 17.1, type 0)" );
is( $inst_log_record->data->{"4|Vaporizer Thermocouple OK:"}->{value}, 0, "InstrumentLogRecord->decode (Instrument Log, 17.4, type 3)" );
is( $inst_log_record->data->{"17|Ion Gauge Status:"}->{value}, 1, "InstrumentLogRecord->decode (Instrument Log, 17.17, type 4)" );
is( $inst_log_record->data->{"32|Power (Watts):"}->{value}, 69, "InstrumentLogRecord->decode (Instrument Log, 17.32, type 6)" );
is( $inst_log_record->data->{"30|Life (hours):"}->{value}, 18398, "InstrumentLogRecord->decode (Instrument Log, 17.30, type 9)" );
ok( num_equal($inst_log_record->data->{"54|Multipole 00 Offset (V):"}->{value}, -2.0935959815979), "InstrumentLogRecord->decode (Instrument Log, 17.54, type 10)" );
is( $inst_log_record->data->{"29|Status:"}->{value}, "Running", "InstrumentLogRecord->decode (Instrument Log, 17.29, type 13)" );
is( $inst_log_record->data->{"158|Divert/Inject valve:"}->{value}, "Inject", "InstrumentLogRecord->decode (Instrument Log, 17.158, last item)" );
# foreach my $key (sort {(split /\|/, $a)[0] <=> (split /\|/, $b)[0]} keys %{$inst_log_record->data}) {
# print STDERR "$key -> " . $inst_log_record->data->{$key}->{value} . "\n";
# }
# Error log (null in the test file);
is( tell INPUT, $error_log_addr, "should have arrived at the start of the error log" );
my $error_log_length = Finnigan::Decoder->read(\*INPUT, ['length' => ['V', 'UInt32']])->{data}->{length}->{value};
is( $error_log_length, 0, "Error log length" );
# ScanEventHierarchy
my $nsegs = Finnigan::Decoder->read(\*INPUT, ['nsegs' => ['V', 'UInt32']])->{data}->{nsegs}->{value};
is( $nsegs, 1, "Number of scan segments" );
my $nev = Finnigan::Decoder->read(\*INPUT, ['nev' => ['V', 'UInt32']])->{data}->{nev}->{value};
is( $nev, 4, "Number of scan event types in the first segment" );
# read the first scan event template
my $et = Finnigan::ScanEventTemplate->decode(\*INPUT, $header->version);
is( join('', $et->preamble->list), "1121111011030000000000004000255255255255000020004222111000000000100000000000000022000000000000002000000000000000200000000000000002140000", "ScanEventTemplate->ScanEventPreamble->list (1)" );
is( join(' ', $et->preamble->list('decode')), "1 1 undefined undefined positive profile MS1 Full 1 1 False ESI 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 255 255 255 255 Off 0 0 0 2 0 0 0 FTMS 2 2 2 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 ...
is( $et->preamble->corona('decode'), "undefined", "ScanEventTemplate->ScanEventPreamble->corona(decode) (1)" );
is( $et->preamble->detector('decode'), "undefined", "ScanEventTemplate->ScanEventPreamble->detector(decode) (1)" );
is( $et->preamble->polarity('decode'), "positive", "ScanEventTemplate->ScanEventPreamble->polarity(decode) (1)" );
is( $et->preamble->scan_mode('decode'), "profile", "ScanEventTemplate->ScanEventPreamble->scan_mode(decode) (1)" );
is( $et->preamble->ms_power('decode'), "MS1", "ScanEventTemplate->ScanEventPreamble->ms_power(decode) (1)" );
is( $et->preamble->scan_type('decode'), "Full", "ScanEventTemplate->ScanEventPreamble->scan_type(decode) (1)" );
is( $et->preamble->dependent, 0, "ScanEventTemplate->ScanEventPreamble->dependent (1)" );
is( $et->preamble->ionization('decode'), "ESI", "ScanEventTemplate->ScanEventPreamble->ionization(decode) (1)" );
is( $et->preamble->ionization('decode'), "ESI", "ScanEventTemplate->ScanEventPreamble->ionization(decode) (1)" );
is( $et->preamble->analyzer('decode'), "FTMS", "ScanEventTemplate->ScanEventPreamble->analyzer(decode) (1)" );
is( $et->preamble->stringify, "FTMS + p ESI Full ms", "ScanEventTemplate->ScanEventPreamble->stringify (1)" );
is( $et->controllerType, 0, "ScanEventTemplate->controllerType; Assumption - not verified!");
is( $et->controllerNumber, 1, "ScanEventTemplate->controllerNumber; Assumption - not verified!");
ok( num_equal($et->fraction_collector->low, 400), "ScanEventTemplate->FractionCollector->low (1)" );
ok( num_equal($et->fraction_collector->high, 2000), "ScanEventTemplate->FractionCollector->high (1)" );
is( $et->fraction_collector->stringify, "[400.00-2000.00]", "ScanEventTemplate->FractionCollector->stringify (1)" );
# the second scan event template
$et = Finnigan::ScanEventTemplate->decode(\*INPUT, $header->version);
is( join(' ', $et->preamble->list('decode')), "1 0 undefined undefined positive profile MS2 Full 1 1 True ESI 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 255 255 255 255 Off 0 0 0 2 0 0 0 ITMS 2 2 2 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0...
is ($et->preamble->stringify, "ITMS + p ESI d Full ms2", "ScanEventTemplate->ScanEventPreamble->stringify (2)" );
# the third scan event template
$et = Finnigan::ScanEventTemplate->decode(\*INPUT, $header->version);
is( join(' ', $et->preamble->list('decode')), "1 0 undefined undefined positive profile MS2 Full 1 1 True ESI 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 255 255 255 255 Off 0 0 0 2 0 0 0 ITMS 2 2 2 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0...
is ($et->preamble->stringify, "ITMS + p ESI d Full ms2", "ScanEventTemplate->ScanEventPreamble->stringify (3)" );
# the fourth scan event template
$et = Finnigan::ScanEventTemplate->decode(\*INPUT, $header->version);
is( join(' ', $et->preamble->list('decode')), "1 0 undefined undefined positive profile MS2 Full 1 1 True ESI 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 255 255 255 255 Off 0 0 0 2 0 0 0 ITMS 2 2 2 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0...
is ($et->preamble->stringify, "ITMS + p ESI d Full ms2", "ScanEventTemplate->ScanEventPreamble->stringify (3)" );
#-------------------------------------------------------------------------
#
# This is where things become convoluted. The following GenericDataHeader
# decodes the ScanParameters stream that sits at the end of the file.
#
# The next ojbect after this will be the tune file, followed by the
# ScanIndex stream, then ScanEvent stream, and finally ScanParameters.
#
#-------------------------------------------------------------------------
my $scan_parameters_header = Finnigan::GenericDataHeader->decode(\*INPUT);
is( $scan_parameters_header->n, 29, "GenericDataHeader->n (ScanParameters stream)" );
# Tune file, a GenericRecord -- no special decoder is necessary
my $tune_file_header = Finnigan::GenericDataHeader->decode(\*INPUT);
is( $tune_file_header->n, 421, "GenericDataHeader->n (Tune File)" );
my $tune_file = Finnigan::GenericRecord->decode(\*INPUT, $tune_file_header->ordered_field_templates);
is( $tune_file->{data}->{"2|Source Type:"}->{value}, "ESI", "GenericRecord->decode (2), type 13" );
ok( num_equal($tune_file->{data}->{"3|Capillary Temp (C):"}->{value}, 275), "GenericRecord->decode (3), type 11" );
ok( num_equal($tune_file->{data}->{"421|FT Cal. Item 250:"}->{value}, 0), "GenericRecord->decode (421), type 11" );
# ScanIndex
is( tell INPUT, $scan_index_addr, "should have arrived at the start of scan index" );
my $index_entry = Finnigan::ScanIndexEntry->decode( \*INPUT, $header->version );
# measure scan index record size
my $record_size = $index_entry->size;
is( $index_entry->size, 72, "ScanIndexEntry->size" );
# check that the index record stream is of the right size
my $stream_size = $trailer_addr - $scan_index_addr;
my $nrecords = $stream_size / $record_size;
is( $stream_size % $record_size, 0, "scan index record stream should contain a whole number of $record_size\-byte records");
# look inside this index entry
is( $index_entry->offset, 0, "ScanIndexEntry->offset (0)" );
is( $index_entry->index, 0, "ScanIndexEntry->index (0)" );
is( $index_entry->scan_event, 0, "ScanIndexEntry->scan_event (0)" );
is( $index_entry->scan_segment, 0, "ScanIndexEntry->scan_segment (0)" );
is( $index_entry->next, 1, "ScanIndexEntry->next (0)" );
is( $index_entry->unknown, 21, "ScanIndexEntry->unknown (0)" );
is( $index_entry->data_size, 31932, "ScanIndexEntry->data_size (0)" );
ok( num_equal($index_entry->start_time, 0.00581833333333333), "ScanIndexEntry->start_time (0)" );
ok( num_equal($index_entry->total_current, 10851256), "ScanIndexEntry->total_current (0)" );
ok( num_equal($index_entry->base_mz, 1521.9716796875), "ScanIndexEntry->base_mz (0)" );
ok( num_equal($index_entry->base_intensity, 796088), "ScanIndexEntry->base_intensity (0)" );
ok( num_equal($index_entry->low_mz, 400), "ScanIndexEntry->low_mz (0)" );
ok( num_equal($index_entry->high_mz, 2000), "ScanIndexEntry->high_mz (0)" );
for my $i (2 .. $nrecords) { # skip to the last index entry
$index_entry = Finnigan::ScanIndexEntry->decode( \*INPUT, $header->version );
}
is( $index_entry->offset, 721572, "ScanIndexEntry->offset (32)" );
is( $index_entry->index, 32, "ScanIndexEntry->index (32)" );
is( $index_entry->scan_event, 0, "ScanIndexEntry->scan_event (32)" );
is( $index_entry->scan_segment, 0, "ScanIndexEntry->scan_segment (32)" );
is( $index_entry->next, 33, "ScanIndexEntry->next (32)" );
is( $index_entry->unknown, 21, "ScanIndexEntry->unknown (32)" );
is( $index_entry->data_size, 31020, "ScanIndexEntry->data_size (32)" );
ok( num_equal($index_entry->start_time, 0.242753333333333), "ScanIndexEntry->start_time (32)" );
ok( num_equal($index_entry->total_current, 11508917), "ScanIndexEntry->total_current (32)" );
ok( num_equal($index_entry->base_mz, 445.120635986328), "ScanIndexEntry->base_mz (32)" );
ok( num_equal($index_entry->base_intensity, 861951.8125), "ScanIndexEntry->base_intensity (32)" );
ok( num_equal($index_entry->low_mz, 400), "ScanIndexEntry->low_mz (32)" );
ok( num_equal($index_entry->high_mz, 2000), "ScanIndexEntry->high_mz (32)" );
is( tell INPUT, $trailer_addr, "should have arrived at the start of ScanEvents stream" );
# read the ScanEvent stream (the "trailer")
my $trailer_length = Finnigan::Decoder->read(\*INPUT, ['length' => ['V', 'UInt32']])->{data}->{length}->{value};
is( $trailer_length, 33, "the trailer events count should be 33");
# read the first ScanEvent record
my $scan_event = Finnigan::ScanEvent->decode( \*INPUT, $header->version );
is( $scan_event->preamble->corona('decode'), "undefined", "ScanEvent->preamble->corona" );
is( $scan_event->preamble->analyzer('decode'), "FTMS", "ScanEvent->preamble->analyzer" );
is( $scan_event->preamble->polarity('decode'), "positive", "ScanEvent->preamble->polarity" );
is( $scan_event->preamble->scan_mode('decode'), "profile", "ScanEvent->preamble->scan_mode" );
is( $scan_event->preamble->ionization('decode'), "ESI", "ScanEvent->preamble->ionization" );
is( $scan_event->preamble->dependent, 0, "ScanEvent->preamble->dependent" );
is( $scan_event->preamble->scan_type('decode'), "Full", "ScanEvent->preamble->scan_type" );
is( $scan_event->preamble->ms_power('decode'), "MS1", "ScanEvent->preamble->ms_power" );
is( "$scan_event", "FTMS + p ESI Full ms [400.00-2000.00]", "ScanEvent->preamble->stringify" );
is( $scan_event->preamble->wideband('decode'), "Off", "ScanEvent->preamble->wideband" );
is( $scan_event->fraction_collector->stringify, "[400.00-2000.00]", "ScanEvent->fraction_collector->stringify" );
is( $scan_event->np, 0, "ScanEvent->np" );
is( $scan_event->precursors, undef, "ScanEvent->precursors" );
my $converter = $scan_event->converter;
ok( num_equal(&$converter(1), 38518081.414831), "ScanEvent->converter");
my $inverse_converter = $scan_event->inverse_converter;
ok( num_equal(&$inverse_converter(325.24), 382.095239027303), "ScanEvent->converter");
ok( num_equal(&$converter(382.095239027303), 325.24), "ScanEvent->converter");
# read the second ScanEvent record
$scan_event = Finnigan::ScanEvent->decode( \*INPUT, $header->version );
is( $scan_event->preamble->analyzer('decode'), "ITMS", "ScanEvent->preamble->analyzer (2)" );
is( $scan_event->preamble->polarity('decode'), "positive", "ScanEvent->preamble->polarity (2)" );
is( $scan_event->preamble->scan_mode('decode'), "profile", "ScanEvent->preamble->scan_mode (2)" );
is( $scan_event->preamble->dependent, 1, "ScanEvent->preamble->dependent (2)" );
is( $scan_event->preamble->scan_type('decode'), "Full", "ScanEvent->preamble->scan_type (2)" );
is( $scan_event->preamble->ms_power('decode'), "MS2", "ScanEvent->preamble->ms_power (2)" );
is( "$scan_event", 'ITMS + p ESI d Full ms2 445.12@cid35.00 [110.00-460.00]', "ScanEvent->preamble->stringify (2)" );
is( $scan_event->preamble->corona('decode'), "undefined", "ScanEvent->preamble->corona (2)" );
is( $scan_event->preamble->wideband('decode'), "Off", "ScanEvent->preamble->wideband (2)" );
is( $scan_event->fraction_collector->stringify, "[110.00-460.00]", "ScanEvent->fraction_collector->stringify (2)" );
is( $scan_event->np, 1, "ScanEvent->np" );
my $pr = join ", ", map {"$_"} @{$scan_event->precursors};
is( $pr, '445.12@cid35.00', "ScanEvent->precursors (2)" );
$Finnigan::activationMethod = 'ecd'; # cos we don't know where to look for it
$pr = $scan_event->reaction->stringify;
is( $pr, '445.12@ecd35.00', "ScanEvent->precursors (2): setting the activation method)" );
ok( num_equal( $scan_event->reaction->precursor, 445.121063232422), "ScanEvent->reaction, Reaction->precursor" );
ok( num_equal($scan_event->reaction(0)->precursor, 445.121063232422), "ScanEvent->reaction(0), Reaction->precursor" );
is( $scan_event->reaction->energy, 35, "ScanEvent->reaction, Reaction->energy" );
for my $i (3 .. $nrecords) { # skip to the last ScanEvent
$scan_event = Finnigan::ScanEvent->decode( \*INPUT, $header->version );
}
is( tell INPUT, $params_addr, "should have arrived at the start of ScanParameters stream" );
# Finally reach ScanParameters. Test these, then return to scan data.
my $p = Finnigan::ScanParameters->decode(\*INPUT, $scan_parameters_header->field_templates);
is( $p->charge_state, 1, "ScanParameters->charge_state (type 6)" );
ok( num_equal($p->injection_time, 200.0), "ScanParameters->injection_time (type 10)" );
# skip to the MS2 scan
$p = Finnigan::ScanParameters->decode(\*INPUT, $scan_parameters_header->field_templates);
ok( num_equal($p->monoisotopic_mz, 445.121063232), "ScanParameters->monoisotopic_mz (type 11)" );
for my $i (3 .. $nrecords) { # skip to the end of file
my $p = Finnigan::ScanParameters->decode(\*INPUT, $scan_parameters_header->field_templates);
}
is( $p->charge_state, 1, "ScanParameters->charge_state (type 6)" );
is( $p->scan_segment, 1, "ScanParameters->scan_segment (type 6)" );
is( $p->scan_event, 2, "ScanParameters->scan_event (type 6)" );
is( tell INPUT, 848001, "should have arrived at the null stream near the end of the file" );
# Read the null stream
my $length = Finnigan::Decoder->read(\*INPUT, ['length' => ['V', 'UInt32']])->{data}->{length}->{value};
is( $length, 0, "the stream at the end of the file should have zero size" );
is( eof INPUT, 1, "should get EOF on the stream handle" );
# ----------------------------------------------------------------------
#
# Now back to the data stream
#
# ----------------------------------------------------------------------
# the first ScanDataPacket
seek INPUT, $data_addr, 0;
is( tell INPUT, 24950, "seek to scan data address" );
# PacketHeader
my $ph = Finnigan::PacketHeader->decode( \*INPUT );
is( $ph->{data}->{"unknown long[1]"}->{value}, 1, "PacketHeader->{unknown long[1]}" );
is( $ph->profile_size, 5624, "PacketHeader->profile_size" );
is( $ph->peak_list_size, 1161, "PacketHeader->peak_list_size" );
is( $ph->layout, 128, "PacketHeader->layout" );
is( $ph->descriptor_list_size, 580, "PacketHeader->descriptor_list_size" );
is( $ph->size_of_unknown_stream, 581, "PacketHeader->size_of_unkonwn_stream" );
is( $ph->size_of_triplet_stream, 27, "PacketHeader->size_of_triplet_stream" );
is( $ph->{data}->{"unknown long[2]"}->{value}, 0, "PacketHeader->{unknown long[2]}" );
ok( num_equal($ph->low_mz, 400.0), "PacketHeader->low_mz" );
ok( num_equal($ph->high_mz, 2000.0), "PacketHeader->high_mz" );
# Profile
( run in 2.340 seconds using v1.01-cache-2.11-cpan-364913b4093 )