<commit_before>/*  This file is part of the Vc library.

    Copyright (C) 2010 Matthias Kretz <kretz@kde.org>

    Vc is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as
    published by the Free Software Foundation, either version 3 of
    the License, or (at your option) any later version.

    Vc is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with Vc.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "macros.h"

namespace Vc
{
namespace SSE
{

template<typename T> inline Vector<T>::Vector(VectorSpecialInitializerZero::ZEnum)
    : Base(VectorHelper<VectorType>::zero())
{
}

template<typename T> inline Vector<T>::Vector(VectorSpecialInitializerOne::OEnum)
    : Base(VectorHelper<T>::one())
{
}

template<typename T> inline Vector<T>::Vector(VectorSpecialInitializerIndexesFromZero::IEnum)
    : Base(VectorHelper<VectorType>::load(Base::_IndexesFromZero(), Aligned))
{
}

template<typename T> inline Vector<T> Vector<T>::Zero()
{
    return VectorHelper<VectorType>::zero();
}

template<typename T> inline Vector<T> Vector<T>::IndexesFromZero()
{
    return VectorHelper<VectorType>::load(Base::_IndexesFromZero(), Aligned);
}

template<typename T> template<typename OtherT> inline Vector<T>::Vector(const Vector<OtherT> &x)
    : Base(StaticCastHelper<OtherT, T>::cast(x.data()))
{
}

template<typename T> inline Vector<T>::Vector(EntryType a)
    : Base(VectorHelper<T>::set(a))
{
}

template<typename T> inline Vector<T>::Vector(const EntryType *x)
    : Base(VectorHelper<VectorType>::load(x, Aligned))
{
}

template<typename T> template<typename A> inline Vector<T>::Vector(const EntryType *x, A align)
    : Base(VectorHelper<VectorType>::load(x, align))
{
}

template<typename T> inline Vector<T>::Vector(const Vector<typename CtorTypeHelper<T>::Type> *a)
    : Base(VectorHelper<T>::concat(a[0].data(), a[1].data()))
{
}

template<typename T> inline void Vector<T>::expand(Vector<typename ExpandTypeHelper<T>::Type> *x) const
{
    if (Size == 8u) {
        x[0].data() = VectorHelper<T>::expand0(data());
        x[1].data() = VectorHelper<T>::expand1(data());
    }
}

template<typename T> inline void Vector<T>::load(const EntryType *mem)
{
    data() = VectorHelper<VectorType>::load(mem, Aligned);
}

template<typename T> template<typename A> inline void Vector<T>::load(const EntryType *mem, A align)
{
    data() = VectorHelper<VectorType>::load(mem, align);
}

template<typename T> inline void Vector<T>::makeZero()
{
    data() = VectorHelper<VectorType>::zero();
}

template<typename T> inline void Vector<T>::makeZero(const Mask &k)
{
    data() = VectorHelper<VectorType>::andnot_(mm128_reinterpret_cast<VectorType>(k.data()), data());
}

template<typename T> inline void Vector<T>::store(EntryType *mem) const
{
    VectorHelper<VectorType>::store(mem, data(), Aligned);
}

template<typename T> inline void Vector<T>::store(EntryType *mem, const Mask &mask) const
{
    // this executes an unaligned store because SSE does not implement aligned masked stores
    VectorHelper<VectorType>::store(mem, data(), mm128_reinterpret_cast<VectorType>(mask.data()));
}

template<typename T> template<typename A> inline void Vector<T>::store(EntryType *mem, A align) const
{
    VectorHelper<VectorType>::store(mem, data(), align);
}

template<typename T> template<typename A> inline void Vector<T>::store(EntryType *mem, const Mask &mask, A) const
{
    store(mem, mask);
}

template<typename T> inline Vector<T> &Vector<T>::operator/=(EntryType x)
{
    if (Base::HasVectorDivision) {
        return operator/=(Vector<T>(x));
    }
    for_all_vector_entries(i,
            d.m(i) /= x;
            );
    return *this;
}

template<typename T> inline Vector<T> Vector<T>::operator/(EntryType x) const
{
    if (Base::HasVectorDivision) {
        return operator/(Vector<T>(x));
    }
    Vector<T> r;
    for_all_vector_entries(i,
            r.d.m(i) = d.m(i) / x;
            );
    return r;
}

template<typename T> inline Vector<T> &Vector<T>::operator/=(const Vector<T> &x)
{
    for_all_vector_entries(i,
            d.m(i) /= x.d.m(i);
            );
    return *this;
}

template<typename T> inline Vector<T> Vector<T>::operator/(const Vector<T> &x) const
{
    Vector<T> r;
    for_all_vector_entries(i,
            r.d.m(i) = d.m(i) / x.d.m(i);
            );
    return r;
}

template<> inline Vector<float> &Vector<float>::operator/=(const Vector<float> &x)
{
    d.v() = _mm_div_ps(d.v(), x.d.v());
    return *this;
}

template<> inline Vector<float> Vector<float>::operator/(const Vector<float> &x) const
{
    return _mm_div_ps(d.v(), x.d.v());
}

template<> inline Vector<float8> &Vector<float8>::operator/=(const Vector<float8> &x)
{
    d.v()[0] = _mm_div_ps(d.v()[0], x.d.v()[0]);
    d.v()[1] = _mm_div_ps(d.v()[1], x.d.v()[1]);
    return *this;
}

template<> inline Vector<float8> Vector<float8>::operator/(const Vector<float8> &x) const
{
    Vector<float8> r;
    r.d.v()[0] = _mm_div_ps(d.v()[0], x.d.v()[0]);
    r.d.v()[1] = _mm_div_ps(d.v()[1], x.d.v()[1]);
    return r;
}

template<> inline Vector<double> &Vector<double>::operator/=(const Vector<double> &x)
{
    d.v() = _mm_div_pd(d.v(), x.d.v());
    return *this;
}

template<> inline Vector<double> Vector<double>::operator/(const Vector<double> &x) const
{
    return _mm_div_pd(d.v(), x.d.v());
}

#define OP_IMPL(T, symbol, fun) \
template<> inline Vector<T> &VectorBase<T>::operator symbol##=(const VectorBase<T> &x) \
{ \
    d.v() = VectorHelper<T>::fun(d.v(), x.d.v()); \
    return *static_cast<Vector<T> *>(this); \
} \
template<> inline Vector<T>  VectorBase<T>::operator symbol(const VectorBase<T> &x) const \
{ \
    return Vector<T>(VectorHelper<T>::fun(d.v(), x.d.v())); \
}
OP_IMPL(int, &, and_)
OP_IMPL(int, |, or_)
OP_IMPL(int, ^, xor_)
OP_IMPL(int, <<, sll)
OP_IMPL(int, >>, srl)
OP_IMPL(unsigned int, &, and_)
OP_IMPL(unsigned int, |, or_)
OP_IMPL(unsigned int, ^, xor_)
OP_IMPL(unsigned int, <<, sll)
OP_IMPL(unsigned int, >>, srl)
OP_IMPL(short, &, and_)
OP_IMPL(short, |, or_)
OP_IMPL(short, ^, xor_)
OP_IMPL(short, <<, sll)
OP_IMPL(short, >>, srl)
OP_IMPL(unsigned short, &, and_)
OP_IMPL(unsigned short, |, or_)
OP_IMPL(unsigned short, ^, xor_)
OP_IMPL(unsigned short, <<, sll)
OP_IMPL(unsigned short, >>, srl)
#undef OP_IMPL

#define OP_IMPL(T, SUFFIX) \
template<> inline Vector<T> &VectorBase<T>::operator<<=(int x) \
{ \
    d.v() = CAT(_mm_slli_epi, SUFFIX)(d.v(), x); \
    return *static_cast<Vector<T> *>(this); \
} \
template<> inline Vector<T> &VectorBase<T>::operator>>=(int x) \
{ \
    d.v() = CAT(_mm_srli_epi, SUFFIX)(d.v(), x); \
    return *static_cast<Vector<T> *>(this); \
} \
template<> inline Vector<T> VectorBase<T>::operator<<(int x) const \
{ \
    return CAT(_mm_slli_epi, SUFFIX)(d.v(), x); \
} \
template<> inline Vector<T> VectorBase<T>::operator>>(int x) const \
{ \
    return CAT(_mm_srli_epi, SUFFIX)(d.v(), x); \
}
OP_IMPL(int, 32)
OP_IMPL(unsigned int, 32)
OP_IMPL(short, 16)
OP_IMPL(unsigned short, 16)
#undef OP_IMPL

} // namespace SSE
} // namespace Vc

#include "undomacros.h"
<commit_msg>implement SSE::short_v division with _mm_div_ps<commit_after>/*  This file is part of the Vc library.

    Copyright (C) 2010 Matthias Kretz <kretz@kde.org>

    Vc is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as
    published by the Free Software Foundation, either version 3 of
    the License, or (at your option) any later version.

    Vc is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with Vc.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "macros.h"

namespace Vc
{
namespace SSE
{

template<typename T> inline Vector<T>::Vector(VectorSpecialInitializerZero::ZEnum)
    : Base(VectorHelper<VectorType>::zero())
{
}

template<typename T> inline Vector<T>::Vector(VectorSpecialInitializerOne::OEnum)
    : Base(VectorHelper<T>::one())
{
}

template<typename T> inline Vector<T>::Vector(VectorSpecialInitializerIndexesFromZero::IEnum)
    : Base(VectorHelper<VectorType>::load(Base::_IndexesFromZero(), Aligned))
{
}

template<typename T> inline Vector<T> Vector<T>::Zero()
{
    return VectorHelper<VectorType>::zero();
}

template<typename T> inline Vector<T> Vector<T>::IndexesFromZero()
{
    return VectorHelper<VectorType>::load(Base::_IndexesFromZero(), Aligned);
}

template<typename T> template<typename OtherT> inline Vector<T>::Vector(const Vector<OtherT> &x)
    : Base(StaticCastHelper<OtherT, T>::cast(x.data()))
{
}

template<typename T> inline Vector<T>::Vector(EntryType a)
    : Base(VectorHelper<T>::set(a))
{
}

template<typename T> inline Vector<T>::Vector(const EntryType *x)
    : Base(VectorHelper<VectorType>::load(x, Aligned))
{
}

template<typename T> template<typename A> inline Vector<T>::Vector(const EntryType *x, A align)
    : Base(VectorHelper<VectorType>::load(x, align))
{
}

template<typename T> inline Vector<T>::Vector(const Vector<typename CtorTypeHelper<T>::Type> *a)
    : Base(VectorHelper<T>::concat(a[0].data(), a[1].data()))
{
}

template<typename T> inline void Vector<T>::expand(Vector<typename ExpandTypeHelper<T>::Type> *x) const
{
    if (Size == 8u) {
        x[0].data() = VectorHelper<T>::expand0(data());
        x[1].data() = VectorHelper<T>::expand1(data());
    }
}

template<typename T> inline void Vector<T>::load(const EntryType *mem)
{
    data() = VectorHelper<VectorType>::load(mem, Aligned);
}

template<typename T> template<typename A> inline void Vector<T>::load(const EntryType *mem, A align)
{
    data() = VectorHelper<VectorType>::load(mem, align);
}

template<typename T> inline void Vector<T>::makeZero()
{
    data() = VectorHelper<VectorType>::zero();
}

template<typename T> inline void Vector<T>::makeZero(const Mask &k)
{
    data() = VectorHelper<VectorType>::andnot_(mm128_reinterpret_cast<VectorType>(k.data()), data());
}

template<typename T> inline void Vector<T>::store(EntryType *mem) const
{
    VectorHelper<VectorType>::store(mem, data(), Aligned);
}

template<typename T> inline void Vector<T>::store(EntryType *mem, const Mask &mask) const
{
    // this executes an unaligned store because SSE does not implement aligned masked stores
    VectorHelper<VectorType>::store(mem, data(), mm128_reinterpret_cast<VectorType>(mask.data()));
}

template<typename T> template<typename A> inline void Vector<T>::store(EntryType *mem, A align) const
{
    VectorHelper<VectorType>::store(mem, data(), align);
}

template<typename T> template<typename A> inline void Vector<T>::store(EntryType *mem, const Mask &mask, A) const
{
    store(mem, mask);
}

template<typename T> inline Vector<T> &Vector<T>::operator/=(EntryType x)
{
    if (Base::HasVectorDivision) {
        return operator/=(Vector<T>(x));
    }
    for_all_vector_entries(i,
            d.m(i) /= x;
            );
    return *this;
}

template<typename T> inline Vector<T> Vector<T>::operator/(EntryType x) const
{
    if (Base::HasVectorDivision) {
        return operator/(Vector<T>(x));
    }
    Vector<T> r;
    for_all_vector_entries(i,
            r.d.m(i) = d.m(i) / x;
            );
    return r;
}

template<typename T> inline Vector<T> &Vector<T>::operator/=(const Vector<T> &x)
{
    for_all_vector_entries(i,
            d.m(i) /= x.d.m(i);
            );
    return *this;
}

template<typename T> inline Vector<T> Vector<T>::operator/(const Vector<T> &x) const
{
    Vector<T> r;
    for_all_vector_entries(i,
            r.d.m(i) = d.m(i) / x.d.m(i);
            );
    return r;
}

template<> inline Vector<short> &Vector<short>::operator/=(const Vector<short> &x)
{
    __m128 lo = _mm_cvtepi32_ps(_mm_unpacklo_epi16(d.v(), _mm_setzero_si128()));
    __m128 hi = _mm_cvtepi32_ps(_mm_unpackhi_epi16(d.v(), _mm_setzero_si128()));
    lo = _mm_div_ps(lo, _mm_cvtepi32_ps(_mm_unpacklo_epi16(x.d.v(), _mm_setzero_si128())));
    hi = _mm_div_ps(hi, _mm_cvtepi32_ps(_mm_unpackhi_epi16(x.d.v(), _mm_setzero_si128())));
    d.v() = _mm_packs_epi32(_mm_cvtps_epi32(lo), _mm_cvtps_epi32(hi));
    return *this;
}

template<> inline Vector<short> Vector<short>::operator/(const Vector<short> &x) const
{
    __m128 lo = _mm_cvtepi32_ps(_mm_unpacklo_epi16(d.v(), _mm_setzero_si128()));
    __m128 hi = _mm_cvtepi32_ps(_mm_unpackhi_epi16(d.v(), _mm_setzero_si128()));
    lo = _mm_div_ps(lo, _mm_cvtepi32_ps(_mm_unpacklo_epi16(x.d.v(), _mm_setzero_si128())));
    hi = _mm_div_ps(hi, _mm_cvtepi32_ps(_mm_unpackhi_epi16(x.d.v(), _mm_setzero_si128())));
    return _mm_packs_epi32(_mm_cvtps_epi32(lo), _mm_cvtps_epi32(hi));
}

template<> inline Vector<unsigned short> &Vector<unsigned short>::operator/=(const Vector<unsigned short> &x)
{
    __m128 lo = _mm_cvtepi32_ps(_mm_unpacklo_epi16(d.v(), _mm_setzero_si128()));
    __m128 hi = _mm_cvtepi32_ps(_mm_unpackhi_epi16(d.v(), _mm_setzero_si128()));
    lo = _mm_div_ps(lo, _mm_cvtepi32_ps(_mm_unpacklo_epi16(x.d.v(), _mm_setzero_si128())));
    hi = _mm_div_ps(hi, _mm_cvtepi32_ps(_mm_unpackhi_epi16(x.d.v(), _mm_setzero_si128())));
    d.v() = _mm_packs_epi32(_mm_cvtps_epi32(lo), _mm_cvtps_epi32(hi));
    return *this;
}

template<> inline Vector<unsigned short> Vector<unsigned short>::operator/(const Vector<unsigned short> &x) const
{
    __m128 lo = _mm_cvtepi32_ps(_mm_unpacklo_epi16(d.v(), _mm_setzero_si128()));
    __m128 hi = _mm_cvtepi32_ps(_mm_unpackhi_epi16(d.v(), _mm_setzero_si128()));
    lo = _mm_div_ps(lo, _mm_cvtepi32_ps(_mm_unpacklo_epi16(x.d.v(), _mm_setzero_si128())));
    hi = _mm_div_ps(hi, _mm_cvtepi32_ps(_mm_unpackhi_epi16(x.d.v(), _mm_setzero_si128())));
    return _mm_packs_epi32(_mm_cvtps_epi32(lo), _mm_cvtps_epi32(hi));
}

template<> inline Vector<float> &Vector<float>::operator/=(const Vector<float> &x)
{
    d.v() = _mm_div_ps(d.v(), x.d.v());
    return *this;
}

template<> inline Vector<float> Vector<float>::operator/(const Vector<float> &x) const
{
    return _mm_div_ps(d.v(), x.d.v());
}

template<> inline Vector<float8> &Vector<float8>::operator/=(const Vector<float8> &x)
{
    d.v()[0] = _mm_div_ps(d.v()[0], x.d.v()[0]);
    d.v()[1] = _mm_div_ps(d.v()[1], x.d.v()[1]);
    return *this;
}

template<> inline Vector<float8> Vector<float8>::operator/(const Vector<float8> &x) const
{
    Vector<float8> r;
    r.d.v()[0] = _mm_div_ps(d.v()[0], x.d.v()[0]);
    r.d.v()[1] = _mm_div_ps(d.v()[1], x.d.v()[1]);
    return r;
}

template<> inline Vector<double> &Vector<double>::operator/=(const Vector<double> &x)
{
    d.v() = _mm_div_pd(d.v(), x.d.v());
    return *this;
}

template<> inline Vector<double> Vector<double>::operator/(const Vector<double> &x) const
{
    return _mm_div_pd(d.v(), x.d.v());
}

#define OP_IMPL(T, symbol, fun) \
template<> inline Vector<T> &VectorBase<T>::operator symbol##=(const VectorBase<T> &x) \
{ \
    d.v() = VectorHelper<T>::fun(d.v(), x.d.v()); \
    return *static_cast<Vector<T> *>(this); \
} \
template<> inline Vector<T>  VectorBase<T>::operator symbol(const VectorBase<T> &x) const \
{ \
    return Vector<T>(VectorHelper<T>::fun(d.v(), x.d.v())); \
}
OP_IMPL(int, &, and_)
OP_IMPL(int, |, or_)
OP_IMPL(int, ^, xor_)
OP_IMPL(int, <<, sll)
OP_IMPL(int, >>, srl)
OP_IMPL(unsigned int, &, and_)
OP_IMPL(unsigned int, |, or_)
OP_IMPL(unsigned int, ^, xor_)
OP_IMPL(unsigned int, <<, sll)
OP_IMPL(unsigned int, >>, srl)
OP_IMPL(short, &, and_)
OP_IMPL(short, |, or_)
OP_IMPL(short, ^, xor_)
OP_IMPL(short, <<, sll)
OP_IMPL(short, >>, srl)
OP_IMPL(unsigned short, &, and_)
OP_IMPL(unsigned short, |, or_)
OP_IMPL(unsigned short, ^, xor_)
OP_IMPL(unsigned short, <<, sll)
OP_IMPL(unsigned short, >>, srl)
#undef OP_IMPL

#define OP_IMPL(T, SUFFIX) \
template<> inline Vector<T> &VectorBase<T>::operator<<=(int x) \
{ \
    d.v() = CAT(_mm_slli_epi, SUFFIX)(d.v(), x); \
    return *static_cast<Vector<T> *>(this); \
} \
template<> inline Vector<T> &VectorBase<T>::operator>>=(int x) \
{ \
    d.v() = CAT(_mm_srli_epi, SUFFIX)(d.v(), x); \
    return *static_cast<Vector<T> *>(this); \
} \
template<> inline Vector<T> VectorBase<T>::operator<<(int x) const \
{ \
    return CAT(_mm_slli_epi, SUFFIX)(d.v(), x); \
} \
template<> inline Vector<T> VectorBase<T>::operator>>(int x) const \
{ \
    return CAT(_mm_srli_epi, SUFFIX)(d.v(), x); \
}
OP_IMPL(int, 32)
OP_IMPL(unsigned int, 32)
OP_IMPL(short, 16)
OP_IMPL(unsigned short, 16)
#undef OP_IMPL

} // namespace SSE
} // namespace Vc

#include "undomacros.h"
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2012 by Glenn Hickey (hickey@soe.ucsc.edu)
 *
 * Released under the MIT license, see LICENSE.txt
 */

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <algorithm>
#include "halPhyloP.h"
#undef min
using namespace std;
using namespace hal;

