Skip to content

Commit

Permalink
Issue-223: Add missing v5 error metric file format (#224)
Browse files Browse the repository at this point in the history
* Issue-223: Add missing v5 error metric file format

* Fix unit tests

* Fix tests

* Fix C#

* Add newline

* Reduce number of python versions

* Reduce further

* Split jobs

* Split more
  • Loading branch information
ezralanglois authored Aug 11, 2020
1 parent 8c8b4bd commit d2af397
Show file tree
Hide file tree
Showing 15 changed files with 308 additions and 61 deletions.
9 changes: 9 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ matrix:
- os: osx
compiler: clang
env: DEPLOY_BUILD=true SCRIPT="bash ./tools/package.sh $PWD $PWD/dist travis OFF Release ALL"
- os: osx
compiler: clang
env: DEPLOY_BUILD=true SCRIPT="bash ./tools/package.sh $PWD $PWD/dist travis OFF Release 3.6.10"
- os: osx
compiler: clang
env: DEPLOY_BUILD=true SCRIPT="bash ./tools/package.sh $PWD $PWD/dist travis OFF Release 3.7.7"
- os: osx
compiler: clang
env: DEPLOY_BUILD=true SCRIPT="bash ./tools/package.sh $PWD $PWD/dist travis OFF Release 3.8.2"
- os: linux
compiler: clang
env: SCRIPT="bash ./tools/package.sh $PWD $PWD/dist travis ON Debug Disable"
Expand Down
1 change: 1 addition & 0 deletions cmake/Modules/FindCSBuild.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ if(NOT CSHARP_TARGET_FRAMEWORK)
endif()

if(CSBUILD_FOUND)
message(STATUS "Using Framework: ${CSHARP_TARGET_FRAMEWORK}")
if(DOTNET_STANDARD_FOUND)
message(STATUS "Using Framework: ${CSHARP_TARGET_FRAMEWORK}")
message(STATUS "Using Platform: ${CSHARP_PLATFORM}")
Expand Down
1 change: 1 addition & 0 deletions docs/src/binary_formats.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ The documentation for the model notes when an attribute is only populated by a s
- @subpage corrected_v4 "Corrected Intensity v4"
- @subpage error_v3 "Error v3"
- @subpage error_v4 "Error v4"
- @subpage error_v5 "Error v5"
- @subpage extended_tile_v2 "Extended Tile Version 2"
- @subpage extended_tile_v3 "Extended Tile Version 3"
- @subpage extraction_v2 "Extraction Version 2"
Expand Down
7 changes: 7 additions & 0 deletions docs/src/changes.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
# Changes {#changes}


## v1.1.11

Date | Description
---------- | -----------
2020-08-10 | Issue-223: Add missing v5 error metric file format


## v1.1.10

Date | Description
Expand Down
21 changes: 18 additions & 3 deletions interop/model/metrics/error_metric.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace illumina { namespace interop { namespace model { namespace metrics
* The error metric is the calculated error rate, as determined by a spiked in PhiX control sample.
* This metric is available for each lane and tile for every cycle.
*
* @note Supported versions: 3 and 4
* @note Supported versions: 3, 4, and 5
*/
class error_metric : public metric_base::base_cycle_metric
{
Expand All @@ -41,7 +41,7 @@ namespace illumina { namespace interop { namespace model { namespace metrics
/** Unique type code for metric */
TYPE = constants::Error,
/** Latest version of the InterOp format */
LATEST_VERSION = 4
LATEST_VERSION = 5
};
/** Define a uint array using an underlying vector
*/
Expand All @@ -52,6 +52,7 @@ namespace illumina { namespace interop { namespace model { namespace metrics
error_metric() :
metric_base::base_cycle_metric(0, 0, 0),
m_error_rate(std::numeric_limits<float>::quiet_NaN()),
m_phix_adapter_rate(std::numeric_limits<float>::quiet_NaN()),
m_mismatch_cluster_count(MAX_MISMATCH, 0)
{
}
Expand All @@ -60,6 +61,7 @@ namespace illumina { namespace interop { namespace model { namespace metrics
error_metric(const header_type&) :
metric_base::base_cycle_metric(0, 0, 0),
m_error_rate(std::numeric_limits<float>::quiet_NaN()),
m_phix_adapter_rate(std::numeric_limits<float>::quiet_NaN()),
m_mismatch_cluster_count(MAX_MISMATCH, 0)
{
}
Expand All @@ -74,9 +76,11 @@ namespace illumina { namespace interop { namespace model { namespace metrics
error_metric(const uint_t lane,
const uint_t tile,
const uint_t cycle,
const float error) :
const float error,
const float phix_adapter_rate) :
metric_base::base_cycle_metric(lane, tile, cycle),
m_error_rate(error),
m_phix_adapter_rate(phix_adapter_rate),
m_mismatch_cluster_count(MAX_MISMATCH, 0)
{
}
Expand All @@ -101,6 +105,16 @@ namespace illumina { namespace interop { namespace model { namespace metrics
return m_error_rate;
}

/** Calculated adapter trim rate of PhiX clusters
*
* @note Supported by v5
* @return adapter trim rate
*/
float phix_adapter_rate() const
{
return m_phix_adapter_rate;
}

/** Number of clusters at given number of mismatches
*
* 0: no mismatches
Expand Down Expand Up @@ -162,6 +176,7 @@ namespace illumina { namespace interop { namespace model { namespace metrics

private:
float m_error_rate;
float m_phix_adapter_rate;
uint_array_t m_mismatch_cluster_count;
template<class MetricType, int Version>
friend
Expand Down
142 changes: 142 additions & 0 deletions src/interop/model/metrics/error_metric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,90 @@ namespace illumina{ namespace interop{ namespace io
}

};

/** Error Metric Record Layout Version 5
*
* This class provides an interface to reading the error metric file:
* - InterOp/ErrorMetrics.bin
* - InterOp/ErrorMetricsOut.bin
*
* The class takes two template arguments:
*
* 1. Metric Type: error_metric
* 2. Version: 5
*/
template<>
struct generic_layout<error_metric, 5> : public default_layout<5>
{
/** @page error_v5 Error Version 5
*
* This class provides an interface to reading the error metric file:
* - InterOp/ErrorMetrics.bin
* - InterOp/ErrorMetricsOut.bin
*
* The file format for error metrics is as follows:
*
* @b Header
*
* illumina::interop::io::read_metrics (Function that parses this information)
*
* byte 0: version number (5)
* byte 1: record size (16)
*
* @b n-Records
*
* illumina::interop::io::layout::base_cycle_metric (Class that parses this information)
*
* 2 bytes: lane number (uint16)
* 4 bytes: tile number (uint32)
* 2 bytes: cycle number (uint16)
*
* illumina::interop::io::generic_layout<error_metric, 5> (Class that parses this information)
*
* 4 bytes: error rate (float32)
* 4 bytes: fraction of reads adapter-trimmed at the cycle (float32)
*/
/** Metric ID type */
typedef layout::base_cycle_metric< ::uint32_t > metric_id_t;
/** Error type */
typedef float error_t;
/** Map reading/writing to stream
*
* Reading and writing are symmetric operations, map it once
*
* @param stream input/output stream
* @param metric source/destination metric
* @return number of bytes read or total number of bytes written
*/
template<class Stream, class Metric, class Header>
static std::streamsize map_stream(Stream& stream, Metric& metric, Header&, const bool)
{
std::streamsize count = 0;
count += stream_map< error_t >(stream, metric.m_error_rate);
count += stream_map< error_t >(stream, metric.m_phix_adapter_rate);
return count;
}
/** Compute the layout size
*
* @return size of the record
*/
static record_size_t compute_size(const error_metric::header_type&)
{
return static_cast<record_size_t>(sizeof(metric_id_t)+
sizeof(error_t)+ // m_errorRate
sizeof(error_t) // m_phix_adapter_rate
);
}
/** Compute header size
*
* @return header size
*/
static record_size_t compute_header_size(const error_metric::header_type&)
{
return static_cast<record_size_t>(sizeof(record_size_t) + sizeof(version_t));
}

};
#pragma pack()
/** Error Metric CSV text format
*
Expand Down Expand Up @@ -246,12 +330,70 @@ namespace illumina{ namespace interop{ namespace io
return 0;
}
};

/** Error Metric CSV text format
*
* This class provide an interface for writing the error metrics to a CSV file:
*
* - ErrorMetrics.csv
*/
template<>
struct text_layout< error_metric, 2 >
{
/** Define a header type */
typedef error_metric::header_type header_type;
/** Write header to the output stream
*
* @param out output stream
* @param sep column separator
* @param eol row separator
* @return number of column headers
*/
static size_t write_header(std::ostream& out,
const header_type&,
const std::vector<std::string>&,
const char sep,
const char eol)
{
const char* headers[] =
{
"Lane", "Tile", "Cycle", "ErrorRate", "PhiXAdapterRate"
};
out << "# Column Count: " << util::length_of(headers) << eol;
out << headers[0];
for(size_t i=1;i<util::length_of(headers);++i)
out << sep << headers[i];
out << eol;
return util::length_of(headers);
}
/** Write a error metric to the output stream
*
* @param out output stream
* @param metric error metric
* @param sep column separator
* @param eol row separator
* @return number of columns written
*/
static size_t write_metric(std::ostream& out,
const error_metric& metric,
const header_type&,
const char sep,
const char eol,
const char)
{
out << metric.lane() << sep << metric.tile() << sep << metric.cycle() << sep;
out << metric.error_rate() << sep << metric.phix_adapter_rate() << eol;
return 0;
}
};
}}}

INTEROP_FORCE_LINK_DEF(error_metric)
INTEROP_REGISTER_METRIC_GENERIC_LAYOUT(error_metric, 3 )
INTEROP_REGISTER_METRIC_GENERIC_LAYOUT(error_metric, 4 )
INTEROP_REGISTER_METRIC_GENERIC_LAYOUT(error_metric, 5 )


// Text formats
INTEROP_REGISTER_METRIC_TEXT_LAYOUT(error_metric, 1)
INTEROP_REGISTER_METRIC_TEXT_LAYOUT(error_metric, 2)
17 changes: 5 additions & 12 deletions src/tests/csharp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ if(NOT CSBUILD_FOUND)
return()
endif()

if(NOT DOTNET_CORE_FOUND)
if(NOT DOTNET_STANDARD_FOUND)
find_package(NUnit)
if(NOT NUNIT_FOUND)
message(WARNING "NUnit not found, C# unit testing will be disabled")
Expand Down Expand Up @@ -53,11 +53,11 @@ set(TEST_SRCS
run/RunInfoTest.cs
run/RunParametersTest.cs
)
if(DOTNET_CORE_FOUND)
if(DOTNET_STANDARD_FOUND)
set(TEST_SRCS ${TEST_SRCS} Program.cs)
endif()


set(CSHARP_TARGET_FRAMEWORK "netcoreapp2.0")
find_program(NUGET_EXE nuget)
if(NUGET_EXE)
# Test the NuGet Package
Expand All @@ -70,10 +70,6 @@ else()
add_dependencies(csharp_unittest csharp_interop ${NUNIT_TARGET})
endif()

if(NOT ENABLE_CSHARP)
set_target_properties(csharp_unittest PROPERTIES EXCLUDE_FROM_ALL 1 EXCLUDE_FROM_DEFAULT_BUILD 1)
endif()

# Clear old packages
# dotnet nuget locals all --clear

Expand All @@ -98,10 +94,6 @@ set(PERF_TEST_SRCS

csharp_add_library(csharp_perftest ${NUNIT_LIBRARIES} ${PERF_TEST_SRCS} ${SWIG_CSHARP_LIBRARY})
add_dependencies(csharp_perftest csharp_interop ${NUNIT_TARGET})
if(NOT ENABLE_CSHARP)
set_target_properties(csharp_perftest PROPERTIES EXCLUDE_FROM_ALL 1 EXCLUDE_FROM_DEFAULT_BUILD 1)
endif()


add_custom_command(TARGET csharp_perftest POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CSBUILD_csharp_perftest_BINARY} $<TARGET_FILE_DIR:${INTEROP_LIB}>
Expand All @@ -112,10 +104,11 @@ if(NOT ENABLE_STATIC)
add_custom_command(TARGET csharp_perftest POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE_DIR:${INTEROP_LIB}> ${CMAKE_CURRENT_BINARY_DIR})
endif()
set(CSHARP_TARGET_FRAMEWORK "netstandard2.0" CACHE STRING "C# .NET framework for dotnet" )

add_custom_target(check_csharp
COMMENT "Running C# unit tests: ${CSHARP_INTERPRETER} $<TARGET_FILE_DIR:${INTEROP_LIB}>/${CSBUILD_csharp_unittest_BINARY_NAME}"
COMMAND ${CSHARP_INTERPRETER} $<TARGET_FILE_DIR:${INTEROP_LIB}>/${CSBUILD_csharp_unittest_BINARY_NAME}
COMMAND ${CHECKER} ${CSHARP_INTERPRETER} $<TARGET_FILE_DIR:${INTEROP_LIB}>/${CSBUILD_csharp_unittest_BINARY_NAME}
)

add_dependencies(check_csharp csharp_unittest)
Expand Down
6 changes: 3 additions & 3 deletions src/tests/csharp/metrics/ErrorMetricsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ public class ErrorMetricsTestV3
protected void SetUp()
{
base_cycle_metric_header header = new base_cycle_metric_header();
expected_metrics.Add(new error_metric(7, 1114, 1, 0.450100899f));
expected_metrics.Add(new error_metric(7, 1114, 2, 0.900201797f));
expected_metrics.Add(new error_metric(7, 1114, 3, 0.465621591f));
expected_metrics.Add(new error_metric(7, 1114, 1, 0.450100899f, 0f));
expected_metrics.Add(new error_metric(7, 1114, 2, 0.900201797f, 0f));
expected_metrics.Add(new error_metric(7, 1114, 3, 0.465621591f, 0f));

int[] tmp = new int[]{3,30,7,0,90,4,1,0,-96,115,-26,62,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,7,0,90,4,2,0,-96,115,102,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Expand Down
7 changes: 4 additions & 3 deletions src/tests/interop/logic/summary_metrics_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -382,14 +382,15 @@ TEST(summary_metrics_test, cycle_35_cycle_34_tile)
model::metric_base::metric_set<model::metrics::error_metric> &actual_error_metrics =
actual_run_metrics.get<model::metrics::error_metric>();
typedef model::metrics::error_metric::uint_t uint_t;
const float kMissingValue = std::numeric_limits<float>::quiet_NaN();
for (uint_t cycle_number = 0; cycle_number < 36; ++cycle_number)
{
expected_error_metrics.insert(error_metric(1, 1101, 1 + cycle_number, 3.0f));
actual_error_metrics.insert(error_metric(1, 1101, 1 + cycle_number, 3.0f));
expected_error_metrics.insert(error_metric(1, 1101, 1 + cycle_number, 3.0f, kMissingValue));
actual_error_metrics.insert(error_metric(1, 1101, 1 + cycle_number, 3.0f, kMissingValue));
}
for (uint_t cycle_number = 0; cycle_number < 34; ++cycle_number)
{
actual_error_metrics.insert(error_metric(1, 1102, 1 + cycle_number, 1.0f));
actual_error_metrics.insert(error_metric(1, 1102, 1 + cycle_number, 1.0f, kMissingValue));
}

model::summary::run_summary expected;
Expand Down
11 changes: 8 additions & 3 deletions src/tests/interop/metrics/error_metrics_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,17 @@ struct error_metrics_tests : public generic_test_fixture< error_metric_set > {};

error_metrics_tests::generator_type error_unit_test_generators[] = {
wrap(new hardcoded_metric_generator< error_metric_v3 >) ,
wrap(new write_read_metric_generator< error_metric_v3 >)
,wrap(new hardcoded_metric_generator< error_metric_v4 >),
wrap(new hardcoded_metric_generator< error_metric_v4 >),
wrap(new hardcoded_metric_generator< error_metric_v5 >),
wrap(new write_read_metric_generator< error_metric_v3 >),
wrap(new write_read_metric_generator< error_metric_v4 >),
wrap(new write_read_metric_generator< error_metric_v5 >),
wrap(new by_cycle_metric_generator< error_metric_v3 >),
wrap(new by_cycle_metric_generator< error_metric_v4 >),
wrap(new by_cycle_metric_generator< error_metric_v5 >),
wrap(new clear_metric_generator< error_metric_v3 >),
wrap(new clear_metric_generator< error_metric_v4 >)
wrap(new clear_metric_generator< error_metric_v4 >),
wrap(new clear_metric_generator< error_metric_v5 >)
};

// Setup unit tests for error_metrics_tests
Expand Down Expand Up @@ -67,6 +71,7 @@ TEST_P(error_metrics_tests, compare_expected_actual)
EXPECT_EQ(it_expected->cycle(), it_actual->cycle());
EXPECT_EQ(it_expected->mismatch_count(), it_actual->mismatch_count());
EXPECT_NEAR(it_expected->error_rate(), it_actual->error_rate(), 1e-5f);
INTEROP_EXPECT_NEAR(it_expected->phix_adapter_rate(), it_actual->phix_adapter_rate(), 1e-5f);
for(ptrdiff_t i=0;i<static_cast<ptrdiff_t>(it_expected->mismatch_count());i++)
EXPECT_EQ(it_expected->mismatch_cluster_count(i), it_actual->mismatch_cluster_count(i));
}
Expand Down
Loading

0 comments on commit d2af397

Please sign in to comment.