diff --git a/docs/src/changes.md b/docs/src/changes.md index b352fcc1c..37efcd121 100644 --- a/docs/src/changes.md +++ b/docs/src/changes.md @@ -4,6 +4,18 @@ Date | Description ---------- | ----------- +2016-12-21 | Replace interop2csv with dumptext +2016-12-20 | IPA-5923: Fix bug in legacy q-metric binning +2016-12-19 | Removes the coverity run from the build matrix for every pull request +2016-12-16 | IPA-5885: Ensure error summary matches requirements +2016-12-14 | Enhance C# version information +2016-12-14 | Clean up unused enum types +2016-12-12 | IPA-5153: Ensure Summary tab calculations are consistent with Docs +2016-12-09 | IPA-5883: Fix possible memory issue in MSVC12 +2016-12-08 | IPA-4674: Add support for absolute naming convention +2016-12-07 | IPA-5869: Add section filtering +2016-12-06 | IPA-5734: Synchronize master +2016-12-02 | Add Google Analytics tracking to documentation 2016-12-08 | Added admonition to avoid using MSVC 12 (2013) with C# bindings 2016-12-08 | Added support for absolute tile naming 2016-12-08 | Added ability to do section filtering diff --git a/interop/io/format/abstract_text_format.h b/interop/io/format/abstract_text_format.h new file mode 100644 index 000000000..9a6c79610 --- /dev/null +++ b/interop/io/format/abstract_text_format.h @@ -0,0 +1,72 @@ +/** Metric format interface for the text format factory + * + * @file + * @date 12/19/16 + * @version 1.0 + * @copyright GNU Public License. + */ + +#pragma once + +#include +#include "interop/util/cstdint.h" + +namespace illumina { namespace interop { namespace io +{ + /** Abstract class that provides an interface for the text format of a metric + * + * The template argument for this class corresponds to a specific type + * of metric set. + */ + template + struct abstract_text_format + { + /** Define the metric type */ + typedef Metric metric_t; + /** Define the metric header type */ + typedef typename Metric::header_type header_t; + /** ID type */ + typedef typename metric_t::id_t id_t; + + /** Destructor + */ + virtual ~abstract_text_format() {} + /** Write the header for a set of metric records to the given output stream + * + * @param out output stream to write the binary InterOp file data + * @param header header of a metric set + * @param channel_names list of channel names + * @param sep column seperator + * @param eol row separator + * @return number of column headers + */ + virtual size_t write_header(std::ostream &out, + const header_t &header, + const std::vector& channel_names, + const char sep, + const char eol) = 0; + /** Write a metric record to the given output stream + * + * @param out output stream to write the binary InterOp file data + * @param metric interop metric data to write + * @param header interop metric header data to write + * @param sep column seperator + * @param eol row separator + * @param missing missing value indicator + * @return number of columns written + */ + virtual size_t write_metric(std::ostream &out, + const metric_t &metric, + const header_t &header, + const char sep, + const char eol, + const char missing) = 0; + + /** Get the version of this metric format + * + * @return version number + */ + virtual ::int16_t version() const=0; + }; +}}} + diff --git a/interop/io/format/generic_layout.h b/interop/io/format/generic_layout.h index 9fcf4bd67..cf7eb31ab 100644 --- a/interop/io/format/generic_layout.h +++ b/interop/io/format/generic_layout.h @@ -23,6 +23,13 @@ namespace illumina { namespace interop { namespace io template struct generic_layout; + /** Define a text layout of the metric + * + * This is currently only used for writing metrics + */ + template + struct text_layout; + }}} diff --git a/interop/io/format/metric_format_factory.h b/interop/io/format/metric_format_factory.h index f6f56532c..df3decf7a 100644 --- a/interop/io/format/metric_format_factory.h +++ b/interop/io/format/metric_format_factory.h @@ -10,6 +10,7 @@ #include #include "interop/util/map.h" #include "interop/util/assert.h" +#include "interop/util/self_registration.h" #include "interop/io/format/abstract_metric_format.h" #include "interop/util/unique_ptr.h" #include "interop/io/stream_exceptions.h" @@ -33,19 +34,6 @@ illumina::interop::io::metric_format_factory< Proxy > \ illumina_interop_io_##Type##Proxy##Version(new illumina::interop::io::metric_format >); -/** Ensure that static libraries are properly linked - * This must be used in a function that will definitely be linked. - * - * Tested for Microsoft Visual C++, GCC and CLang - */ -#define INTEROP_FORCE_LINK_USE(X) void force_link_metric_format(X*); force_link_metric_format(0); -/** Ensure that static libraries are properly linked - * This must be used in a file that may not be linked. - * - * Tested for Microsoft Visual C++, GCC and CLang - */ -#define INTEROP_FORCE_LINK_DEF(X) namespace illumina{namespace interop{namespace io{ void force_link_metric_format(X*){} }}} \ - void force_link_metric_format(X*){} // For Microsoft Visual C++ namespace illumina { namespace interop { namespace io { diff --git a/interop/io/format/text_format.h b/interop/io/format/text_format.h new file mode 100644 index 000000000..eeb488725 --- /dev/null +++ b/interop/io/format/text_format.h @@ -0,0 +1,92 @@ +/** Concrete text layout formats for the abstract text format interface. + * + * + * @file + * @date 12/19/16 + * @version 1.0 + * @copyright GNU Public License. + */ +#pragma once +#ifdef _MSC_VER +#pragma warning(disable:4702) // MSVC warns that there is unreachable code +#endif + + +#include "interop/util/exception.h" +#include "interop/io/format/abstract_text_format.h" +#include "interop/io/format/generic_layout.h" + +namespace illumina { namespace interop { namespace io +{ + /** Shared functionality for writing text InterOp metrics + */ + template + struct text_format; + /** Shared functionality for writing text InterOp metrics + * + * Specialization for text_layout + */ + template + struct text_format > : public abstract_text_format + { + private: + typedef text_layout layout_t; + typedef typename Metric::id_t id_t; + public: + /** Define the metric type */ + typedef Metric metric_t; + /** Define the metric header type */ + typedef typename Metric::header_type header_t; + + /** Write the header of text format to the given output stream + * + * @param out output stream to write the binary InterOp file data + * @param header header of a metric set + * @param channel_names list of channel names + * @param sep column seperator + * @param eol row separator + * @return number of column headers + */ + size_t write_header(std::ostream &out, + const header_t &header, + const std::vector& channel_names, + const char sep, + const char eol) + { + out << "# " << Metric::prefix() << Metric::suffix() << sep; + out << Version << eol; + return layout_t::write_header(out, header, channel_names, sep, eol); + } + + /** Write a text record to the given output stream + * + * @param out output stream + * @param metric a metric to write + * @param header metric set header + * @param sep column seperator + * @param eol row separator + * @param missing missing value indicator + * @return number of columns written + */ + size_t write_metric(std::ostream &out, + const metric_t &metric, + const header_t &header, + const char sep, + const char eol, + const char missing) + { + return layout_t::write_metric(out, metric, header, sep, eol, missing); + } + + /** Get the version of this metric format + * + * @return version number + */ + ::int16_t version() const + { + return static_cast< ::int16_t >(Version); + } + }; +}}} + + diff --git a/interop/io/format/text_format_factory.h b/interop/io/format/text_format_factory.h new file mode 100644 index 000000000..a0246f10c --- /dev/null +++ b/interop/io/format/text_format_factory.h @@ -0,0 +1,125 @@ +/** Factory for generating text formats + * + * @file + * @date 12/19/16 + * @version 1.0 + * @copyright GNU Public License. + */ +#pragma once + +#include +#include "interop/util/map.h" +#include "interop/util/assert.h" +#include "interop/util/self_registration.h" +#include "interop/io/format/abstract_text_format.h" +#include "interop/util/unique_ptr.h" +#include "interop/io/stream_exceptions.h" + +/** Register a text format with the factory + * + * @param Metric metric class + * @param Version version number + */ +#define INTEROP_REGISTER_METRIC_TEXT_LAYOUT(Metric, Version) \ + illumina::interop::io::text_format_factory_proxy< Metric > \ + illumina_interop_io_text_##Type##Metric##Version(new illumina::interop::io::text_format >); + + +namespace illumina { namespace interop { namespace io +{ + /** Factory for generating text formats + * + * This class defines static methods to register a metric format. The registered metric formats can + * be accessed through the `instance()` static function. + * + * @note this is not thread safe + */ + template + struct text_format_factory + { + /** Define the metric type */ + typedef Metric metric_type; + /** Define the abstract format type */ + typedef abstract_text_format abstract_text_format_t; + /** Define the header type */ + typedef typename Metric::header_type header_type; + /** Define a unique pointer to a metric format */ + typedef stdbp::unique_ptr metric_format_pointer; + /** Define a map between format version and the format */ + typedef INTEROP_UNORDERED_MAP(int, metric_format_pointer) text_format_map; + + /** Find a format for a given version + * + * If the format is not found, return null + * + * @param version version to search for + * @return pointer to format or null + */ + abstract_text_format_t* find(int version) + { + if(version < 0) version = m_latest_version; + typename text_format_map::iterator it = m_format_map.find(version); + if(it == m_format_map.end()) return 0; + return &(*it->second); + } + + /** Add a text format to the factory + * + * @param pformat format to add + */ + void add(abstract_text_format_t *pformat) + { + const int version = pformat->version(); + if(version > m_latest_version) m_latest_version = version; + m_format_map[version] = metric_format_pointer(pformat); + } + /** Get number of text formats + * + * @return number of text formats + */ + size_t size()const + { + return m_format_map.size(); + } + + /** Instance of the factory singleton + * + * @note this is not thread safe + * @return instance to singleton + */ + static text_format_factory &instance() + { + INTEROP_FORCE_LINK_USE(metric_type); + static text_format_factory _inst; + return _inst; + } + + private: + text_format_factory() : m_latest_version(-1) {} + text_format_map m_format_map; + int m_latest_version; + + }; + /** Proxy for registering text formats + */ + template + struct text_format_factory_proxy + { + /** Define the metric type */ + typedef Metric metric_type; + /** Define the abstract format type */ + typedef abstract_text_format abstract_text_format_t; + /** Constructor + * + * This constructor is used to statically register a text format in a source file. + */ + text_format_factory_proxy(abstract_text_format_t *pformat) + { + text_format_factory::instance().add(pformat); + } + }; + +}}} + + + diff --git a/interop/io/metric_stream.h b/interop/io/metric_stream.h index a0810c1e0..eb5305fef 100644 --- a/interop/io/metric_stream.h +++ b/interop/io/metric_stream.h @@ -11,6 +11,7 @@ #include "interop/util/exception.h" #include "interop/model/model_exceptions.h" #include "interop/io/format/metric_format_factory.h" +#include "interop/io/format/text_format_factory.h" #include "interop/io/paths.h" #include "interop/util/filesystem.h" #include "interop/util/assert.h" @@ -273,7 +274,7 @@ namespace illumina { namespace interop { namespace io format_map[version]->write_metric_header(out, header); } - /** Write a metric header to a binary Interop output stream + /** Write a set of metrics to a binary Interop output stream * * @param out output stream * @param metrics set of metrics @@ -300,6 +301,44 @@ namespace illumina { namespace interop { namespace io it != metrics.end(); it++) format_map[version]->write_metric(out, *it, metrics); } + /** Write a set of metrics to a text output stream + * + * @param out output stream + * @param metrics set of metrics + * @param channel_names list of channel names + * @param version version of the InterOp to write (if less than 0, get from metric set) + * @param sep column separator + * @param eol row separator + * @param missing missing value indicator + */ + template + static void write_text(std::ostream &out, + const MetricSet &metrics, + const std::vector& channel_names, + ::int16_t version = -1, + const char sep=',', + const char eol='\n', + const char missing='-') + { + typedef typename MetricSet::metric_type metric_type; + typedef text_format_factory factory_type; + typedef typename factory_type::abstract_text_format_t* abstract_text_format_pointer_t; + + factory_type &factory = factory_type::instance(); + abstract_text_format_pointer_t format = factory.find(version); + if (format == 0) + INTEROP_THROW(bad_format_exception, + "No format found to write file with version: " + << version << " of " << factory.size() + << " for " << metric_type::prefix() << "" << metric_type::suffix() + << " with " << metrics.size() << " metrics"); + INTEROP_ASSERT(format); + format->write_header(out, metrics, channel_names, sep, eol); + for (typename MetricSet::const_iterator it = metrics.begin(); + it != metrics.end(); it++) + format->write_metric(out, *it, metrics, sep, eol, missing); + + } }}} diff --git a/interop/model/metrics/extraction_metric.h b/interop/model/metrics/extraction_metric.h index a34df1251..80edea5d9 100644 --- a/interop/model/metrics/extraction_metric.h +++ b/interop/model/metrics/extraction_metric.h @@ -25,6 +25,49 @@ namespace illumina { namespace interop { namespace model { namespace metrics { + /** Header information for writing an image metric set + */ + class extraction_metric_header : public metric_base::base_cycle_metric::header_type + { + public: + enum{ + /** Maximum number of channels supported **/ + MAX_CHANNELS=4 + }; + /** Unsigned int16_t + */ + typedef ::uint16_t ushort_t; + public: + /** Constructor + * + * @param channel_count number of channels + */ + extraction_metric_header(ushort_t channel_count) : m_channel_count(channel_count) {} + /** Number of channels + * + * @return number of channels + */ + ushort_t channel_count()const{return m_channel_count;} + /** Generate a default header + * + * @return default header + */ + static extraction_metric_header default_header() + { + return extraction_metric_header(MAX_CHANNELS); + } + /** Clear the data + */ + void clear() + { + m_channel_count=MAX_CHANNELS; + metric_base::base_cycle_metric::header_type::clear(); + } + private: + ushort_t m_channel_count; + template + friend struct io::generic_layout; + }; /** Extraction metric * * The extraction metrics include the max intensity and the focus score for each color channel. @@ -43,6 +86,8 @@ namespace illumina { namespace interop { namespace model { namespace metrics /** Latest version of the InterOp format */ LATEST_VERSION = 2 }; + /** Extraction metric header */ + typedef extraction_metric_header header_type; /** Define a uint16_t array using an underlying vector */ typedef std::vector ushort_array_t; @@ -68,13 +113,15 @@ namespace illumina { namespace interop { namespace model { namespace metrics { } /** Constructor + * + * @param header extraction metric header */ - extraction_metric(const header_type&) : + extraction_metric(const header_type& header) : metric_base::base_cycle_metric(0, 0, 0), m_date_time_csharp(0), m_date_time(0), - m_max_intensity_values(MAX_CHANNELS, 0), - m_focus_scores(MAX_CHANNELS, 0) + m_max_intensity_values(header.channel_count(), 0), + m_focus_scores(header.channel_count(), 0) { } diff --git a/interop/model/metrics/q_metric.h b/interop/model/metrics/q_metric.h index cde388be9..9a13a1985 100644 --- a/interop/model/metrics/q_metric.h +++ b/interop/model/metrics/q_metric.h @@ -171,6 +171,12 @@ namespace illumina { namespace interop { namespace model { namespace metrics */ size_t bin_count() const { return m_qscore_bins.size(); } + /** Get the number of bins in header + * + * @return number of bins in header + */ + size_t q_val_count() const + { return m_qscore_bins.empty() ? static_cast(MAX_Q_BINS) : m_qscore_bins.size(); } /** Get the index for the given q-value * diff --git a/interop/util/self_registration.h b/interop/util/self_registration.h new file mode 100644 index 000000000..f824c065e --- /dev/null +++ b/interop/util/self_registration.h @@ -0,0 +1,22 @@ +/** Ensure self registration classes properly link + * + * @file + * @date 12/19/16 + * @version 1.0 + * @copyright GNU Public License. + */ +#pragma once + +/** Ensure that static libraries are properly linked + * This must be used in a function that will definitely be linked. + * + * Tested for Microsoft Visual C++, GCC and CLang + */ +#define INTEROP_FORCE_LINK_USE(X) void force_link_metric_format(X*); force_link_metric_format(0); +/** Ensure that static libraries are properly linked + * This must be used in a file that may not be linked. + * + * Tested for Microsoft Visual C++, GCC and CLang + */ +#define INTEROP_FORCE_LINK_DEF(X) namespace illumina{namespace interop{namespace io{ void force_link_metric_format(X*){} }}} \ + void force_link_metric_format(X*){} // For Microsoft Visual C++ diff --git a/src/apps/CMakeLists.txt b/src/apps/CMakeLists.txt index 7e060e754..28aacfeb2 100644 --- a/src/apps/CMakeLists.txt +++ b/src/apps/CMakeLists.txt @@ -31,6 +31,7 @@ endfunction() set(SWIG_VERSION_INFO "") add_application(interop2csv interop2csv.cpp) +add_application(dumptext dumptext.cpp) add_application(cyclesim cyclesim.cpp) add_application(summary summary.cpp) add_application(index-summary index_summary.cpp) diff --git a/src/apps/dumptext.cpp b/src/apps/dumptext.cpp new file mode 100644 index 000000000..fd16f6da8 --- /dev/null +++ b/src/apps/dumptext.cpp @@ -0,0 +1,164 @@ +/** @page dumpbin Dump Interop data into a text format + * + * + * This developer application is to help debug InterOp files. + * + * ### Running the Program + * + * The program runs as follows: + * + * $ dumptext 140131_1287_0851_A01n401drr + * + * In this sample, 140131_1287_0851_A01n401drr is a run folder and the summary is written to the standard output. + * + * # Version: v1.0.4-70-g9bcfb5a-dirty + * + */ + +#include +#include +#include "interop/io/metric_file_stream.h" +#include "interop/model/run_metrics.h" +#include "interop/util/option_parser.h" +#include "interop/version.h" +#include "inc/application.h" + +using namespace illumina::interop::model::metrics; +using namespace illumina::interop; + +/** Call back functor for writing text data to the output stream + */ +struct metric_writer +{ + /** Constructor + * + * @param out output stream + * @param channels list of channel names + */ + metric_writer(std::ostream& out, const std::vector& channels) : m_out(out), m_channel_names(channels){} + /** Function operator overload to write data + * + * @param metrics set of metrics + */ + template + void operator()(const MetricSet& metrics)const + { + if(metrics.empty()) return; + io::write_text(m_out, metrics, m_channel_names); + } +private: + std::ostream& m_out; + std::vector m_channel_names; + +}; +/** Copy of subset of metrics + */ +struct subset_copier +{ + /** Constructor + * + * @param run run metrics + * @param total number to subsample + */ + subset_copier(run_metrics& run, const size_t total) : m_run(run), m_total(total){} + + /** Function operator overload to collect a subset of metrics + * + * @param metrics set of metrics + */ + template + void operator()(const MetricSet& metrics)const + { + m_run.get() = MetricSet(metrics, metrics.version()); + const size_t total = std::min(m_total, metrics.size()); + + for(size_t i=0;i().insert(metrics.at(i)); + } +private: + run_metrics& m_run; + size_t m_total; +}; + +int main(int argc, const char** argv) +{ + if(argc == 0) + { + std::cerr << "No arguments specified!" << std::endl; + //print_help(std::cout); + return INVALID_ARGUMENTS; + } + + const char eol = '\n'; + + std::cout << "# Version: " << INTEROP_VERSION << std::endl; + + size_t subset_count=0; + util::option_parser description; + description + (subset_count, "subset", "Number of metrics to subsample"); + if(description.is_help_requested(argc, argv)) + { + std::cout << "Usage: " << io::basename(argv[0]) << " run_folder [--option1=value1] [--option2=value2]" << std::endl; + description.display_help(std::cout); + return SUCCESS; + } + try{ + description.parse(argc, argv); + description.check_for_unknown_options(argc, argv); + } + catch(const util::option_exception& ex) + { + std::cerr << ex.what() << std::endl; + return INVALID_ARGUMENTS; + } + + for(int i=1;i 0 ) + { + run_metrics subset; + subset_copier copy_subset(subset, subset_count); + try + { + run.metrics_callback(copy_subset); + } + catch (const std::exception &ex) + { + std::cerr << ex.what() << std::endl; + return UNEXPECTED_EXCEPTION; + } + try + { + subset.metrics_callback(write_metrics); + } + catch (const io::bad_format_exception &ex) + { + std::cerr << ex.what() << std::endl; + return BAD_FORMAT; + } + } + else + { + try + { + run.metrics_callback(write_metrics); + } + catch (const io::bad_format_exception &ex) + { + std::cerr << ex.what() << std::endl; + return BAD_FORMAT; + } + } + std::cout << eol << std::endl; + + } + return SUCCESS; +} + + + diff --git a/src/apps/interop2csv.cpp b/src/apps/interop2csv.cpp index 8b24e77de..144e7c3cd 100644 --- a/src/apps/interop2csv.cpp +++ b/src/apps/interop2csv.cpp @@ -4,6 +4,8 @@ * the data as a special type of CSV (common separated format) file. The program takes the run folder as an input * and then writes the data as plain text to the console. This data can then be redirected to a file. * + * @warning This program is deprecated and will be removed. Use dumptext instead + * * ### Running the Program * * The program runs as follows: @@ -694,7 +696,7 @@ int write_index_metrics(std::ostream& out, const std::string& filename) if(res != 0) return res; write_header(out, metrics); - out << "Lane,Tile,Read,Sequence,Sample,Project,Count\n"; + out << "Lane,Tile,Read,Sequence,Sample,Project,ClusterCount\n"; for(index_metric_set::metric_array_t::const_iterator beg = metrics.begin(), end = vec_end(metrics);beg != end;++beg) { const index_metric& metric = *beg; diff --git a/src/interop/CMakeLists.txt b/src/interop/CMakeLists.txt index d9d9a6df0..ec20e6b82 100644 --- a/src/interop/CMakeLists.txt +++ b/src/interop/CMakeLists.txt @@ -150,6 +150,10 @@ set(HEADERS ../../interop/util/map.h ../../interop/util/timer.h ../../interop/constants/enum_description.h + ../../interop/io/format/abstract_text_format.h + ../../interop/io/format/text_format.h + ../../interop/util/self_registration.h + ../../interop/io/format/text_format_factory.h ) set(INTEROP_HEADERS ${HEADERS} PARENT_SCOPE) diff --git a/src/interop/model/metrics/corrected_intensity_metric.cpp b/src/interop/model/metrics/corrected_intensity_metric.cpp index bf0903e86..1052ac04f 100644 --- a/src/interop/model/metrics/corrected_intensity_metric.cpp +++ b/src/interop/model/metrics/corrected_intensity_metric.cpp @@ -10,8 +10,11 @@ #include "interop/model/metrics/corrected_intensity_metric.h" #include "interop/io/format/metric_format_factory.h" +#include "interop/io/format/text_format_factory.h" #include "interop/io/format/default_layout.h" #include "interop/io/format/metric_format.h" +#include "interop/io/format/text_format.h" +#include "interop/logic/utils/enums.h" using namespace illumina::interop::model::metrics; @@ -219,10 +222,93 @@ namespace illumina{ namespace interop{ namespace io }; #pragma pack() + + + /** Corrected intensity Metric CSV text format + * + * This class provide an interface for writing the corrected intensity metrics to a CSV file: + * + * - CorrectedIntMetrics.csv + */ + template<> + struct text_layout< corrected_intensity_metric, 1 > + { + /** Define a header type */ + typedef corrected_intensity_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&, + const char sep, + const char eol) + { + const char* column_headers[] = + { + "Lane", "Tile", "Cycle", "AverageCycleIntensity", "SignalToNoise" + }; + const char* subcolumn_headers[] = + { + "CalledCount", "CalledIntensity", "AllIntensity" + }; + std::vector bases; + constants::list_enum_names(bases); + std::vector headers; + headers.reserve(util::length_of(column_headers)+util::length_of(subcolumn_headers)*5); + for(size_t i=0;i(constants::NUM_OF_BASES_AND_NC);++i) + headers.push_back(std::string()+subcolumn_headers[0]+"_"+bases[i]); + for(size_t i=1;i(constants::NUM_OF_BASES_AND_NC);++j) + headers.push_back(std::string()+subcolumn_headers[i]+"_"+bases[j]); + } + out << "# Column Count: " << util::length_of(headers) << eol; + out << headers[0]; + for(size_t i=1;i(i)); + for(size_t i=0;i(i)); + for(size_t i=0;i(i)); + out << eol; + return 0; + } + }; }}} +INTEROP_FORCE_LINK_DEF(corrected_intensity_metric) INTEROP_REGISTER_METRIC_GENERIC_LAYOUT(corrected_intensity_metric, 2 ) INTEROP_REGISTER_METRIC_GENERIC_LAYOUT(corrected_intensity_metric, 3 ) -INTEROP_FORCE_LINK_DEF(corrected_intensity_metric) +// Text formats +INTEROP_REGISTER_METRIC_TEXT_LAYOUT(corrected_intensity_metric, 1) diff --git a/src/interop/model/metrics/error_metric.cpp b/src/interop/model/metrics/error_metric.cpp index 0a1a3250a..e63a424b4 100644 --- a/src/interop/model/metrics/error_metric.cpp +++ b/src/interop/model/metrics/error_metric.cpp @@ -9,8 +9,10 @@ */ #include "interop/model/metrics/error_metric.h" #include "interop/io/format/metric_format_factory.h" +#include "interop/io/format/text_format_factory.h" #include "interop/io/format/default_layout.h" #include "interop/io/format/metric_format.h" +#include "interop/io/format/text_format.h" using namespace illumina::interop::model::metrics; @@ -110,8 +112,66 @@ namespace illumina{ namespace interop{ namespace io #pragma pack() + /** 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, 1 > + { + /** 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&, + const char sep, + const char eol) + { + const char* headers[] = + { + "Lane", "Tile", "Cycle", "ErrorRate" + }; + out << "# Column Count: " << util::length_of(headers) << eol; + out << headers[0]; + for(size_t i=1;i + struct text_layout< extraction_metric, 1 > + { + /** Define a header type */ + typedef extraction_metric::header_type header_type; + /** Write header to the output stream + * + * @param out output stream + * @param header extraction metric header + * @param channel_names list of channel names + * @param sep column separator + * @param eol row separator + * @return number of column headers + */ + static size_t write_header(std::ostream& out, + const header_type& header, + const std::vector& channel_names, + const char sep, + const char eol) + { + if( static_cast(header.channel_count()) != channel_names.size() ) + INTEROP_THROW(bad_format_exception, "Header and channel names count mismatch"); + const char* headers[] = + { + "Lane", "Tile", "Cycle", "TimeStamp" + }; + out << "# Column Count: " << util::length_of(headers)+header.channel_count()*2 << eol; + out << "# Channel Count: " << header.channel_count() << eol; + out << headers[0]; + for(size_t i=1;i(header.channel_count());++i) + out << sep << max_intensity << "_" << channel_names[i]; + const std::string focus = "Focus"; + for(size_t i=0;i(header.channel_count());++i) + out << sep << focus << "_" << channel_names[i]; + out << eol; + return util::length_of(headers); + } + /** Write a extraction metric to the output stream + * + * @param out output stream + * @param metric extraction metric + * @param header extraction metric header + * @param sep column separator + * @param eol row separator + * @return number of columns written + */ + static size_t write_metric(std::ostream& out, + const extraction_metric& metric, + const header_type& header, + const char sep, + const char eol, + const char) + { + if( header.channel_count() != metric.channel_count() ) + INTEROP_THROW(bad_format_exception, "Header and metric channel count mismatch"); + out << metric.lane() << sep << metric.tile() << sep << metric.cycle() << sep; + out << metric.date_time(); // TODO: Format date/time + for(size_t i=0;i(header.channel_count());i++) + out << sep << metric.max_intensity(i); + for(size_t i=0;i(header.channel_count());i++) + out << sep << metric.focus_score(i); + out << eol; + return 0; + } + }; }}} INTEROP_FORCE_LINK_DEF(extraction_metric) INTEROP_REGISTER_METRIC_GENERIC_LAYOUT(extraction_metric, 2) + +// Text formats +INTEROP_REGISTER_METRIC_TEXT_LAYOUT(extraction_metric, 1) + diff --git a/src/interop/model/metrics/image_metric.cpp b/src/interop/model/metrics/image_metric.cpp index 4a452588c..424656a6a 100644 --- a/src/interop/model/metrics/image_metric.cpp +++ b/src/interop/model/metrics/image_metric.cpp @@ -11,8 +11,10 @@ #include #include "interop/model/metrics/image_metric.h" #include "interop/io/format/metric_format_factory.h" +#include "interop/io/format/text_format_factory.h" #include "interop/io/format/default_layout.h" #include "interop/io/format/metric_format.h" +#include "interop/io/format/text_format.h" using namespace illumina::interop::model::metrics; @@ -264,6 +266,79 @@ namespace illumina { namespace interop { namespace io #pragma pack() // DO NOT MOVE + /** Image Metric CSV text format + * + * This class provide an interface for writing the image metrics to a CSV file: + * + * - ImageMetrics.csv + */ + template<> + struct text_layout< image_metric, 1 > + { + /** Define a header type */ + typedef image_metric::header_type header_type; + /** Write header to the output stream + * + * @param out output stream + * @param header image metric header + * @param channel_names list of channel names + * @param sep column separator + * @param eol row separator + * @return number of column headers + */ + static size_t write_header(std::ostream& out, + const header_type& header, + const std::vector& channel_names, + const char sep, + const char eol) + { + if( static_cast(header.channel_count()) != channel_names.size() ) + INTEROP_THROW(bad_format_exception, "Header and channel names count mismatch"); + const char* headers[] = + { + "Lane", "Tile", "Cycle" + }; + out << "# Column Count: " << util::length_of(headers)+header.channel_count()*2 << eol; + out << "# Channel Count: " << header.channel_count() << eol; + out << headers[0]; + for(size_t i=1;i(header.channel_count());++i) + out << sep << min_contrast << "_" << channel_names[i]; + const std::string max_contrast = "MaxContrast"; + for(size_t i=0;i(header.channel_count());++i) + out << sep << max_contrast << "_" << channel_names[i]; + out << eol; + return util::length_of(headers); + } + /** Write a image metric to the output stream + * + * @param out output stream + * @param metric image metric + * @param header image metric header + * @param sep column separator + * @param eol row separator + * @return number of columns written + */ + static size_t write_metric(std::ostream& out, + const image_metric& metric, + const header_type& header, + const char sep, + const char eol, + const char) + { + if( header.channel_count() != metric.channel_count() ) + INTEROP_THROW(bad_format_exception, "Header and metric channel count mismatch"); + out << metric.lane() << sep << metric.tile() << sep << metric.cycle() << sep; + for(size_t i=0;i(header.channel_count());i++) + out << sep << metric.min_contrast(i); + for(size_t i=0;i(header.channel_count());i++) + out << sep << metric.max_contrast(i); + out << eol; + return 0; + } + }; }}} INTEROP_FORCE_LINK_DEF(image_metric) @@ -271,3 +346,7 @@ INTEROP_FORCE_LINK_DEF(image_metric) INTEROP_REGISTER_METRIC_GENERIC_LAYOUT(image_metric, 1) INTEROP_REGISTER_METRIC_GENERIC_LAYOUT(image_metric, 2) + +// Text formats +INTEROP_REGISTER_METRIC_TEXT_LAYOUT(image_metric, 1) + diff --git a/src/interop/model/metrics/index_metric.cpp b/src/interop/model/metrics/index_metric.cpp index 659fc1441..062889dba 100644 --- a/src/interop/model/metrics/index_metric.cpp +++ b/src/interop/model/metrics/index_metric.cpp @@ -10,8 +10,10 @@ #include #include "interop/model/metrics/index_metric.h" #include "interop/io/format/metric_format_factory.h" +#include "interop/io/format/text_format_factory.h" #include "interop/io/format/default_layout.h" #include "interop/io/format/metric_format.h" +#include "interop/io/format/text_format.h" using namespace illumina::interop::model::metrics; @@ -172,9 +174,73 @@ namespace illumina { namespace interop { namespace io }; #pragma pack() + /** Tile Metric CSV text format + * + * This class provide an interface for writing the tile metrics to a CSV file: + * + * - TileMetrics.csv + */ + template<> + struct text_layout< index_metric, 1 > + { + /** Define a header type */ + typedef index_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&, + const char sep, + const char eol) + { + const char* headers[] = + { + "Lane", "Tile", "Read", "Sequence", "Sample", "Project", "ClusterCount" + }; + out << "# Column Count: " << util::length_of(headers) << eol; + out << headers[0]; + for(size_t i=1;iindex_seq() << sep << index_beg->sample_id(); + out << sep << index_beg->sample_proj() << sep << index_beg->cluster_count() << eol; + } + return 0; + } + }; }}} INTEROP_FORCE_LINK_DEF(index_metric) INTEROP_REGISTER_METRIC_GENERIC_LAYOUT(index_metric, 1) + +// Text formats +INTEROP_REGISTER_METRIC_TEXT_LAYOUT(index_metric, 1) + diff --git a/src/interop/model/metrics/q_collapsed_metric.cpp b/src/interop/model/metrics/q_collapsed_metric.cpp index 07e87f80a..72bee1904 100644 --- a/src/interop/model/metrics/q_collapsed_metric.cpp +++ b/src/interop/model/metrics/q_collapsed_metric.cpp @@ -13,8 +13,10 @@ #include "interop/util/assert.h" #include "interop/model/metrics/q_collapsed_metric.h" #include "interop/io/format/metric_format_factory.h" +#include "interop/io/format/text_format_factory.h" #include "interop/io/format/default_layout.h" #include "interop/io/format/metric_format.h" +#include "interop/io/format/text_format.h" using namespace illumina::interop::model::metrics; @@ -567,6 +569,62 @@ namespace illumina{ namespace interop{ namespace io { */ enum{/**Version of the format */VERSION=6}; }; + /** Tile Metric CSV text format + * + * This class provide an interface for writing the tile metrics to a CSV file: + * + * - TileMetrics.csv + */ + template<> + struct text_layout< q_collapsed_metric, 1 > + { + /** Define a header type */ + typedef q_collapsed_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&, + const char sep, + const char eol) + { + const char* headers[] = + { + "Lane", "Tile", "Cycle", + "Q20", "Q30", "Total", "MedianQScore" + }; + out << "# Column Count: " << util::length_of(headers) << eol; + out << headers[0]; + for(size_t i=1;i + struct text_layout< q_metric, 1 > + { + /** Define a header type */ + typedef q_metric::header_type header_type; + /** Write header to the output stream + * + * @param out output stream + * @param header q-metric header + * @param sep column separator + * @param eol row separator + * @return number of column headers + */ + static size_t write_header(std::ostream& out, + const header_type& header, + const std::vector&, + const char sep, + const char eol) + { + const char* headers[] = + { + "Lane", "Tile", "Cycle" + }; + out << "# Bin Count: " << header.q_val_count() << eol; + if(header.bin_count() > 0) + { + const char* bin_headers[] = + { + "Lower", "Value", "Upper" + }; + out << "# Column Count: " << util::length_of(bin_headers) << eol; + out << bin_headers[0]; + for(size_t i=1;i(header.q_val_count()) != metric.size() ) + INTEROP_THROW(bad_format_exception, "Header and metric bin count mismatch: " + << header.q_val_count() << " != " << metric.size()); + out << metric.lane() << sep << metric.tile() << sep << metric.cycle(); + for(size_t i=0;i + struct text_layout< q_by_lane_metric, 1 > : public text_layout< q_metric, 1 > + { + }; }}} INTEROP_FORCE_LINK_DEF(q_metric) @@ -753,3 +852,6 @@ INTEROP_REGISTER_METRIC_GENERIC_LAYOUT(q_by_lane_metric, 4) INTEROP_REGISTER_METRIC_GENERIC_LAYOUT(q_by_lane_metric, 5) INTEROP_REGISTER_METRIC_GENERIC_LAYOUT(q_by_lane_metric, 6) +// Text formats +INTEROP_REGISTER_METRIC_TEXT_LAYOUT(q_metric, 1) +INTEROP_REGISTER_METRIC_TEXT_LAYOUT(q_by_lane_metric, 1) diff --git a/src/interop/model/metrics/tile_metric.cpp b/src/interop/model/metrics/tile_metric.cpp index a4952dec8..4561020c7 100644 --- a/src/interop/model/metrics/tile_metric.cpp +++ b/src/interop/model/metrics/tile_metric.cpp @@ -11,14 +11,15 @@ #include "interop/util/math.h" #include "interop/model/metrics/tile_metric.h" #include "interop/io/format/metric_format_factory.h" +#include "interop/io/format/text_format_factory.h" #include "interop/io/format/default_layout.h" #include "interop/io/format/metric_format.h" +#include "interop/io/format/text_format.h" using namespace illumina::interop::model::metrics; namespace illumina { namespace interop { namespace io { - #pragma pack(1) /** Tile Metric Record Layout Version 2 @@ -266,8 +267,86 @@ namespace illumina { namespace interop { namespace io #pragma pack() + /** Tile Metric CSV text format + * + * This class provide an interface for writing the tile metrics to a CSV file: + * + * - TileMetrics.csv + */ + template<> + struct text_layout< tile_metric, 1 > + { + /** Define a header type */ + typedef tile_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&, + const char sep, + const char eol) + { + const char* headers[] = + { + "Lane", "Tile", "Read", + "ClusterCount", "ClusterCountPF", "Density", "DensityPF", "Aligned", "Prephasing", "Phasing" + }; + out << "# Column Count: " << util::length_of(headers) << eol; + out << headers[0]; + for(size_t i=1;iread() << sep; + out << metric.cluster_count() << sep << metric.cluster_count_pf() << sep; + out << metric.cluster_density() << sep << metric.cluster_density_pf() << sep; + out << rbeg->percent_aligned() << sep << rbeg->percent_prephasing() + << sep << rbeg->percent_phasing(); + out << eol; + } + } + return 0; + } + }; }}} INTEROP_FORCE_LINK_DEF(tile_metric) INTEROP_REGISTER_METRIC_GENERIC_LAYOUT(tile_metric, 2) +// Text formats +INTEROP_REGISTER_METRIC_TEXT_LAYOUT(tile_metric, 1) diff --git a/src/tests/csharp/metrics/ExtractionMetricsTest.cs b/src/tests/csharp/metrics/ExtractionMetricsTest.cs index 623f205bb..e00960045 100644 --- a/src/tests/csharp/metrics/ExtractionMetricsTest.cs +++ b/src/tests/csharp/metrics/ExtractionMetricsTest.cs @@ -24,7 +24,7 @@ public class ExtractionMetricsTestV2 [SetUp] protected void SetUp() { - base_cycle_metric_header header = new base_cycle_metric_header(); + extraction_metric_header header = new extraction_metric_header(2); float[] focus1 = new float[]{2.24664021f, 2.1896739f, 0, 0}; ushort[] p90_1 = new ushort[]{302, 273, 0, 0}; expected_metrics.Add(new extraction_metric(7, 1114, 1, new csharp_date_time(9859129975844165472ul), (p90_1), (focus1), 4)); diff --git a/src/tests/csharp/metrics/PerformanceTest.cs b/src/tests/csharp/metrics/PerformanceTest.cs index 30be2e6ca..24e62e9a2 100644 --- a/src/tests/csharp/metrics/PerformanceTest.cs +++ b/src/tests/csharp/metrics/PerformanceTest.cs @@ -21,7 +21,7 @@ public class ExtractionMetricsPerformanceTestV2 [SetUp] protected void SetUp() { - base_cycle_metric_header header = new base_cycle_metric_header(); + extraction_metric_header header = new extraction_metric_header(2); if(metrics.Count == 0) { System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();