/** This is basically copied from halAlignability.cpp but returns
 * the phyloP score rather than the count of alignments.
 *
 * Coordinates are always genome-relative by default (as opposed to
 * sequence-relative).  The one exception is all methods within the
 * Sequence interface.
 *
 * By default, all bases in the reference genome are scanned.  And all
 * other genomes are considered.  The --refSequence, --start, and
 * --length options can limit the query to a subrange.  Note that unless
 * --refSequence is specified, --start is genome-relative (based on
 * all sequences being concatenated together).
 *
 * Genomes to include are determined by genomes in the neutral model
 * (.mod) file- this should be in the format outputted by phyloFit.
 *
 * There are a few options for dealing with duplications. The default
 * is dupMask=soft, dupType=ambiguous. This replaces any species base
 * with an N if duplications cause uncertainty in the base for a
 * particular alignment column. If dupType=all, then all duplications
 * are masked regardless of whether they cause uncertainty. If
 * dupMask=hard, then the entire column is masked (p-value returned is 1.0)
 */

/** Print the phyloP wiggle for a subrange of a given sequence to
 * the output stream. */
static void printSequence(ostream& outStream, halPhyloP *phyloP,
                          const Sequence* sequence,
                          hal_size_t start, hal_size_t length, hal_size_t step);

/** If given genome-relative coordinates, map them to a series of
 * sequence subranges */
static void printGenome(ostream& outStream, halPhyloP *phyloP,
                        const Genome* genome, const Sequence* sequence,
                        hal_size_t start, hal_size_t length, hal_size_t step);

static const hal_size_t StringBufferSize = 1024;

static CLParserPtr initParser()
{
  /** It is convenient to use the HAL command line parser for the command
   * line because it automatically adds some comman options.  Using the
   * parser is by no means required however */
  CLParserPtr optionsParser = hdf5CLParserInstance(false);
  optionsParser->addArgument("halPath", "input hal file");
  optionsParser->addArgument("refGenome", "reference genome to scan");
  optionsParser->addArgument("modPath", "input neutral model file");
  optionsParser->addArgument("outWiggle", "output wig file (or \"stdout\""
                             " to pipe to standard output)");
  optionsParser->addOption("refSequence", "sequence name to export ("
                           "all sequences by default)",
                           "\"\"");
   optionsParser->addOption("start",
                           "coordinate within reference genome (or sequence"
                           " if specified) to start at",
                           0);
  optionsParser->addOption("length",
                           "length of the reference genome (or sequence"
                           " if specified) to convert.  If set to 0,"
                           " the entire thing is converted",
                           0);
  optionsParser->addOption("dupType",
                           "Which duplications to mask according to dupMask "
                           "option. Choices are: "
                           "\"all\": Any duplicated region; or "
                           "\"ambiguous\": Regions within duplications where "
                           "alignments from the same species do not contain"
                           " the same base.",
                           "ambiguous");
  optionsParser->addOption("dupMask",
                           "What to do with duplicated regions. Choices are: "
                           "\"hard\": mask entire alignment column if any "
                           "duplications occur; or "
                           "\"soft\": mask species where duplications occur.",
                           "soft");
  optionsParser->addOption("step", "step size", 1);
  optionsParser->setDescription("Make PhyloP wiggle plot for a genome.");
  return optionsParser;
}

int main(int argc, char** argv)
{
  CLParserPtr optionsParser = initParser();
  string modPath;
  string halPath;
  string wigPath;
  string refGenomeName;
  string refSequenceName;
  string dupType;
  string dupMask;
  hal_size_t start;
  hal_size_t length;
  hal_size_t step;
  try
  {
    optionsParser->parseOptions(argc, argv);
    modPath = optionsParser->getArgument<string>("modPath");
    halPath = optionsParser->getArgument<string>("halPath");
    refGenomeName = optionsParser->getArgument<string>("refGenome");
    wigPath = optionsParser->getArgument<string>("outWiggle");
    refSequenceName = optionsParser->getOption<string>("refSequence");
    start = optionsParser->getOption<hal_size_t>("start");
    length = optionsParser->getOption<hal_size_t>("length");
    step = optionsParser->getOption<hal_size_t>("step");
    dupType = optionsParser->getOption<string>("dupType");
    dupMask = optionsParser->getOption<string>("dupMask");

  }
  catch(exception& e)
  {
    cerr << e.what() << endl;
    optionsParser->printUsage(cerr);
    exit(1);
  }

  try
  {
    /** Everything begins with the alignment object, which is created
     * via a path to a .hal file.  Options don't necessarily need to
     * come from the optionsParser -- see other interfaces in
     * hal/api/inc/halAlignmentInstance.h */
    AlignmentConstPtr alignment = openHalAlignmentReadOnly(halPath,
                                                           optionsParser);

    if (alignment->getNumGenomes() == 0)
    {
      throw hal_exception("input hal alignmenet is empty");
    }

    halPhyloP phyloPObj = halPhyloP(alignment, modPath);
    halPhyloP *phyloP = &phyloPObj;
    phyloP->setDupMask(dupMask);
    phyloP->setDupType(dupType);

    /** Open the reference genome */
    const Genome* refGenome = NULL;
    if (refGenomeName != "\"\"")
    {
      refGenome = alignment->openGenome(refGenomeName);
      if (refGenome == NULL)
      {
        throw hal_exception(string("Reference genome, ") + refGenomeName +
                            ", not found in alignment");
      }
    }
    else
    {
      refGenome = alignment->openGenome(alignment->getRootName());
    }

    /** If a sequence was spefied we look for it in the reference genome */
    const Sequence* refSequence = NULL;
    if (refSequenceName != "\"\"")
    {
      refSequence = refGenome->getSequence(refSequenceName);
      if (refSequence == NULL)
      {
        throw hal_exception(string("Reference sequence, ") + refSequenceName +
                            ", not found in reference genome, " +
                            refGenome->getName());
      }
    }

    ofstream ofile;
    ostream& outStream = wigPath == "stdout" ? cout : ofile;
    if (wigPath != "stdout")
    {
      ofile.open(wigPath.c_str());
      if (!ofile)
      {
        throw hal_exception(string("Error opening output file ") +
                            wigPath);
      }
    }

    printGenome(outStream, phyloP, refGenome, refSequence, start, length,
	        step);

  }
  catch(hal_exception& e)
  {
    cerr << "hal exception caught: " << e.what() << endl;
    return 1;
  }
  catch(exception& e)
  {
    cerr << "Exception caught: " << e.what() << endl;
    return 1;
  }

  return 0;
}

/** Given a Sequence (chromosome) and a (sequence-relative) coordinate
 * range, print the phyloP wiggle with respect to the genomes
 * in the target set */
void printSequence(ostream& outStream, halPhyloP *phyloP,
		   const Sequence* sequence,
                   hal_size_t start, hal_size_t length, hal_size_t step)
{
  hal_size_t seqLen = sequence->getSequenceLength();
  if (seqLen == 0)
  {
    return;
  }
  /** If the length is 0, we do from the start position until the end
   * of the sequence */
  if (length == 0)
  {
    length = seqLen - start;
  }
  hal_size_t last = start + length;
  if (last > seqLen)
  {
    stringstream ss;
    ss << "Specified range [" << start << "," << length << "] is"
       << "out of range for sequence " << sequence->getName()
       << ", which has length " << seqLen;
    throw (hal_exception(ss.str()));
  }

  const Genome* genome = sequence->getGenome();
  string sequenceName = sequence->getName();
  string genomeName = genome->getName();
  /** A hack to take the genome name out of the chromosome name.  Should
   * be largely unnecessary now that our naming conventions are better */
  if (sequenceName.find(genomeName + '.') == 0)
  {
    sequenceName = sequenceName.substr(genomeName.length() + 1);
  }

  /** The ColumnIterator is fundamental structure used in this example to
   * traverse the alignment.  It essientially generates the multiple alignment
   * on the fly according to the given reference (in this case the target
   * sequence).  Since this is the sequence interface, the positions
   * are sequence relative.  Note that we must specify the last position
   * in advance when we get the iterator.  This will limit it following
   * duplications out of the desired range while we are iterating. */
  hal_size_t pos = start;
  ColumnIteratorConstPtr colIt = sequence->getColumnIterator(&phyloP->_targetSet,
                                                             0, pos,
                                                             last - 1,
                                                             true);
  // note wig coordinates are 1-based for some reason so we shift to right
  outStream << "fixedStep chrom=" << sequenceName << " start=" << start + 1
            << " step=" << step << "\n";

  // set float precision to 3 places to be consistent with non-hal phyloP
  outStream.setf(ios::fixed, ios::floatfield);
  outStream.precision(3);

  /** Since the column iterator stores coordinates in Genome coordinates
   * internally, we have to switch back to genome coordinates.  */
  // convert to genome coordinates
  pos += sequence->getStartPosition();
  last += sequence->getStartPosition();
  while (pos <= last)
  {
    /** ColumnIterator::ColumnMap maps a Sequence to a list of bases
     * the bases in the map form the alignment column.  Some sequences
     * in the map can have no bases (for efficiency reasons) */
    const ColumnIterator::ColumnMap* cmap = colIt->getColumnMap();
    double pval = phyloP->pval(cmap);

    outStream << pval << '\n';

    /** lastColumn checks if we are at the last column (inclusive)
     * in range.  So we need to check at end of iteration instead
     * of beginning (which would be more convenient).  Need to
     * merge global fix from other branch */
    if (colIt->lastColumn() == true)
    {
      break;
    }

    pos += step;
    if (step == 1)
    {
      /** Move the iterator one position to the right */
      colIt->toRight();

      /** This is some tuning code that will probably be hidden from
       * the interface at some point.  It is a good idea to use for now
       * though */
      // erase empty entries from the column.  helps when there are
      // millions of sequences (ie from fastas with lots of scaffolds)
      if (pos % 1000 == 0)
      {
        colIt->defragment();
      }
    }
    else
    {
      /** Reset the iterator to a non-contiguous position */
      colIt->toSite(pos, last);
    }
  }
}

/** Map a range of genome-level coordinates to potentially multiple sequence
 * ranges.  For example, if a genome contains two chromosomes ChrA and ChrB,
 * both of which are of length 500, then the genome-coordinates would be
 * [0,499] for ChrA and [500,999] for ChrB. All aspects of the HAL API
 * use these global coordinates (chromosomes concatenated together) except
 * for the hal::Sequence interface.  We can convert between the two by
 * adding or subtracting the sequence start position (in the example it woudl
 * be 0 for ChrA and 500 for ChrB) */
void printGenome(ostream& outStream, halPhyloP *phyloP,
                 const Genome* genome, const Sequence* sequence,
                 hal_size_t start, hal_size_t length, hal_size_t step)
{
  if (sequence != NULL)
  {
    printSequence(outStream, phyloP, sequence, start, length, step);
  }
  else
  {
    if (start + length > genome->getSequenceLength())
    {
      stringstream ss;
      ss << "Specified range [" << start << "," << length << "] is"
         << "out of range for genome " << genome->getName()
         << ", which has length " << genome->getSequenceLength();
      throw (hal_exception(ss.str()));
    }
    if (length == 0)
    {
      length = genome->getSequenceLength() - start;
    }

    SequenceIteratorConstPtr seqIt = genome->getSequenceIterator();
    SequenceIteratorConstPtr seqEndIt = genome->getSequenceEndIterator();
    hal_size_t runningLength = 0;
    for (; seqIt != seqEndIt; seqIt->toNext())
    {
      const Sequence* sequence = seqIt->getSequence();
      hal_size_t seqLen = sequence->getSequenceLength();
      hal_size_t seqStart = (hal_size_t)sequence->getStartPosition();

      if (start + length >= seqStart &&
          start < seqStart + seqLen &&
          runningLength < length)
      {
        hal_size_t readStart = seqStart >= start ? 0 : start - seqStart;
        hal_size_t readLen = min(seqLen - readStart, length);

        printSequence(outStream, phyloP, sequence, readStart, readLen, step);
        runningLength += readLen;
      }
    }
  }
}

<commit_msg>remove hack to take dots out of sequence names<commit_after>/*
 * Copyright (C) 2012 by Glenn Hickey (hickey@soe.ucsc.edu)
 *
 * Released under the MIT license, see LICENSE.txt
 */

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <algorithm>
#include "halPhyloP.h"
#undef min
using namespace std;
using namespace hal;

/** This is basically copied from halAlignability.cpp but returns
 * the phyloP score rather than the count of alignments.
 *
 * Coordinates are always genome-relative by default (as opposed to
 * sequence-relative).  The one exception is all methods within the
 * Sequence interface.
 *
 * By default, all bases in the reference genome are scanned.  And all
 * other genomes are considered.  The --refSequence, --start, and
 * --length options can limit the query to a subrange.  Note that unless
 * --refSequence is specified, --start is genome-relative (based on
 * all sequences being concatenated together).
 *
 * Genomes to include are determined by genomes in the neutral model
 * (.mod) file- this should be in the format outputted by phyloFit.
 *
 * There are a few options for dealing with duplications. The default
 * is dupMask=soft, dupType=ambiguous. This replaces any species base
 * with an N if duplications cause uncertainty in the base for a
 * particular alignment column. If dupType=all, then all duplications
 * are masked regardless of whether they cause uncertainty. If
 * dupMask=hard, then the entire column is masked (p-value returned is 1.0)
 */

/** Print the phyloP wiggle for a subrange of a given sequence to
 * the output stream. */
static void printSequence(ostream& outStream, halPhyloP *phyloP,
                          const Sequence* sequence,
                          hal_size_t start, hal_size_t length, hal_size_t step);

/** If given genome-relative coordinates, map them to a series of
 * sequence subranges */
static void printGenome(ostream& outStream, halPhyloP *phyloP,
                        const Genome* genome, const Sequence* sequence,
                        hal_size_t start, hal_size_t length, hal_size_t step);

static const hal_size_t StringBufferSize = 1024;

static CLParserPtr initParser()
{
  /** It is convenient to use the HAL command line parser for the command
   * line because it automatically adds some comman options.  Using the
   * parser is by no means required however */
  CLParserPtr optionsParser = hdf5CLParserInstance(false);
  optionsParser->addArgument("halPath", "input hal file");
  optionsParser->addArgument("refGenome", "reference genome to scan");
  optionsParser->addArgument("modPath", "input neutral model file");
  optionsParser->addArgument("outWiggle", "output wig file (or \"stdout\""
                             " to pipe to standard output)");
  optionsParser->addOption("refSequence", "sequence name to export ("
                           "all sequences by default)",
                           "\"\"");
   optionsParser->addOption("start",
                           "coordinate within reference genome (or sequence"
                           " if specified) to start at",
                           0);
  optionsParser->addOption("length",
                           "length of the reference genome (or sequence"
                           " if specified) to convert.  If set to 0,"
                           " the entire thing is converted",
                           0);
  optionsParser->addOption("dupType",
                           "Which duplications to mask according to dupMask "
                           "option. Choices are: "
                           "\"all\": Any duplicated region; or "
                           "\"ambiguous\": Regions within duplications where "
                           "alignments from the same species do not contain"
                           " the same base.",
                           "ambiguous");
  optionsParser->addOption("dupMask",
                           "What to do with duplicated regions. Choices are: "
                           "\"hard\": mask entire alignment column if any "
                           "duplications occur; or "
                           "\"soft\": mask species where duplications occur.",
                           "soft");
  optionsParser->addOption("step", "step size", 1);
  optionsParser->setDescription("Make PhyloP wiggle plot for a genome.");
  return optionsParser;
}

int main(int argc, char** argv)
{
  CLParserPtr optionsParser = initParser();
  string modPath;
  string halPath;
  string wigPath;
  string refGenomeName;
  string refSequenceName;
  string dupType;
  string dupMask;
  hal_size_t start;
  hal_size_t length;
  hal_size_t step;
  try
  {
    optionsParser->parseOptions(argc, argv);
    modPath = optionsParser->getArgument<string>("modPath");
    halPath = optionsParser->getArgument<string>("halPath");
    refGenomeName = optionsParser->getArgument<string>("refGenome");
    wigPath = optionsParser->getArgument<string>("outWiggle");
    refSequenceName = optionsParser->getOption<string>("refSequence");
    start = optionsParser->getOption<hal_size_t>("start");
    length = optionsParser->getOption<hal_size_t>("length");
    step = optionsParser->getOption<hal_size_t>("step");
    dupType = optionsParser->getOption<string>("dupType");
    dupMask = optionsParser->getOption<string>("dupMask");

  }
  catch(exception& e)
  {
    cerr << e.what() << endl;
    optionsParser->printUsage(cerr);
    exit(1);
  }

  try
  {
    /** Everything begins with the alignment object, which is created
     * via a path to a .hal file.  Options don't necessarily need to
     * come from the optionsParser -- see other interfaces in
     * hal/api/inc/halAlignmentInstance.h */
    AlignmentConstPtr alignment = openHalAlignmentReadOnly(halPath,
                                                           optionsParser);

    if (alignment->getNumGenomes() == 0)
    {
      throw hal_exception("input hal alignmenet is empty");
    }

    halPhyloP phyloPObj = halPhyloP(alignment, modPath);
    halPhyloP *phyloP = &phyloPObj;
    phyloP->setDupMask(dupMask);
    phyloP->setDupType(dupType);

    /** Open the reference genome */
    const Genome* refGenome = NULL;
    if (refGenomeName != "\"\"")
    {
      refGenome = alignment->openGenome(refGenomeName);
      if (refGenome == NULL)
      {
        throw hal_exception(string("Reference genome, ") + refGenomeName +
                            ", not found in alignment");
      }
    }
    else
    {
      refGenome = alignment->openGenome(alignment->getRootName());
    }

    /** If a sequence was spefied we look for it in the reference genome */
    const Sequence* refSequence = NULL;
    if (refSequenceName != "\"\"")
    {
      refSequence = refGenome->getSequence(refSequenceName);
      if (refSequence == NULL)
      {
        throw hal_exception(string("Reference sequence, ") + refSequenceName +
                            ", not found in reference genome, " +
                            refGenome->getName());
      }
    }

    ofstream ofile;
    ostream& outStream = wigPath == "stdout" ? cout : ofile;
    if (wigPath != "stdout")
    {
      ofile.open(wigPath.c_str());
      if (!ofile)
      {
        throw hal_exception(string("Error opening output file ") +
                            wigPath);
      }
    }

    printGenome(outStream, phyloP, refGenome, refSequence, start, length,
	        step);

  }
  catch(hal_exception& e)
  {
    cerr << "hal exception caught: " << e.what() << endl;
    return 1;
  }
  catch(exception& e)
  {
    cerr << "Exception caught: " << e.what() << endl;
    return 1;
  }

  return 0;
}

/** Given a Sequence (chromosome) and a (sequence-relative) coordinate
 * range, print the phyloP wiggle with respect to the genomes
 * in the target set */
void printSequence(ostream& outStream, halPhyloP *phyloP,
		   const Sequence* sequence,
                   hal_size_t start, hal_size_t length, hal_size_t step)
{
  hal_size_t seqLen = sequence->getSequenceLength();
  if (seqLen == 0)
  {
    return;
  }
  /** If the length is 0, we do from the start position until the end
   * of the sequence */
  if (length == 0)
  {
    length = seqLen - start;
  }
  hal_size_t last = start + length;
  if (last > seqLen)
  {
    stringstream ss;
    ss << "Specified range [" << start << "," << length << "] is"
       << "out of range for sequence " << sequence->getName()
       << ", which has length " << seqLen;
    throw (hal_exception(ss.str()));
  }

  const Genome* genome = sequence->getGenome();
  string sequenceName = sequence->getName();
  string genomeName = genome->getName();

  /** The ColumnIterator is fundamental structure used in this example to
   * traverse the alignment.  It essientially generates the multiple alignment
   * on the fly according to the given reference (in this case the target
   * sequence).  Since this is the sequence interface, the positions
   * are sequence relative.  Note that we must specify the last position
   * in advance when we get the iterator.  This will limit it following
   * duplications out of the desired range while we are iterating. */
  hal_size_t pos = start;
  ColumnIteratorConstPtr colIt = sequence->getColumnIterator(&phyloP->_targetSet,
                                                             0, pos,
                                                             last - 1,
                                                             true);
  // note wig coordinates are 1-based for some reason so we shift to right
  outStream << "fixedStep chrom=" << sequenceName << " start=" << start + 1
            << " step=" << step << "\n";

  // set float precision to 3 places to be consistent with non-hal phyloP
  outStream.setf(ios::fixed, ios::floatfield);
  outStream.precision(3);

  /** Since the column iterator stores coordinates in Genome coordinates
   * internally, we have to switch back to genome coordinates.  */
  // convert to genome coordinates
  pos += sequence->getStartPosition();
  last += sequence->getStartPosition();
  while (pos <= last)
  {
    /** ColumnIterator::ColumnMap maps a Sequence to a list of bases
     * the bases in the map form the alignment column.  Some sequences
     * in the map can have no bases (for efficiency reasons) */
    const ColumnIterator::ColumnMap* cmap = colIt->getColumnMap();
    double pval = phyloP->pval(cmap);

    outStream << pval << '\n';

    /** lastColumn checks if we are at the last column (inclusive)
     * in range.  So we need to check at end of iteration instead
     * of beginning (which would be more convenient).  Need to
     * merge global fix from other branch */
    if (colIt->lastColumn() == true)
    {
      break;
    }

    pos += step;
    if (step == 1)
    {
      /** Move the iterator one position to the right */
      colIt->toRight();

      /** This is some tuning code that will probably be hidden from
       * the interface at some point.  It is a good idea to use for now
       * though */
      // erase empty entries from the column.  helps when there are
      // millions of sequences (ie from fastas with lots of scaffolds)
      if (pos % 1000 == 0)
      {
        colIt->defragment();
      }
    }
    else
    {
      /** Reset the iterator to a non-contiguous position */
      colIt->toSite(pos, last);
    }
  }
}

/** Map a range of genome-level coordinates to potentially multiple sequence
 * ranges.  For example, if a genome contains two chromosomes ChrA and ChrB,
 * both of which are of length 500, then the genome-coordinates would be
 * [0,499] for ChrA and [500,999] for ChrB. All aspects of the HAL API
 * use these global coordinates (chromosomes concatenated together) except
 * for the hal::Sequence interface.  We can convert between the two by
 * adding or subtracting the sequence start position (in the example it woudl
 * be 0 for ChrA and 500 for ChrB) */
void printGenome(ostream& outStream, halPhyloP *phyloP,
                 const Genome* genome, const Sequence* sequence,
                 hal_size_t start, hal_size_t length, hal_size_t step)
{
  if (sequence != NULL)
  {
    printSequence(outStream, phyloP, sequence, start, length, step);
  }
  else
  {
    if (start + length > genome->getSequenceLength())
    {
      stringstream ss;
      ss << "Specified range [" << start << "," << length << "] is"
         << "out of range for genome " << genome->getName()
         << ", which has length " << genome->getSequenceLength();
      throw (hal_exception(ss.str()));
    }
    if (length == 0)
    {
      length = genome->getSequenceLength() - start;
    }

    SequenceIteratorConstPtr seqIt = genome->getSequenceIterator();
    SequenceIteratorConstPtr seqEndIt = genome->getSequenceEndIterator();
    hal_size_t runningLength = 0;
    for (; seqIt != seqEndIt; seqIt->toNext())
    {
      const Sequence* sequence = seqIt->getSequence();
      hal_size_t seqLen = sequence->getSequenceLength();
      hal_size_t seqStart = (hal_size_t)sequence->getStartPosition();

      if (start + length >= seqStart &&
          start < seqStart + seqLen &&
          runningLength < length)
      {
        hal_size_t readStart = seqStart >= start ? 0 : start - seqStart;
        hal_size_t readLen = min(seqLen - readStart, length);

        printSequence(outStream, phyloP, sequence, readStart, readLen, step);
        runningLength += readLen;
      }
    }
  }
}

<|endoftext|>


<commit_before>/*
 * Systronix_PCA9548A.cpp
 *
 *  Created on: 2017 Feb 06
 *	  Author: BAB
 */

/**---------------------------< REVISIONS >----------------------------------

2017 Jul 12			rewrite to make Wire1 aware; to conform to the 'standard' established in PCA9557

2017 May 22 bboyes	change to UINT64_MAX

2017 May 21 bboyes	Changed total_error_count and successful_count to 64 bit
long long and check against ULLONG_MAX before incrementing

2017 May 05 bboyes	Changed default i2c_t3 timeout to 5000 usec, which is still
likely way too much. There's nothing that slow in the 9557 access.

2017 Mar 15	bboyes	Changed tally_transaction to properly record current Wire.status()
return values. Disabled simpleTest because it is not so simple and could return
with the config register changed in the middle of another loop which requires it
to be not changed.

-----------------------------------------------------------------------------*/

#include <Systronix_PCA9548A.h>

/**---------------------------< CONSTRUCTOR >----------------------------------

	@brief  Instantiates a new PCA9548A class to use the given base address
	base is clipped to min or max if necessary

-----------------------------------------------------------------------------*/
/*
Systronix_PCA9548A::Systronix_PCA9548A(uint8_t base)
	{
	if (base < PCA9548A_SLAVE_ADDR_0)
		{
		_base = PCA9548A_SLAVE_ADDR_0;
		_base_clipped = true;
		}
	else if (base > PCA9548A_SLAVE_ADDR_7)
		{
		_base = PCA9548A_SLAVE_ADDR_7;
		_base_clipped = true;
		}
	else
		{
		_base = base;
		_base_clipped = false;
		}
	error.total_error_count = 0;				// clear the error counter
	}
*/

//---------------------------< D E F A U L T   C O N S R U C T O R >------------------------------------------
//
// default constructor assumes lowest base address
//

Systronix_PCA9548A::Systronix_PCA9548A()
	{
	_base = PCA9548A_SLAVE_ADDR_0;
	_base_clipped = false;						// since it's constant it must be OK
	error.total_error_count = 0;				// clear the error counter
	}

//---------------------------< D E S T R U C T O R >----------------------------------------------------------
//
// destructor
//

Systronix_PCA9548A::~Systronix_PCA9548A()
{
	// Anything to do here? Leave I2C as master? Set flag?
}

//---------------------------< B A S E _ C L I P P E D >------------------------------------------------------
//
// base address passed in constructor or setup() was out of range so clipped to value min <= base <= max
//

boolean Systronix_PCA9548A::base_clipped()
{
	return _base_clipped;
}

//---------------------------< B A S E _ G E T >--------------------------------------------------------------
//
// return the base address; will be the same as the address in constructor or setup() unless clipped in which
// case base address shall be PCA9548A_SLAVE_ADDR_0 or PCA9548A_SLAVE_ADDR_7
//

uint8_t Systronix_PCA9548A::base_get()
{
	return _base;
}

//---------------------------< S E T U P >--------------------------------------------------------------------
//
// TODO: merge with begin()? This function doesn't actually do anything, it just sets some private values. It's
// redundant and some params must be effectively specified again in begin (Wire net and pins are not independent).	what parameters are specified again? [wsk]
//

uint8_t Systronix_PCA9548A::setup (uint8_t base, i2c_t3 wire, char* name)
	{
	if ((PCA9548A_BASE_MIN > base) || (PCA9548A_BASE_MAX < base))
		{
		tally_transaction (SILLY_PROGRAMMER);
		return FAIL;
		}

	_base = base;
	_wire = wire;
	_wire_name = wire_name = name;		// protected and public
	return SUCCESS;
	}

//---------------------------< B E G I N >--------------------------------------------------------------------
//
//
//

void Systronix_PCA9548A::begin (i2c_pins pins, i2c_rate rate)
	{
	_wire.begin(I2C_MASTER, 0x00, pins, I2C_PULLUP_EXT, rate);	// join I2C as master
//	Serial.printf("9548A lib begin %s\r\n", _wire_name);
	_wire.setDefaultTimeout(200000); // 200ms
	}

//---------------------------< D E F A U L T   B E G I N >----------------------------------------------------
/**
	@ brief Void version of begin for backwards compatibility, assumes Wire net

*/

void Systronix_PCA9548A::begin (void)
	{
	_wire.begin();	// join I2C as master
	_wire.setDefaultTimeout(200000); // 200ms
	}

/**---------------------------< I N I T >---------------------------------------------------------------------

Address the MUX and write to the control register.
If successful, _exists = true;

TODO: if endTransmission times out its return should so indicate. See in i2c_t3 if it does and if not
make that change? This might break code which assumes value can only be max of 4. In that case add
a struct with more error information, have the library maintain it?

TODO How is this different from control write ???
**/

uint8_t Systronix_PCA9548A::init (uint8_t control)
	{
	uint8_t ret_val;

	error.exists = true;					// so we can use control_write(); we'll find out later if device does not exist

//	Serial.printf("9548A lib init %s at base 0x%.2X\r\n", _wire_name, _base);
	ret_val = control_write (control);		// if successful this means we got two ACKs from slave device
	if (SUCCESS != ret_val)
		{
		Serial.printf("9548A lib init %s at base 0x%.2X failed with %s (0x%.2X)\r\n", _wire_name, _base, status_text[error.error_val], error.error_val);
		error.exists = false;				// only place error.exists is set false
		return ABSENT;
		}

	return SUCCESS;
	}

//---------------------------< R E S E T _ B U S >------------------------------------------------------------
/**
	Invoke resetBus of whichever Wire net this class instance is using
	@return nothing
*/
void Systronix_PCA9548A::reset_bus (void)
{
	_wire.resetBus();
}

//---------------------------< R E S E T _ B U S _ C O U N T _ R E A D >--------------------------------------
/**
	Return the resetBusCount of whichever Wire net this class instance is using
	@return number of Wire net resets, clips at UINT32_MAX
*/
uint32_t Systronix_PCA9548A::reset_bus_count_read (void)
{
	return _wire.resetBusCountRead();
}

//---------------------------< T A L L Y _ T R A N S A C T I O N >--------------------------------------------
/**
Here we tally errors.  This does not answer the what-to-do-in-the-event-of-these-errors question; it just
counts them.

TODO: we should decide if the correct thing to do when slave does not ack, or arbitration is lost, or
timeout occurs, or auto reset fails (states 2, 5 and 4, 7 ??? state numbers may have changed since this
comment originally added) is to declare these addresses as non-existent.

We need to decide what to do when those conditions occur if we do not declare the device non-existent.
When a device is declared non-existent, what do we do then? (this last is more a question for the
application than this library).  The questions in this TODO apply equally to other i2c libraries that tally
these errors.

Don't set error.exists = false here! These errors are likely recoverable. bab & wsk 170612

This is the only place we set error.error_val()

TODO use i2c_t3 error or status enumeration here in the switch/case
*/

void Systronix_PCA9548A::tally_transaction (uint8_t value)
	{
	if (value && (error.total_error_count < UINT64_MAX))
		error.total_error_count++; 			// every time here incr total error count

	error.error_val = value;

	switch (value)
		{
		case SUCCESS:
			if (error.successful_count < UINT64_MAX)
				error.successful_count++;
			break;
		case 1:								// i2c_t3 and Wire: data too long from endTransmission() (rx/tx buffers are 259 bytes - slave addr + 2 cmd bytes + 256 data)
			error.data_len_error_count++;
			break;
#if defined I2C_T3_H
		case I2C_TIMEOUT:
			error.timeout_count++;			// 4 from i2c_t3; timeout from call to status() (read)
#else
		case 4:
			error.other_error_count++;		// i2c_t3 and Wire: from endTransmission() "other error"
#endif
			break;
		case 2:								// i2c_t3 and Wire: from endTransmission()
		case I2C_ADDR_NAK:					// 5 from i2c_t3
			error.rcv_addr_nack_count++;
			break;
		case 3:								// i2c_t3 and Wire: from endTransmission()
		case I2C_DATA_NAK:					// 6 from i2c_t3
			error.rcv_data_nack_count++;
			break;
		case I2C_ARB_LOST:					// 7 from i2c_t3; arbitration lost from call to status() (read)
			error.arbitration_lost_count++;
			break;
		case I2C_BUF_OVF:
			error.buffer_overflow_count++;
			break;
		case I2C_SLAVE_TX:
		case I2C_SLAVE_RX:
			error.other_error_count++;		// 9 & 10 from i2c_t3; these are not errors, I think
			break;
		case WR_INCOMPLETE:					// 11; Wire.write failed to write all of the data to tx_buffer
			error.incomplete_write_count++;
			break;
		case SILLY_PROGRAMMER:				// 12
			error.silly_programmer_error++;
			break;
		default:
			error.unknown_error_count++;
			break;
		}
	}

//---------------------------< C O N T R O L _ W R I T E >----------------------------------------------------
/**
Write to the 8-bit control register
returns 0 if no error, positive values for NAK errors

Prevent setting more than one bit?

*/

uint8_t Systronix_PCA9548A::control_write (uint8_t control)
	{
	uint8_t ret_val;

	if (!error.exists)							// exit immediately if device does not exist
		return ABSENT;

	_wire.beginTransmission (_base);			// base address

	ret_val = _wire.write (control);			// returns # of bytes written to i2c_t3 buffer
	if (1 != ret_val)
		{
		tally_transaction (WR_INCOMPLETE);		// set the error value
		return FAIL;
		}

	ret_val = _wire.endTransmission();			// returns 0 if successful
	if (SUCCESS != ret_val)
		{
		tally_transaction (ret_val);			// increment the appropriate counter
		return FAIL;							// calling function decides what to do with the error
		}

	_control_reg = control;						// shadow copy to remember this setting
	tally_transaction (SUCCESS);
	return SUCCESS;
	}

//---------------------------< C O N T R O L _ R E A D >------------------------------------------------------
/**

  Read the 8-bit control register

  return 0 if no error, FAIL if error (detail by using error.error_val, ABSENT if slave had prior NAK
*/

uint8_t Systronix_PCA9548A::control_read (uint8_t *data_ptr)
	{
	uint8_t ret_val;

	if (!error.exists)						// exit immediately if device does not exist
		return ABSENT;

	if (1 != _wire.requestFrom (_base, 1, I2C_STOP))
		{
		ret_val = _wire.status();						// to get error value
		tally_transaction (ret_val);					// increment the appropriate counter
		return FAIL;
		}

	*data_ptr = _wire.readByte();

	tally_transaction (SUCCESS);
	return SUCCESS;
	}

/**---------------------------< testSimple >-----------------------------------
	@brief  Enable multiple MUX outputs and see if we can still access control reg

	Read the control reg. Then write test patterns to it, reading to verify.
	Patterns are 0xA5 and its complement 0x5A
	Then restore to the original value.

	Error counters and exists will be updated by the subroutines which this
	function calls.

	return SUCCESS if all was OK, !SUCCESS if any problem
	error struct has details of error(s) if any

	TODO finish this.
-----------------------------------------------------------------------------*/

uint8_t Systronix_PCA9548A::enableManyTest (void)
{
	uint8_t control_read_val = 0;
	uint8_t control_original = 0;
	uint8_t stat = 0;
	uint8_t test_write = 0xA5;		// can enable multiple mux outputs at once
	uint8_t bad_count = 0;

	Serial.printf("enableManyTest is not complete! Use not recommended!\r\n");

	stat = control_read(&control_original);
	if (SUCCESS != stat) return !SUCCESS;		// if we can't even read why continue?

	// write test pattern
	stat = control_write(test_write);
	if (SUCCESS != stat) bad_count++;

	stat = control_read(&control_read_val);
	if (SUCCESS != stat) bad_count++;
	if (test_write != control_read_val)
	{
		bad_count++;
	}

	// write test pattern complement
	// dangerous, ~0x01 is 0xFE which enables 7 ports and any pullups on them,
	// could prevent slave driving low against such a large pullup load
	test_write = ~test_write;
	stat = control_write(test_write);
	if (SUCCESS != stat) return !SUCCESS;

	stat = control_read(&control_read_val);
	if (SUCCESS != stat) return !SUCCESS;
	if (test_write != control_read_val) return !SUCCESS;

	stat = control_write(control_original);
	if (SUCCESS != stat) return !SUCCESS;

	return SUCCESS;
}
<commit_msg>read/write test in init() as proof of exisitence;<commit_after>/*
 * Systronix_PCA9548A.cpp
 *
 *  Created on: 2017 Feb 06
 *	  Author: BAB
 */

/**---------------------------< REVISIONS >----------------------------------

2017 Jul 12			rewrite to make Wire1 aware; to conform to the 'standard' established in PCA9557

2017 May 22 bboyes	change to UINT64_MAX

2017 May 21 bboyes	Changed total_error_count and successful_count to 64 bit
long long and check against ULLONG_MAX before incrementing

2017 May 05 bboyes	Changed default i2c_t3 timeout to 5000 usec, which is still
likely way too much. There's nothing that slow in the 9557 access.

2017 Mar 15	bboyes	Changed tally_transaction to properly record current Wire.status()
return values. Disabled simpleTest because it is not so simple and could return
with the config register changed in the middle of another loop which requires it
to be not changed.

-----------------------------------------------------------------------------*/

#include <Systronix_PCA9548A.h>

/**---------------------------< CONSTRUCTOR >----------------------------------

	@brief  Instantiates a new PCA9548A class to use the given base address
	base is clipped to min or max if necessary

-----------------------------------------------------------------------------*/
/*
Systronix_PCA9548A::Systronix_PCA9548A(uint8_t base)
	{
	if (base < PCA9548A_SLAVE_ADDR_0)
		{
		_base = PCA9548A_SLAVE_ADDR_0;
		_base_clipped = true;
		}
	else if (base > PCA9548A_SLAVE_ADDR_7)
		{
		_base = PCA9548A_SLAVE_ADDR_7;
		_base_clipped = true;
		}
	else
		{
		_base = base;
		_base_clipped = false;
		}
	error.total_error_count = 0;				// clear the error counter
	}
*/

//---------------------------< D E F A U L T   C O N S R U C T O R >------------------------------------------
//
// default constructor assumes lowest base address
//

Systronix_PCA9548A::Systronix_PCA9548A()
	{
	_base = PCA9548A_SLAVE_ADDR_0;
	_base_clipped = false;						// since it's constant it must be OK
	error.total_error_count = 0;				// clear the error counter
	}

//---------------------------< D E S T R U C T O R >----------------------------------------------------------
//
// destructor
//

Systronix_PCA9548A::~Systronix_PCA9548A()
{
	// Anything to do here? Leave I2C as master? Set flag?
}

//---------------------------< B A S E _ C L I P P E D >------------------------------------------------------
//
// base address passed in constructor or setup() was out of range so clipped to value min <= base <= max
//

boolean Systronix_PCA9548A::base_clipped()
{
	return _base_clipped;
}

//---------------------------< B A S E _ G E T >--------------------------------------------------------------
//
// return the base address; will be the same as the address in constructor or setup() unless clipped in which
// case base address shall be PCA9548A_SLAVE_ADDR_0 or PCA9548A_SLAVE_ADDR_7
//

uint8_t Systronix_PCA9548A::base_get()
{
	return _base;
}

//---------------------------< S E T U P >--------------------------------------------------------------------
//
// TODO: merge with begin()? This function doesn't actually do anything, it just sets some private values. It's
// redundant and some params must be effectively specified again in begin (Wire net and pins are not independent).	what parameters are specified again? [wsk]
//

uint8_t Systronix_PCA9548A::setup (uint8_t base, i2c_t3 wire, char* name)
	{
	if ((PCA9548A_BASE_MIN > base) || (PCA9548A_BASE_MAX < base))
		{
		tally_transaction (SILLY_PROGRAMMER);
		return FAIL;
		}

	_base = base;
	_wire = wire;
	_wire_name = wire_name = name;		// protected and public
	return SUCCESS;
	}

//---------------------------< B E G I N >--------------------------------------------------------------------
//
//
//

void Systronix_PCA9548A::begin (i2c_pins pins, i2c_rate rate)
	{
	_wire.begin(I2C_MASTER, 0x00, pins, I2C_PULLUP_EXT, rate);	// join I2C as master
//	Serial.printf("9548A lib begin %s\r\n", _wire_name);
	_wire.setDefaultTimeout(200000); // 200ms
	}

//---------------------------< D E F A U L T   B E G I N >----------------------------------------------------
/**
	@ brief Void version of begin for backwards compatibility, assumes Wire net

*/

void Systronix_PCA9548A::begin (void)
	{
	_wire.begin();	// join I2C as master
	_wire.setDefaultTimeout(200000); // 200ms
	}

/**---------------------------< I N I T >---------------------------------------------------------------------

Address the MUX and write to the control register.
If successful, _exists = true;

TODO: if endTransmission times out its return should so indicate. See in i2c_t3 if it does and if not
make that change? This might break code which assumes value can only be max of 4. In that case add
a struct with more error information, have the library maintain it?

TODO How is this different from control write ???
**/

uint8_t Systronix_PCA9548A::init (uint8_t control)
	{
	uint8_t ret_val;

	error.exists = true;					// so we can use control_write(); we'll find out later if device does not exist

//	Serial.printf("9548A lib init %s at base 0x%.2X\r\n", _wire_name, _base);
	ret_val = control_write (0x5A);			// if successful this means we got two ACKs from slave device and should have a recognizable pattern in control reg
	if (SUCCESS != ret_val)
		{
		Serial.printf("9548A lib init %s at base 0x%.2X failed with %s (0x%.2X)\r\n", _wire_name, _base, status_text[error.error_val], error.error_val);
		error.exists = false;				// this function only place error.exists is set false
		return ABSENT;
		}

	control_read (&ret_val);				// is the pattern in the control reg?
	if (0x5A != ret_val)
		{									// nope
		Serial.printf("9548A lib init %s at base 0x%.2X failed control reg test write; wr: 0x%.2X; got: 0x%.2X\r\n", _wire_name, _base, 0x5A, ret_val);
		error.exists = false;				// this function only place error.exists is set false
		return ABSENT;
		}

	control_write (control);				// working so set the correct initial value

	return SUCCESS;
	}

//---------------------------< R E S E T _ B U S >------------------------------------------------------------
/**
	Invoke resetBus of whichever Wire net this class instance is using
	@return nothing
*/
void Systronix_PCA9548A::reset_bus (void)
{
	_wire.resetBus();
}

//---------------------------< R E S E T _ B U S _ C O U N T _ R E A D >--------------------------------------
/**
	Return the resetBusCount of whichever Wire net this class instance is using
	@return number of Wire net resets, clips at UINT32_MAX
*/
uint32_t Systronix_PCA9548A::reset_bus_count_read (void)
{
	return _wire.resetBusCountRead();
}

//---------------------------< T A L L Y _ T R A N S A C T I O N >--------------------------------------------
/**
Here we tally errors.  This does not answer the what-to-do-in-the-event-of-these-errors question; it just
counts them.

TODO: we should decide if the correct thing to do when slave does not ack, or arbitration is lost, or
timeout occurs, or auto reset fails (states 2, 5 and 4, 7 ??? state numbers may have changed since this
comment originally added) is to declare these addresses as non-existent.

We need to decide what to do when those conditions occur if we do not declare the device non-existent.
When a device is declared non-existent, what do we do then? (this last is more a question for the
application than this library).  The questions in this TODO apply equally to other i2c libraries that tally
these errors.

Don't set error.exists = false here! These errors are likely recoverable. bab & wsk 170612

This is the only place we set error.error_val()

TODO use i2c_t3 error or status enumeration here in the switch/case
*/

void Systronix_PCA9548A::tally_transaction (uint8_t value)
	{
	if (value && (error.total_error_count < UINT64_MAX))
		error.total_error_count++; 			// every time here incr total error count

	error.error_val = value;

	switch (value)
		{
		case SUCCESS:
			if (error.successful_count < UINT64_MAX)
				error.successful_count++;
			break;
		case 1:								// i2c_t3 and Wire: data too long from endTransmission() (rx/tx buffers are 259 bytes - slave addr + 2 cmd bytes + 256 data)
			error.data_len_error_count++;
			break;
#if defined I2C_T3_H
		case I2C_TIMEOUT:
			error.timeout_count++;			// 4 from i2c_t3; timeout from call to status() (read)
#else
		case 4:
			error.other_error_count++;		// i2c_t3 and Wire: from endTransmission() "other error"
#endif
			break;
		case 2:								// i2c_t3 and Wire: from endTransmission()
		case I2C_ADDR_NAK:					// 5 from i2c_t3
			error.rcv_addr_nack_count++;
			break;
		case 3:								// i2c_t3 and Wire: from endTransmission()
		case I2C_DATA_NAK:					// 6 from i2c_t3
			error.rcv_data_nack_count++;
			break;
		case I2C_ARB_LOST:					// 7 from i2c_t3; arbitration lost from call to status() (read)
			error.arbitration_lost_count++;
			break;
		case I2C_BUF_OVF:
			error.buffer_overflow_count++;
			break;
		case I2C_SLAVE_TX:
		case I2C_SLAVE_RX:
			error.other_error_count++;		// 9 & 10 from i2c_t3; these are not errors, I think
			break;
		case WR_INCOMPLETE:					// 11; Wire.write failed to write all of the data to tx_buffer
			error.incomplete_write_count++;
			break;
		case SILLY_PROGRAMMER:				// 12
			error.silly_programmer_error++;
			break;
		default:
			error.unknown_error_count++;
			break;
		}
	}

//---------------------------< C O N T R O L _ W R I T E >----------------------------------------------------
/**
Write to the 8-bit control register
returns 0 if no error, positive values for NAK errors

Prevent setting more than one bit?

*/

uint8_t Systronix_PCA9548A::control_write (uint8_t control)
	{
	uint8_t ret_val;

	if (!error.exists)							// exit immediately if device does not exist
		return ABSENT;

	_wire.beginTransmission (_base);			// base address

	ret_val = _wire.write (control);			// returns # of bytes written to i2c_t3 buffer
	if (1 != ret_val)
		{
		tally_transaction (WR_INCOMPLETE);		// set the error value
		return FAIL;
		}

	ret_val = _wire.endTransmission();			// returns 0 if successful
	if (SUCCESS != ret_val)
		{
		tally_transaction (ret_val);			// increment the appropriate counter
		return FAIL;							// calling function decides what to do with the error
		}

	_control_reg = control;						// shadow copy to remember this setting
	tally_transaction (SUCCESS);
	return SUCCESS;
	}

//---------------------------< C O N T R O L _ R E A D >------------------------------------------------------
/**

  Read the 8-bit control register

  return 0 if no error, FAIL if error (detail by using error.error_val, ABSENT if slave had prior NAK
*/

uint8_t Systronix_PCA9548A::control_read (uint8_t *data_ptr)
	{
	uint8_t ret_val;

	if (!error.exists)						// exit immediately if device does not exist
		return ABSENT;

	if (1 != _wire.requestFrom (_base, 1, I2C_STOP))
		{
		ret_val = _wire.status();						// to get error value
		tally_transaction (ret_val);					// increment the appropriate counter
		return FAIL;
		}

	*data_ptr = _wire.readByte();

	tally_transaction (SUCCESS);
	return SUCCESS;
	}

/**---------------------------< testSimple >-----------------------------------
	@brief  Enable multiple MUX outputs and see if we can still access control reg

	Read the control reg. Then write test patterns to it, reading to verify.
	Patterns are 0xA5 and its complement 0x5A
	Then restore to the original value.

	Error counters and exists will be updated by the subroutines which this
	function calls.

	return SUCCESS if all was OK, !SUCCESS if any problem
	error struct has details of error(s) if any

	TODO finish this.
-----------------------------------------------------------------------------*/

uint8_t Systronix_PCA9548A::enableManyTest (void)
{
	uint8_t control_read_val = 0;
	uint8_t control_original = 0;
	uint8_t stat = 0;
	uint8_t test_write = 0xA5;		// can enable multiple mux outputs at once
	uint8_t bad_count = 0;

	Serial.printf("enableManyTest is not complete! Use not recommended!\r\n");

	stat = control_read(&control_original);
	if (SUCCESS != stat) return !SUCCESS;		// if we can't even read why continue?

	// write test pattern
	stat = control_write(test_write);
	if (SUCCESS != stat) bad_count++;

	stat = control_read(&control_read_val);
	if (SUCCESS != stat) bad_count++;
	if (test_write != control_read_val)
	{
		bad_count++;
	}

	// write test pattern complement
	// dangerous, ~0x01 is 0xFE which enables 7 ports and any pullups on them,
	// could prevent slave driving low against such a large pullup load
	test_write = ~test_write;
	stat = control_write(test_write);
	if (SUCCESS != stat) return !SUCCESS;

	stat = control_read(&control_read_val);
	if (SUCCESS != stat) return !SUCCESS;
	if (test_write != control_read_val) return !SUCCESS;

	stat = control_write(control_original);
	if (SUCCESS != stat) return !SUCCESS;

	return SUCCESS;
}
<|endoftext|>


<commit_before>
/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */
/***********************************************************************
 *      this class doing calibration during reconstruction
 *      2 steps:
 *      - equalizing channels
 *      - applying walk corrections
 *
 * Alla.Maevskaya@cern.ch
 *
 **********************************************************************/

//#include <Riostream.h>

#include "AliLog.h"
#include "AliT0Parameters.h"
#include "AliT0Calibrator.h"
#include "AliT0Reconstructor.h"
#include "AliT0RecoParam.h"
#include <TGraph.h>
#include <TH1F.h>
#include <TMath.h>
#include <Riostream.h>

ClassImp(AliT0Calibrator)

//____________________________________________________________________
  AliT0Calibrator::AliT0Calibrator():TNamed(),
				     fChannelWidth(0),
				     fWalk(0)

{
  //constructor
   AliT0Parameters* param = AliT0Parameters::Instance();
   param->Init();
   //slewing correcion and equalizing channels

  fChannelWidth = param->GetChannelWidth() ;
   //   Double_t *grX ;
  for (Int_t i=0; i<24; i++){
    fMaxValue[i]=0;
    fTimeDelayCFD[i] = Int_t (param->GetTimeDelayCFD(i));
     TGraph* fu = param ->GetWalk(i);
    // fWalk.AddAtAndExpand(fu,i);
    //TGraph* fu = param ->GetAmpLEDRec(i);
    fWalk.AddAtAndExpand(fu,i);

  }

}
//_____________________________________________________________________________

AliT0Calibrator::AliT0Calibrator(const AliT0Calibrator &r): TNamed(),
  fChannelWidth(0),
  fWalk(0)

{
  //
  // AliT0calibartor copy constructor
  //

  ((AliT0Calibrator &) r).Copy(*this);

}

//_____________________________________________________________________________
AliT0Calibrator &AliT0Calibrator::operator=(const AliT0Calibrator &r)
{
  //
  // Assignment operator
  //

  if (this != &r) ((AliT0Calibrator &) r).Copy(*this);
  return *this;

}

//____________________________________________________________________

Int_t  AliT0Calibrator::WalkCorrection(Int_t refAmp,  Int_t ipmt, Int_t qt, Int_t time)

{
  //
  // referemce amplitude for walk correction now read from RecoParam
  Int_t walk=0;

  Int_t timeEq=0, timeWalk=0;
  TGraph *fu1=(TGraph*) fWalk.At(ipmt);
  if(fu1 && fu1->GetN()>0) {
    walk = Int_t(fu1->Eval(Double_t(qt)));
  }

  timeWalk = time - walk   ;
  timeEq =timeWalk - fTimeDelayCFD[ipmt]; //in refAmp - mean CFD position

  //   printf(" ipmt %i time before %i timeWalk %i , walk %i  qt %i fTimeDelayCFD[ipmt] %i timeEq %i \n ",
  //	 ipmt, time,timeWalk, walk, qt,fTimeDelayCFD[ipmt], timeEq );
     AliDebug(10,Form(" ipmt %i time before %i timeWalk %i , walk %i  qt %i timeEq %i \n ",
     ipmt, time,timeWalk, walk, qt, timeEq ));

   return timeEq;
}

<commit_msg>coverity<commit_after>
/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */
/***********************************************************************
 *      this class doing calibration during reconstruction
 *      2 steps:
 *      - equalizing channels
 *      - applying walk corrections
 *
 * Alla.Maevskaya@cern.ch
 *
 **********************************************************************/

//#include <Riostream.h>

#include "AliLog.h"
#include "AliT0Parameters.h"
#include "AliT0Calibrator.h"
#include "AliT0Reconstructor.h"
#include "AliT0RecoParam.h"
#include <TGraph.h>
#include <TH1F.h>
#include <TMath.h>
#include <Riostream.h>

ClassImp(AliT0Calibrator)

//____________________________________________________________________
  AliT0Calibrator::AliT0Calibrator():TNamed(),
				     fChannelWidth(0),
				     fWalk(0)

{
  //constructor
   AliT0Parameters* param = AliT0Parameters::Instance();
   param->Init();
   //slewing correcion and equalizing channels

  fChannelWidth = param->GetChannelWidth() ;
   //   Double_t *grX ;
  for (Int_t i=0; i<24; i++){
    fMaxValue[i]=0;
    fTimeDelayCFD[i] = Int_t (param->GetTimeDelayCFD(i));
     TGraph* fu = param ->GetWalk(i);
    // fWalk.AddAtAndExpand(fu,i);
    //TGraph* fu = param ->GetAmpLEDRec(i);
    fWalk.AddAtAndExpand(fu,i);

  }

}
//_____________________________________________________________________________

AliT0Calibrator::AliT0Calibrator(const AliT0Calibrator &r): TNamed(),
  fChannelWidth(0),
  fWalk(0)

{
  //
  // AliT0calibartor copy constructor
  //

  ((AliT0Calibrator &) r).Copy(*this);

}

//_____________________________________________________________________________
AliT0Calibrator &AliT0Calibrator::operator=(const AliT0Calibrator &r)
{
  //
  // Assignment operator
  //

  if (this != &r) ((AliT0Calibrator &) r).Copy(*this);
  return *this;

}

//____________________________________________________________________

Int_t  AliT0Calibrator::WalkCorrection(Int_t refAmp,  Int_t ipmt, Int_t qt, Int_t time)

{
  //
  // referemce amplitude for walk correction now read from RecoParam

   Int_t walk=0;
  Int_t timeEq=0, timeWalk=0;
  TGraph *fu1=(TGraph*) fWalk.At(ipmt);
  if(fu1 && fu1->GetN()>0) {
    walk = Int_t(fu1->Eval(Double_t(qt)));
  }

  timeWalk = time - walk   ;
  timeEq= timeWalk - fTimeDelayCFD[ipmt];
  //   printf(" ipmt %i time before %i timeWalk %i , walk %i  qt %i fTimeDelayCFD[ipmt] %i timeEq %i \n ",
  //	 ipmt, time,timeWalk, walk, qt,fTimeDelayCFD[ipmt], timeEq );
     AliDebug(10,Form(" ipmt %i refAmp %i time before %i timeWalk %i , walk %i  qt %i timeEq %i \n ",
		      ipmt, refAmp, time,timeWalk, walk, qt, timeEq ));

   return timeEq;
}

<|endoftext|>


<commit_before>// $Id$
// Category: global
//
// See the class description in the header file.

#include "TG4Globals.h"

#include <stdlib.h>

TG4Globals::TG4Globals() {
//
}

TG4Globals::~TG4Globals() {
//
}

// static methods

void TG4Globals::Exception(const char* string)
{
// Prints error message end exits the program.
// ---

  if (string)
  {  G4cerr << G4endl << "    " << string << G4endl; }
  G4cerr << "*** TG4Exception: Aborting execution ***" << G4endl;
  exit(1);
}

void TG4Globals::Warning(const char* string)
{
// Prints warning message.
// ---

  G4cerr << "++++  TG4Warning:  ++++" << G4endl;
  if (string)
  {  G4cerr  << "    " << string << G4endl; }
  G4cerr << "+++++++++++++++++++++++" << G4endl;
}
<commit_msg>added AppendNumberToString() method<commit_after>// $Id$
// Category: global
//
// See the class description in the header file.

#include "TG4Globals.h"

#include <stdlib.h>

TG4Globals::TG4Globals() {
//
}

TG4Globals::~TG4Globals() {
//
}

// static methods

void TG4Globals::Exception(const char* string)
{
// Prints error message end exits the program.
// ---

  if (string)
  {  G4cerr << G4endl << "    " << string << G4endl; }
  G4cerr << "*** TG4Exception: Aborting execution ***" << G4endl;
  exit(1);
}

void TG4Globals::Warning(const char* string)
{
// Prints warning message.
// ---

  G4cerr << "++++  TG4Warning:  ++++" << G4endl;
  if (string)
  {  G4cerr  << "    " << string << G4endl; }
  G4cerr << "+++++++++++++++++++++++" << G4endl;
}

void TG4Globals::AppendNumberToString(G4String& s, G4int a)
{
// Appends number to string.
// ---

  const char* kpNumber="0123456789";
  G4String p=""; G4String q="";
  do
  {
    G4int b=a/10;
    G4int c=a%10;
    p=kpNumber[c];
    q=p.append(q);
    a=b;
  } while (a>0);
  s.append(q);
}

<|endoftext|>