<commit_before>/*******************************************************************************

Licensed to the OpenCOR team under one or more contributor license agreements.
See the NOTICE.txt file distributed with this work for additional information
regarding copyright ownership. The OpenCOR team licenses this file to you under
the Apache License, Version 2.0 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.

*******************************************************************************/

//==============================================================================
// Lexer for the pretty CellML format
//==============================================================================

#include "prettycellmlviewlexer.h"
#include "qscintillawidget.h"

//==============================================================================

#include <QRegularExpression>

//==============================================================================

namespace OpenCOR {
namespace PrettyCellMLView {

//==============================================================================

PrettyCellmlViewLexer::PrettyCellmlViewLexer(QObject *pParent) :
    QsciLexerCustom(pParent),
    mFullText(QString()),
    mEolString(QString())
{
    // Some initialisations

    mKeywordsRegEx = QRegularExpression(
                         "\\b("
                             "as|base|comp|def|enddef|group|import|map|model|"
                             "unit|var"
                         ")\\b");

    mCellmlKeywordsRegEx = QRegularExpression(
                               "\\b("
                                   // Standard units

                                   "ampere|becquerel|candela|celsius|coulomb|"
                                   "dimensionless|farad|gram|gray|henry|hertz|"
                                   "joule|katal|kelvin|kilogram|liter|litre|"
                                   "lumen|lux|meter|metre|mole|newton|ohm|"
                                   "pascal|radian|second|siemens|sievert|"
                                   "steradian|tesla|volt|watt|weber"
                               ")\\b");

    mParameterKeywordsRegEx = QRegularExpression(
                                  "\\b("
                                      // Unit keywords

                                      "pref|expo|mult|off|"

                                      // Variable keywords

                                      "init|pub|priv"
                                  ")\\b");

    mParameterValueKeywordsRegEx = QRegularExpression(
                                       "\\b("
                                           // Unit prefixes

                                           "yotta|zetta|exa|peta|tera|giga|"
                                           "mega|kilo|hecto|deka|deci|centi|"
                                           "milli|micro|nano|pico|femto|atto|"
                                           "zepto|yocto|"

                                           // Public/private interfaces

                                           "in|out|none"
                                       ")\\b");

    mNumberRegEx = QRegularExpression("\\b\\d*\\.?\\d+([eE][+-]?\\d+)?\\b");
}

//==============================================================================

const char * PrettyCellmlViewLexer::language() const
{
    // Return the language for our lexer

    return "Pretty CellML";
}

//==============================================================================

QString PrettyCellmlViewLexer::description(int pStyle) const
{
    // Return the given style's description

    switch (pStyle) {
    case Default:
        return QObject::tr("Default");
    case Comment:
        return QObject::tr("Comment");
    case Keyword:
        return QObject::tr("Keyword");
    case CellmlKeyword:
        return QObject::tr("CellML keyword");
    case Number:
        return QObject::tr("Number");
    case ParameterGroup:
        return QObject::tr("Parameter group");
    case ParameterKeyword:
        return QObject::tr("Parameter keyword");
    case ParameterValueKeyword:
        return QObject::tr("Parameter value keyword");
    case ParameterNumber:
        return QObject::tr("Parameter number");
    }

    return QString();
}

//==============================================================================

QColor PrettyCellmlViewLexer::color(int pStyle) const
{
    // Return the given style's colour

    switch (pStyle) {
    case Default:
    case ParameterGroup:
        return QColor(0x1f, 0x1f, 0x1f);
    case Comment:
        return QColor(0x00, 0x7f, 0x00);
    case Keyword:
    case ParameterKeyword:
        return QColor(0x00, 0x00, 0x7f);
    case CellmlKeyword:
    case ParameterValueKeyword:
        return QColor(0x7f, 0x00, 0x7f);
    case Number:
    case ParameterNumber:
        return QColor(0x00, 0x7f, 0x7f);
    }

    return QsciLexerCustom::color(pStyle);
}

//==============================================================================

QFont PrettyCellmlViewLexer::font(int pStyle) const
{
    // Return the given style's colour

    QFont res = QsciLexer::font(pStyle);

    switch (pStyle) {
    case ParameterGroup:
    case ParameterKeyword:
    case ParameterValueKeyword:
    case ParameterNumber:
        res.setItalic(true);

        break;
    }

    return res;
}

//==============================================================================

void PrettyCellmlViewLexer::styleText(int pStart, int pEnd)
{
    // Make sure that we have an editor

    if (!editor())
        return;

    // Retrieve the text to style

    char *data = new char[pEnd-pStart+1];

    editor()->SendScintilla(QsciScintilla::SCI_GETTEXTRANGE, pStart, pEnd, data);

    QString text = QString(data);

    delete[] data;

    if (text.trimmed().isEmpty())
        return;

    // Effectively style our text

    mFullText = editor()->text();
    mEolString = qobject_cast<QScintillaSupport::QScintillaWidget *>(editor())->eolString();

    doStyleText(pStart, pEnd, text, false);

    // Let QScintilla know that we are done with the styling of our text
    // Note: indeed, QScintilla uses the end position of the last bit of text
    //       that we styled (in our call to doStyleText()) to determine the
    //       position (pStart) of the next bit of text to style (see
    //       QsciLexerCustom::handleStyleNeeded()). Now, depending on how we do
    //       the styling, that end position may not be optimal at all. So, here,
    //       we set that value to pEnd, which is what end position would be if
    //       we were to style sequentially...

    startStyling(pEnd);
}

//==============================================================================

static const auto CommentString = QStringLiteral("//");
static const int CommentStringLength = CommentString.length();

//==============================================================================

static const auto StartCommentString = QStringLiteral("/*");
static const auto EndCommentString = QStringLiteral("*/");
static const int StartCommentLength = StartCommentString.length();
static const int EndCommentLength = EndCommentString.length();

//==============================================================================

static const auto StartParameterGroupString = QStringLiteral("{");
static const auto EndParameterGroupString = QStringLiteral("}");
static const int StartParameterGroupLength = StartParameterGroupString.length();
static const int EndParameterGroupLength = EndParameterGroupString.length();

//==============================================================================

void PrettyCellmlViewLexer::doStyleText(int pStart, int pEnd, QString pText,
                                        bool pParameterGroup)
{
    // Make sure that we are given some text to style

    if (pText.trimmed().isEmpty())
        return;

    // Check whether a /* XXX */ comment started before or at the beginning of
    // the given text

    int commentStartPosition = mFullText.lastIndexOf(StartCommentString, pStart+StartCommentLength-1);

    if (commentStartPosition != -1) {
        // A /* XXX */ comment started before or at the beginning of the given
        // text, so now look for where it ends

        int commentEndPosition = mFullText.indexOf(EndCommentString, commentStartPosition+StartCommentLength);

        if (commentEndPosition == -1) {
            // The comment doesn't end as such, so consider that it 'ends' at
            // the of the full text

            commentEndPosition = mFullText.length();
        }

        if ((commentStartPosition <= pStart) && (pStart <= commentEndPosition)) {
            // The beginning of the given text is a comment, so style it

            int realEnd = commentEndPosition+EndCommentLength;
            int end = qMin(pEnd, realEnd);

            startStyling(pStart);
            setStyling(end-pStart, Comment);

            // Get ready to style everything that is behind the comment, if
            // anything

            if (end == realEnd) {
                pStart = end;
                pText = pText.right(pEnd-end);
            } else {
                return;
            }
        }
    }

    // Check whether a parameter group started before or at the beginning of the
    // given text

    int parameterGroupStartPosition = findString(StartParameterGroupString, pStart+StartParameterGroupLength-1, false);

    if (parameterGroupStartPosition != -1) {
        // A parameter group started before or at the beginning of the given
        // text, so now look for where it ends

        int parameterGroupEndPosition = findString(EndParameterGroupString, parameterGroupStartPosition+StartParameterGroupLength);

        if (parameterGroupEndPosition == -1)
            parameterGroupEndPosition = mFullText.length();

        if ((parameterGroupStartPosition <= pStart) && (pStart <= parameterGroupEndPosition)) {
            // The beginning of the given text is a parameter group, so style
            // everything that is behind the parameter group, if anything

            int realEnd = parameterGroupEndPosition+EndParameterGroupLength;
            int end = qMin(pEnd, realEnd);
            bool hasEnd = end == realEnd;

            if (hasEnd)
                doStyleText(end, pEnd, pText.right(pEnd-end), pParameterGroup);

            // If possible, style the beginning and/or the end of the parameter
            // group

            bool hasBeginning = parameterGroupStartPosition == pStart;

            if (hasBeginning) {
                startStyling(pStart);
                setStyling(StartParameterGroupLength, ParameterGroup);
            }

            if (hasEnd) {
                startStyling(end-EndParameterGroupLength);
                setStyling(EndParameterGroupLength, ParameterGroup);
            }

            // Now style the contents of the parameter group

            int newStart = pStart+(hasBeginning?StartParameterGroupLength:0);
            int newEnd = end-(hasEnd?EndParameterGroupLength:0);

            pText = pText.mid(newStart-pStart, newEnd-newStart);

            pStart = newStart;
            pEnd = newEnd;
            pParameterGroup = true;
        }
    }

    // Check whether the given text contains a // comment

    int commentPosition = pText.indexOf(CommentString);

    if (commentPosition != -1) {
        // There is a // comment to style, so first style everything that is
        // before it

        doStyleText(pStart, pStart+commentPosition, pText.left(commentPosition),
                    pParameterGroup);

        // Now, style everything that is after the // comment, if anything, by
        // looking for the end of the line on which the // comment is

        int eolPosition = pText.indexOf(mEolString, commentPosition+CommentStringLength);

        if (eolPosition != -1) {
            int start = pStart+eolPosition+mEolString.length();

            doStyleText(start, pEnd, pText.right(pEnd-start), pParameterGroup);
        }

        // Style the // comment itself

        int start = pStart+commentPosition;

        startStyling(start);
        setStyling(((eolPosition == -1)?pEnd:pStart+eolPosition)-start, Comment);

        return;
    }

    // Check whether the given text contains a /* XXX */ comment

    commentStartPosition = pText.indexOf(StartCommentString);

    if (commentStartPosition != -1) {
        // There is a /* XXX */ comment to style, so first style everything that
        // is before it

        doStyleText(pStart, pStart+commentStartPosition,
                    pText.left(commentStartPosition), pParameterGroup);

        // Now style everything from the comment onwards
        // Note: to style everything from the comment onwards means that we will
        //       find that a /* XXX */ comment starts at the beginning of the
        //       'new' given text...

        doStyleText(pStart+commentStartPosition, pEnd,
                    pText.right(pEnd-pStart-commentStartPosition),
                    pParameterGroup);

        return;
    }

    // Check whether the given text contains a parameter group

    parameterGroupStartPosition = pText.indexOf(StartParameterGroupString);

    if (parameterGroupStartPosition != -1) {
        // There is a parameter group, so first style everything that is before
        // it

        doStyleText(pStart, pStart+parameterGroupStartPosition,
                    pText.left(parameterGroupStartPosition), pParameterGroup);

        // Now style everything from the parameter group onwards
        // Note: to style everything from the parameter group onwards means that
        //       we will find that a parameter group starts at the beginning of
        //       the 'new' given text...

        doStyleText(pStart+parameterGroupStartPosition, pEnd,
                    pText.right(pEnd-pStart-parameterGroupStartPosition),
                    pParameterGroup);

        return;
    }

    // Use a default style for the given text

    startStyling(pStart);
    setStyling(pEnd-pStart, pParameterGroup?ParameterGroup:Default);

    // Check whether the given text contains keywords from various categories

    doStyleTextKeyword(pStart, pText, mKeywordsRegEx, pParameterGroup?ParameterGroup:Keyword);
    doStyleTextKeyword(pStart, pText, mCellmlKeywordsRegEx, pParameterGroup?ParameterGroup:CellmlKeyword);
    doStyleTextKeyword(pStart, pText, mParameterKeywordsRegEx, pParameterGroup?ParameterKeyword:Default);
    doStyleTextKeyword(pStart, pText, mParameterValueKeywordsRegEx, pParameterGroup?ParameterValueKeyword:Default);

    // Check whether the given text contains some numbers

    doStyleTextNumber(pStart, pText, pParameterGroup?ParameterNumber:Number);
}

//==============================================================================

void PrettyCellmlViewLexer::doStyleTextKeyword(int pStart,
                                               const QString &pText,
                                               const QRegularExpression &pKeywordsRegEx,
                                               const int &pKeywordStyle)
{
    // Style the given text with the given keyword style in the cases where a
    // match for the given regular expression is found

    QRegularExpressionMatchIterator regExMatchIter = pKeywordsRegEx.globalMatch(pText);
    QRegularExpressionMatch regExMatch;

    while (regExMatchIter.hasNext()) {
        regExMatch = regExMatchIter.next();

        // We found a keyword, so style it as such

        startStyling(pStart+regExMatch.capturedStart());
        setStyling(regExMatch.capturedLength(), pKeywordStyle);
    }
}

//==============================================================================

void PrettyCellmlViewLexer::doStyleTextNumber(int pStart, const QString &pText,
                                              const int &pNumberStyle)
{
    // Check whether the given text contains some numbers

    QRegularExpressionMatchIterator regExMatchIter = mNumberRegEx.globalMatch(pText);
    QRegularExpressionMatch regExMatch;

    while (regExMatchIter.hasNext()) {
        regExMatch = regExMatchIter.next();

        // We found a number, so style it as such

        startStyling(pStart+regExMatch.capturedStart());
        setStyling(regExMatch.capturedLength(), pNumberStyle);
    }
}

//==============================================================================

bool PrettyCellmlViewLexer::stringWithinComment(const int &pFrom,
                                                const int &pTo) const
{
    // Return whether the given string located at the given location is within
    // a comment

    // Check whether we are within a /* XXX */ comment

    int commentStartPosition = mFullText.lastIndexOf(StartCommentString, pFrom);

    if (commentStartPosition != -1) {
        int commentEndPosition = mFullText.indexOf(EndCommentString, commentStartPosition+StartCommentLength);

        if (commentEndPosition == -1)
            commentEndPosition = mFullText.length();

        if ((commentStartPosition < pFrom) && (pTo < commentEndPosition))
            return true;
    }

    // Check whether we are within a // comment

    int commentPosition = mFullText.lastIndexOf(CommentString, pFrom);

    if (commentPosition != -1) {
        int eolPosition = mFullText.indexOf(mEolString, commentPosition+CommentStringLength);

        if (eolPosition == -1)
            eolPosition = mFullText.length();

        if ((commentPosition < pFrom) && (pTo < eolPosition))
            return true;
    }

    return false;
}

//==============================================================================

int PrettyCellmlViewLexer::findString(const QString &pString, int pFrom,
                                      const bool &pForward)
{
    // Find forward/backward the given string starting from the given position

    int stringLength = pString.length();
    int res = pForward?pFrom-stringLength:pFrom+1;

    do {
        pFrom = pForward?res+stringLength:res-1;

        res = pForward?mFullText.indexOf(pString, pFrom):mFullText.lastIndexOf(pString, pFrom);
    } while ((res != -1) && stringWithinComment(res, res+stringLength-1));

    return res;
}

//==============================================================================

}   // namespace PrettyCellMLView
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<commit_msg>Pretty CellML view: some work on providing syntax highlighting for the pretty CellML format (#530) [ci skip].<commit_after>/*******************************************************************************

Licensed to the OpenCOR team under one or more contributor license agreements.
See the NOTICE.txt file distributed with this work for additional information
regarding copyright ownership. The OpenCOR team licenses this file to you under
the Apache License, Version 2.0 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.

*******************************************************************************/

//==============================================================================
// Lexer for the pretty CellML format
//==============================================================================

#include "prettycellmlviewlexer.h"
#include "qscintillawidget.h"

//==============================================================================

#include <QRegularExpression>

//==============================================================================

namespace OpenCOR {
namespace PrettyCellMLView {

//==============================================================================

PrettyCellmlViewLexer::PrettyCellmlViewLexer(QObject *pParent) :
    QsciLexerCustom(pParent),
    mFullText(QString()),
    mEolString(QString())
{
    // Some initialisations

    mKeywordsRegEx = QRegularExpression(
                         "\\b("
                             "as|base|comp|def|enddef|for|group|import|map|"
                             "model|unit|using|var"
                         ")\\b");

    mCellmlKeywordsRegEx = QRegularExpression(
                               "\\b("
                                   // Standard units

                                   "ampere|becquerel|candela|celsius|coulomb|"
                                   "dimensionless|farad|gram|gray|henry|hertz|"
                                   "joule|katal|kelvin|kilogram|liter|litre|"
                                   "lumen|lux|meter|metre|mole|newton|ohm|"
                                   "pascal|radian|second|siemens|sievert|"
                                   "steradian|tesla|volt|watt|weber"
                               ")\\b");

    mParameterKeywordsRegEx = QRegularExpression(
                                  "\\b("
                                      // Unit keywords

                                      "pref|expo|mult|off|"

                                      // Variable keywords

                                      "init|pub|priv"
                                  ")\\b");

    mParameterValueKeywordsRegEx = QRegularExpression(
                                       "\\b("
                                           // Unit prefixes

                                           "yotta|zetta|exa|peta|tera|giga|"
                                           "mega|kilo|hecto|deka|deci|centi|"
                                           "milli|micro|nano|pico|femto|atto|"
                                           "zepto|yocto|"

                                           // Public/private interfaces

                                           "in|out|none"
                                       ")\\b");

    mNumberRegEx = QRegularExpression("\\b\\d*\\.?\\d+([eE][+-]?\\d+)?\\b");
}

//==============================================================================

const char * PrettyCellmlViewLexer::language() const
{
    // Return the language for our lexer

    return "Pretty CellML";
}

//==============================================================================

QString PrettyCellmlViewLexer::description(int pStyle) const
{
    // Return the given style's description

    switch (pStyle) {
    case Default:
        return QObject::tr("Default");
    case Comment:
        return QObject::tr("Comment");
    case Keyword:
        return QObject::tr("Keyword");
    case CellmlKeyword:
        return QObject::tr("CellML keyword");
    case Number:
        return QObject::tr("Number");
    case ParameterGroup:
        return QObject::tr("Parameter group");
    case ParameterKeyword:
        return QObject::tr("Parameter keyword");
    case ParameterValueKeyword:
        return QObject::tr("Parameter value keyword");
    case ParameterNumber:
        return QObject::tr("Parameter number");
    }

    return QString();
}

//==============================================================================

QColor PrettyCellmlViewLexer::color(int pStyle) const
{
    // Return the given style's colour

    switch (pStyle) {
    case Default:
    case ParameterGroup:
        return QColor(0x1f, 0x1f, 0x1f);
    case Comment:
        return QColor(0x00, 0x7f, 0x00);
    case Keyword:
    case ParameterKeyword:
        return QColor(0x00, 0x00, 0x7f);
    case CellmlKeyword:
    case ParameterValueKeyword:
        return QColor(0x7f, 0x00, 0x7f);
    case Number:
    case ParameterNumber:
        return QColor(0x00, 0x7f, 0x7f);
    }

    return QsciLexerCustom::color(pStyle);
}

//==============================================================================

QFont PrettyCellmlViewLexer::font(int pStyle) const
{
    // Return the given style's colour

    QFont res = QsciLexer::font(pStyle);

    switch (pStyle) {
    case ParameterGroup:
    case ParameterKeyword:
    case ParameterValueKeyword:
    case ParameterNumber:
        res.setItalic(true);

        break;
    }

    return res;
}

//==============================================================================

void PrettyCellmlViewLexer::styleText(int pStart, int pEnd)
{
    // Make sure that we have an editor

    if (!editor())
        return;

    // Retrieve the text to style

    char *data = new char[pEnd-pStart+1];

    editor()->SendScintilla(QsciScintilla::SCI_GETTEXTRANGE, pStart, pEnd, data);

    QString text = QString(data);

    delete[] data;

    if (text.trimmed().isEmpty())
        return;

    // Effectively style our text

    mFullText = editor()->text();
    mEolString = qobject_cast<QScintillaSupport::QScintillaWidget *>(editor())->eolString();

    doStyleText(pStart, pEnd, text, false);

    // Let QScintilla know that we are done with the styling of our text
    // Note: indeed, QScintilla uses the end position of the last bit of text
    //       that we styled (in our call to doStyleText()) to determine the
    //       position (pStart) of the next bit of text to style (see
    //       QsciLexerCustom::handleStyleNeeded()). Now, depending on how we do
    //       the styling, that end position may not be optimal at all. So, here,
    //       we set that value to pEnd, which is what end position would be if
    //       we were to style sequentially...

    startStyling(pEnd);
}

//==============================================================================

static const auto CommentString = QStringLiteral("//");
static const int CommentStringLength = CommentString.length();

//==============================================================================

static const auto StartCommentString = QStringLiteral("/*");
static const auto EndCommentString = QStringLiteral("*/");
static const int StartCommentLength = StartCommentString.length();
static const int EndCommentLength = EndCommentString.length();

//==============================================================================

static const auto StartParameterGroupString = QStringLiteral("{");
static const auto EndParameterGroupString = QStringLiteral("}");
static const int StartParameterGroupLength = StartParameterGroupString.length();
static const int EndParameterGroupLength = EndParameterGroupString.length();

//==============================================================================

void PrettyCellmlViewLexer::doStyleText(int pStart, int pEnd, QString pText,
                                        bool pParameterGroup)
{
    // Make sure that we are given some text to style

    if (pText.trimmed().isEmpty())
        return;

    // Check whether a /* XXX */ comment started before or at the beginning of
    // the given text

    int commentStartPosition = mFullText.lastIndexOf(StartCommentString, pStart+StartCommentLength-1);

    if (commentStartPosition != -1) {
        // A /* XXX */ comment started before or at the beginning of the given
        // text, so now look for where it ends

        int commentEndPosition = mFullText.indexOf(EndCommentString, commentStartPosition+StartCommentLength);

        if (commentEndPosition == -1) {
            // The comment doesn't end as such, so consider that it 'ends' at
            // the of the full text

            commentEndPosition = mFullText.length();
        }

        if ((commentStartPosition <= pStart) && (pStart <= commentEndPosition)) {
            // The beginning of the given text is a comment, so style it

            int realEnd = commentEndPosition+EndCommentLength;
            int end = qMin(pEnd, realEnd);

            startStyling(pStart);
            setStyling(end-pStart, Comment);

            // Get ready to style everything that is behind the comment, if
            // anything

            if (end == realEnd) {
                pStart = end;
                pText = pText.right(pEnd-end);
            } else {
                return;
            }
        }
    }

    // Check whether a parameter group started before or at the beginning of the
    // given text

    int parameterGroupStartPosition = findString(StartParameterGroupString, pStart+StartParameterGroupLength-1, false);

    if (parameterGroupStartPosition != -1) {
        // A parameter group started before or at the beginning of the given
        // text, so now look for where it ends

        int parameterGroupEndPosition = findString(EndParameterGroupString, parameterGroupStartPosition+StartParameterGroupLength);

        if (parameterGroupEndPosition == -1)
            parameterGroupEndPosition = mFullText.length();

        if ((parameterGroupStartPosition <= pStart) && (pStart <= parameterGroupEndPosition)) {
            // The beginning of the given text is a parameter group, so style
            // everything that is behind the parameter group, if anything

            int realEnd = parameterGroupEndPosition+EndParameterGroupLength;
            int end = qMin(pEnd, realEnd);
            bool hasEnd = end == realEnd;

            if (hasEnd)
                doStyleText(end, pEnd, pText.right(pEnd-end), pParameterGroup);

            // If possible, style the beginning and/or the end of the parameter
            // group

            bool hasBeginning = parameterGroupStartPosition == pStart;

            if (hasBeginning) {
                startStyling(pStart);
                setStyling(StartParameterGroupLength, ParameterGroup);
            }

            if (hasEnd) {
                startStyling(end-EndParameterGroupLength);
                setStyling(EndParameterGroupLength, ParameterGroup);
            }

            // Now style the contents of the parameter group

            int newStart = pStart+(hasBeginning?StartParameterGroupLength:0);
            int newEnd = end-(hasEnd?EndParameterGroupLength:0);

            pText = pText.mid(newStart-pStart, newEnd-newStart);

            pStart = newStart;
            pEnd = newEnd;
            pParameterGroup = true;
        }
    }

    // Check whether the given text contains a // comment

    int commentPosition = pText.indexOf(CommentString);

    if (commentPosition != -1) {
        // There is a // comment to style, so first style everything that is
        // before it

        doStyleText(pStart, pStart+commentPosition, pText.left(commentPosition),
                    pParameterGroup);

        // Now, style everything that is after the // comment, if anything, by
        // looking for the end of the line on which the // comment is

        int eolPosition = pText.indexOf(mEolString, commentPosition+CommentStringLength);

        if (eolPosition != -1) {
            int start = pStart+eolPosition+mEolString.length();

            doStyleText(start, pEnd, pText.right(pEnd-start), pParameterGroup);
        }

        // Style the // comment itself

        int start = pStart+commentPosition;

        startStyling(start);
        setStyling(((eolPosition == -1)?pEnd:pStart+eolPosition)-start, Comment);

        return;
    }

    // Check whether the given text contains a /* XXX */ comment

    commentStartPosition = pText.indexOf(StartCommentString);

    if (commentStartPosition != -1) {
        // There is a /* XXX */ comment to style, so first style everything that
        // is before it

        doStyleText(pStart, pStart+commentStartPosition,
                    pText.left(commentStartPosition), pParameterGroup);

        // Now style everything from the comment onwards
        // Note: to style everything from the comment onwards means that we will
        //       find that a /* XXX */ comment starts at the beginning of the
        //       'new' given text...

        doStyleText(pStart+commentStartPosition, pEnd,
                    pText.right(pEnd-pStart-commentStartPosition),
                    pParameterGroup);

        return;
    }

    // Check whether the given text contains a parameter group

    parameterGroupStartPosition = pText.indexOf(StartParameterGroupString);

    if (parameterGroupStartPosition != -1) {
        // There is a parameter group, so first style everything that is before
        // it

        doStyleText(pStart, pStart+parameterGroupStartPosition,
                    pText.left(parameterGroupStartPosition), pParameterGroup);

        // Now style everything from the parameter group onwards
        // Note: to style everything from the parameter group onwards means that
        //       we will find that a parameter group starts at the beginning of
        //       the 'new' given text...

        doStyleText(pStart+parameterGroupStartPosition, pEnd,
                    pText.right(pEnd-pStart-parameterGroupStartPosition),
                    pParameterGroup);

        return;
    }

    // Use a default style for the given text

    startStyling(pStart);
    setStyling(pEnd-pStart, pParameterGroup?ParameterGroup:Default);

    // Check whether the given text contains keywords from various categories

    doStyleTextKeyword(pStart, pText, mKeywordsRegEx, pParameterGroup?ParameterGroup:Keyword);
    doStyleTextKeyword(pStart, pText, mCellmlKeywordsRegEx, pParameterGroup?ParameterGroup:CellmlKeyword);
    doStyleTextKeyword(pStart, pText, mParameterKeywordsRegEx, pParameterGroup?ParameterKeyword:Default);
    doStyleTextKeyword(pStart, pText, mParameterValueKeywordsRegEx, pParameterGroup?ParameterValueKeyword:Default);

    // Check whether the given text contains some numbers

    doStyleTextNumber(pStart, pText, pParameterGroup?ParameterNumber:Number);
}

//==============================================================================

void PrettyCellmlViewLexer::doStyleTextKeyword(int pStart,
                                               const QString &pText,
                                               const QRegularExpression &pKeywordsRegEx,
                                               const int &pKeywordStyle)
{
    // Style the given text with the given keyword style in the cases where a
    // match for the given regular expression is found

    QRegularExpressionMatchIterator regExMatchIter = pKeywordsRegEx.globalMatch(pText);
    QRegularExpressionMatch regExMatch;

    while (regExMatchIter.hasNext()) {
        regExMatch = regExMatchIter.next();

        // We found a keyword, so style it as such

        startStyling(pStart+regExMatch.capturedStart());
        setStyling(regExMatch.capturedLength(), pKeywordStyle);
    }
}

//==============================================================================

void PrettyCellmlViewLexer::doStyleTextNumber(int pStart, const QString &pText,
                                              const int &pNumberStyle)
{
    // Check whether the given text contains some numbers

    QRegularExpressionMatchIterator regExMatchIter = mNumberRegEx.globalMatch(pText);
    QRegularExpressionMatch regExMatch;

    while (regExMatchIter.hasNext()) {
        regExMatch = regExMatchIter.next();

        // We found a number, so style it as such

        startStyling(pStart+regExMatch.capturedStart());
        setStyling(regExMatch.capturedLength(), pNumberStyle);
    }
}

//==============================================================================

bool PrettyCellmlViewLexer::stringWithinComment(const int &pFrom,
                                                const int &pTo) const
{
    // Return whether the given string located at the given location is within
    // a comment

    // Check whether we are within a /* XXX */ comment

    int commentStartPosition = mFullText.lastIndexOf(StartCommentString, pFrom);

    if (commentStartPosition != -1) {
        int commentEndPosition = mFullText.indexOf(EndCommentString, commentStartPosition+StartCommentLength);

        if (commentEndPosition == -1)
            commentEndPosition = mFullText.length();

        if ((commentStartPosition < pFrom) && (pTo < commentEndPosition))
            return true;
    }

    // Check whether we are within a // comment

    int commentPosition = mFullText.lastIndexOf(CommentString, pFrom);

    if (commentPosition != -1) {
        int eolPosition = mFullText.indexOf(mEolString, commentPosition+CommentStringLength);

        if (eolPosition == -1)
            eolPosition = mFullText.length();

        if ((commentPosition < pFrom) && (pTo < eolPosition))
            return true;
    }

    return false;
}

//==============================================================================

int PrettyCellmlViewLexer::findString(const QString &pString, int pFrom,
                                      const bool &pForward)
{
    // Find forward/backward the given string starting from the given position

    int stringLength = pString.length();
    int res = pForward?pFrom-stringLength:pFrom+1;

    do {
        pFrom = pForward?res+stringLength:res-1;

        res = pForward?mFullText.indexOf(pString, pFrom):mFullText.lastIndexOf(pString, pFrom);
    } while ((res != -1) && stringWithinComment(res, res+stringLength-1));

    return res;
}

//==============================================================================

}   // namespace PrettyCellMLView
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<|endoftext|>


<commit_before><commit_msg>patch accessing_xhr.response_as_arraybuffer_from_node_context<commit_after><|endoftext|>


<commit_before>/* Copyright 2020 The TensorFlow Quantum Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include <memory>
#include <vector>

#include "cirq/google/api/v2/program.pb.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/shape_inference.h"
#include "tensorflow/core/framework/tensor_shape.h"
#include "tensorflow/core/lib/core/error_codes.pb.h"
#include "tensorflow/core/lib/core/status.h"
#include "tensorflow/core/lib/core/threadpool.h"
#include "tensorflow_quantum/core/ops/parse_context.h"
#include "tensorflow_quantum/core/ops/tfq_simulate_utils.h"
#include "tensorflow_quantum/core/proto/pauli_sum.pb.h"
#include "tensorflow_quantum/core/qsim/mux.h"
#include "tensorflow_quantum/core/qsim/state_space.h"
#include "tensorflow_quantum/core/src/circuit.h"
#include "tensorflow_quantum/core/src/circuit_parser.h"
#include "tensorflow_quantum/core/src/program_resolution.h"

namespace tfq {

using ::cirq::google::api::v2::Program;
using ::tensorflow::Status;
using ::tfq::proto::PauliSum;
using ::tfq::qsim::GetStateSpace;
using ::tfq::qsim::StateSpace;

class TfqSimulateSampledExpectationOp : public tensorflow::OpKernel {
 public:
  explicit TfqSimulateSampledExpectationOp(
      tensorflow::OpKernelConstruction *context)
      : OpKernel(context) {}

  void Compute(tensorflow::OpKernelContext *context) override {
    // TODO (mbbrough): add more dimension checks for other inputs here.
    const int num_inputs = context->num_inputs();
    OP_REQUIRES(context, num_inputs == 5,
                tensorflow::errors::InvalidArgument(absl::StrCat(
                    "Expected 5 inputs, got ", num_inputs, " inputs.")));

    // Create the output Tensor.
    const int output_dim_batch_size = context->input(0).dim_size(0);
    const int output_dim_op_size = context->input(3).dim_size(1);
    tensorflow::TensorShape output_shape;
    output_shape.AddDim(output_dim_batch_size);
    output_shape.AddDim(output_dim_op_size);

    tensorflow::Tensor *output = nullptr;
    OP_REQUIRES_OK(context, context->allocate_output(0, output_shape, &output));
    auto output_tensor = output->matrix<float>();

    std::vector<Program> programs;
    std::vector<int> num_qubits;
    std::vector<std::vector<PauliSum>> pauli_sums;
    OP_REQUIRES_OK(context, GetProgramsAndNumQubits(context, &programs,
                                                    &num_qubits, &pauli_sums));

    std::vector<SymbolMap> maps;
    OP_REQUIRES_OK(context, GetSymbolMaps(context, &maps));

    OP_REQUIRES(context, pauli_sums.size() == programs.size(),
                tensorflow::errors::InvalidArgument(absl::StrCat(
                    "Number of circuits and PauliSums do not match. Got ",
                    programs.size(), " circuits and ", pauli_sums.size(),
                    " paulisums.")));

    std::vector<std::vector<unsigned int>> num_samples;
    OP_REQUIRES_OK(context, GetNumSamples(context, &num_samples));

    OP_REQUIRES(context, num_samples.size() == pauli_sums.size(),
                tensorflow::errors::InvalidArgument(absl::StrCat(
                    "Dimension 0 of num_samples and pauli_sums do not match.",
                    "Got ", num_samples.size(), " lists of sample sizes and ",
                    pauli_sums.size(), " lists of pauli sums.")));

    auto DoWork = [&](int start, int end) {
      int old_batch_index = -2;
      int cur_batch_index = -1;
      int old_num_qubits = -2;
      int cur_op_index;
      std::unique_ptr<StateSpace> test_state =
          std::unique_ptr<StateSpace>(GetStateSpace(1, 1));
      std::unique_ptr<StateSpace> scratch_state =
          std::unique_ptr<StateSpace>(GetStateSpace(1, 1));
      for (int i = start; i < end; i++) {
        cur_batch_index = i / output_dim_op_size;
        cur_op_index = i % output_dim_op_size;

        // (#679) Just ignore empty program
        if (programs[cur_batch_index].circuit().moments().empty()) {
          output_tensor(cur_batch_index, cur_op_index) = -2.0;
          continue;
        }

        if (cur_batch_index != old_batch_index) {
          // We've run into a new wavefunction we must compute.
          // Only compute a new wavefunction when we have to.
          Program program = programs[cur_batch_index];
          const int num = num_qubits[cur_batch_index];
          OP_REQUIRES_OK(context,
                         ResolveSymbols(maps[cur_batch_index], &program));

          Circuit circuit;
          OP_REQUIRES_OK(context, CircuitFromProgram(program, num, &circuit));

          // TODO(mbbrough): Update this allocation hack so that a StateSpace
          //  object can grow it's memory dynamically to larger and larger size
          //  without ever having to call free (until very end). This is tricky
          //  to implement because right now certain statespaces can't simulate
          //  all states and we use StateSpaceSlow for smaller circuits.
          if (num != old_num_qubits) {
            test_state.reset(GetStateSpace(num, 1));
            test_state->CreateState();

            // Also re-allocate scratch state for expectation calculations.
            scratch_state.reset(GetStateSpace(num, 1));
            scratch_state->CreateState();
          }
          // no need to update scratch_state since ComputeExpectation
          // will take care of things for us.
          test_state->SetStateZero();
          OP_REQUIRES_OK(context, test_state->Update(circuit));
          old_num_qubits = num;
        }

        float expectation = 0.0;
        OP_REQUIRES_OK(
            context,
            test_state->ComputeSampledExpectation(
                pauli_sums[cur_batch_index][cur_op_index], scratch_state.get(),
                &expectation, num_samples[cur_batch_index][cur_op_index]));

        output_tensor(cur_batch_index, cur_op_index) = expectation;
        old_batch_index = cur_batch_index;
      }
    };

    const int block_size =
        GetBlockSize(context, output_dim_batch_size * output_dim_op_size);
    context->device()
        ->tensorflow_cpu_worker_threads()
        ->workers->TransformRangeConcurrently(
            block_size, output_dim_batch_size * output_dim_op_size, DoWork);
  }
};

REGISTER_KERNEL_BUILDER(
    Name("TfqSimulateSampledExpectation").Device(tensorflow::DEVICE_CPU),
    TfqSimulateSampledExpectationOp);

REGISTER_OP("TfqSimulateSampledExpectation")
    .Input("programs: string")
    .Input("symbol_names: string")
    .Input("symbol_values: float")
    .Input("pauli_sums: string")
    .Input("num_samples: uint32")
    .Output("expectations: float")
    .SetShapeFn([](tensorflow::shape_inference::InferenceContext *c) {
      tensorflow::shape_inference::ShapeHandle programs_shape;
      TF_RETURN_IF_ERROR(c->WithRank(c->input(0), 1, &programs_shape));

      tensorflow::shape_inference::ShapeHandle symbol_names_shape;
      TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 1, &symbol_names_shape));

      tensorflow::shape_inference::ShapeHandle symbol_values_shape;
      TF_RETURN_IF_ERROR(c->WithRank(c->input(2), 2, &symbol_values_shape));

      tensorflow::shape_inference::ShapeHandle pauli_sums_shape;
      TF_RETURN_IF_ERROR(c->WithRank(c->input(3), 2, &pauli_sums_shape));

      tensorflow::shape_inference::ShapeHandle num_samples_shape;
      TF_RETURN_IF_ERROR(c->WithRank(c->input(4), 2, &num_samples_shape));

      tensorflow::shape_inference::DimensionHandle output_rows =
          c->Dim(programs_shape, 0);
      tensorflow::shape_inference::DimensionHandle output_cols =
          c->Dim(pauli_sums_shape, 1);
      c->set_output(0, c->Matrix(output_rows, output_cols));

      return tensorflow::Status::OK();
    });

}  // namespace tfq
<commit_msg>Update to pointer<commit_after>/* Copyright 2020 The TensorFlow Quantum Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include <memory>
#include <vector>

#include "cirq/google/api/v2/program.pb.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/shape_inference.h"
#include "tensorflow/core/framework/tensor_shape.h"
#include "tensorflow/core/lib/core/error_codes.pb.h"
#include "tensorflow/core/lib/core/status.h"
#include "tensorflow/core/lib/core/threadpool.h"
#include "tensorflow_quantum/core/ops/parse_context.h"
#include "tensorflow_quantum/core/ops/tfq_simulate_utils.h"
#include "tensorflow_quantum/core/proto/pauli_sum.pb.h"
#include "tensorflow_quantum/core/qsim/mux.h"
#include "tensorflow_quantum/core/qsim/state_space.h"
#include "tensorflow_quantum/core/src/circuit.h"
#include "tensorflow_quantum/core/src/circuit_parser.h"
#include "tensorflow_quantum/core/src/program_resolution.h"

namespace tfq {

using ::cirq::google::api::v2::Program;
using ::tensorflow::Status;
using ::tfq::proto::PauliSum;
using ::tfq::qsim::GetStateSpace;
using ::tfq::qsim::StateSpace;

class TfqSimulateSampledExpectationOp : public tensorflow::OpKernel {
 public:
  explicit TfqSimulateSampledExpectationOp(
      tensorflow::OpKernelConstruction *context)
      : OpKernel(context) {}

  void Compute(tensorflow::OpKernelContext *context) override {
    // TODO (mbbrough): add more dimension checks for other inputs here.
    const int num_inputs = context->num_inputs();
    OP_REQUIRES(context, num_inputs == 5,
                tensorflow::errors::InvalidArgument(absl::StrCat(
                    "Expected 5 inputs, got ", num_inputs, " inputs.")));

    // Create the output Tensor.
    const int output_dim_batch_size = context->input(0).dim_size(0);
    const int output_dim_op_size = context->input(3).dim_size(1);
    tensorflow::TensorShape output_shape;
    output_shape.AddDim(output_dim_batch_size);
    output_shape.AddDim(output_dim_op_size);

    tensorflow::Tensor *output = nullptr;
    OP_REQUIRES_OK(context, context->allocate_output(0, output_shape, &output));
    auto output_tensor = output->matrix<float>();

    std::vector<Program> programs;
    std::vector<int> num_qubits;
    std::vector<std::vector<PauliSum>> pauli_sums;
    OP_REQUIRES_OK(context, GetProgramsAndNumQubits(context, &programs,
                                                    &num_qubits, &pauli_sums));

    std::vector<SymbolMap> maps;
    OP_REQUIRES_OK(context, GetSymbolMaps(context, &maps));

    OP_REQUIRES(context, pauli_sums.size() == programs.size(),
                tensorflow::errors::InvalidArgument(absl::StrCat(
                    "Number of circuits and PauliSums do not match. Got ",
                    programs.size(), " circuits and ", pauli_sums.size(),
                    " paulisums.")));

    std::vector<std::vector<unsigned int>> num_samples;
    OP_REQUIRES_OK(context, GetNumSamples(context, &num_samples));

    OP_REQUIRES(context, num_samples.size() == pauli_sums.size(),
                tensorflow::errors::InvalidArgument(absl::StrCat(
                    "Dimension 0 of num_samples and pauli_sums do not match.",
                    "Got ", num_samples.size(), " lists of sample sizes and ",
                    pauli_sums.size(), " lists of pauli sums.")));

    auto DoWork = [&](int start, int end) {
      int old_batch_index = -2;
      int cur_batch_index = -1;
      int old_num_qubits = -2;
      int cur_op_index;
      std::unique_ptr<StateSpace> test_state = GetStateSpace(1, 1);
      std::unique_ptr<StateSpace> scratch_state = GetStateSpace(1, 1);
      for (int i = start; i < end; i++) {
        cur_batch_index = i / output_dim_op_size;
        cur_op_index = i % output_dim_op_size;

        // (#679) Just ignore empty program
        if (programs[cur_batch_index].circuit().moments().empty()) {
          output_tensor(cur_batch_index, cur_op_index) = -2.0;
          continue;
        }

        if (cur_batch_index != old_batch_index) {
          // We've run into a new wavefunction we must compute.
          // Only compute a new wavefunction when we have to.
          Program program = programs[cur_batch_index];
          const int num = num_qubits[cur_batch_index];
          OP_REQUIRES_OK(context,
                         ResolveSymbols(maps[cur_batch_index], &program));

          Circuit circuit;
          OP_REQUIRES_OK(context, CircuitFromProgram(program, num, &circuit));

          // TODO(mbbrough): Update this allocation hack so that a StateSpace
          //  object can grow it's memory dynamically to larger and larger size
          //  without ever having to call free (until very end). This is tricky
          //  to implement because right now certain statespaces can't simulate
          //  all states and we use StateSpaceSlow for smaller circuits.
          if (num != old_num_qubits) {
            test_state = GetStateSpace(num, 1);
            test_state->CreateState();

            // Also re-allocate scratch state for expectation calculations.
            scratch_state = GetStateSpace(num, 1);
            scratch_state->CreateState();
          }
          // no need to update scratch_state since ComputeExpectation
          // will take care of things for us.
          test_state->SetStateZero();
          OP_REQUIRES_OK(context, test_state->Update(circuit));
          old_num_qubits = num;
        }

        float expectation = 0.0;
        OP_REQUIRES_OK(
            context,
            test_state->ComputeSampledExpectation(
                pauli_sums[cur_batch_index][cur_op_index], scratch_state.get(),
                &expectation, num_samples[cur_batch_index][cur_op_index]));

        output_tensor(cur_batch_index, cur_op_index) = expectation;
        old_batch_index = cur_batch_index;
      }
    };

    const int block_size =
        GetBlockSize(context, output_dim_batch_size * output_dim_op_size);
    context->device()
        ->tensorflow_cpu_worker_threads()
        ->workers->TransformRangeConcurrently(
            block_size, output_dim_batch_size * output_dim_op_size, DoWork);
  }
};

REGISTER_KERNEL_BUILDER(
    Name("TfqSimulateSampledExpectation").Device(tensorflow::DEVICE_CPU),
    TfqSimulateSampledExpectationOp);

REGISTER_OP("TfqSimulateSampledExpectation")
    .Input("programs: string")
    .Input("symbol_names: string")
    .Input("symbol_values: float")
    .Input("pauli_sums: string")
    .Input("num_samples: uint32")
    .Output("expectations: float")
    .SetShapeFn([](tensorflow::shape_inference::InferenceContext *c) {
      tensorflow::shape_inference::ShapeHandle programs_shape;
      TF_RETURN_IF_ERROR(c->WithRank(c->input(0), 1, &programs_shape));

      tensorflow::shape_inference::ShapeHandle symbol_names_shape;
      TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 1, &symbol_names_shape));

      tensorflow::shape_inference::ShapeHandle symbol_values_shape;
      TF_RETURN_IF_ERROR(c->WithRank(c->input(2), 2, &symbol_values_shape));

      tensorflow::shape_inference::ShapeHandle pauli_sums_shape;
      TF_RETURN_IF_ERROR(c->WithRank(c->input(3), 2, &pauli_sums_shape));

      tensorflow::shape_inference::ShapeHandle num_samples_shape;
      TF_RETURN_IF_ERROR(c->WithRank(c->input(4), 2, &num_samples_shape));

      tensorflow::shape_inference::DimensionHandle output_rows =
          c->Dim(programs_shape, 0);
      tensorflow::shape_inference::DimensionHandle output_cols =
          c->Dim(pauli_sums_shape, 1);
      c->set_output(0, c->Matrix(output_rows, output_cols));

      return tensorflow::Status::OK();
    });

}  // namespace tfq
<|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$ */

//--------------------------------------------------------------------
//          Options for the TPC Reconstruction in rec.C
//
//  4 options can be set to change the input for TPC reconstruction
//  which overwrites the usage of fUseHLTClusters of the AliTPCRecoParam
//
//  1) useRAW        - use RAW, if not present -> do nothing
//  2) useRAWorHLT   - use RAW, if not present -> use HLT clusters
//  3) useHLT        - use HLT clusters, if not present -> do nothing
//  4) useHLTorRAW   - use HLT clusters, if not present -> use RAW
//
//  -> The current default is useHLTorRAW
//--------------------------------------------------------------------

///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// class for TPC reconstruction                                              //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include <TObject.h>
#include <TString.h>
#include <TObjString.h>
#include <TObjArray.h>
#include <TFile.h>

#include <AliLog.h>
#include <AliPID.h>
#include <AliESDpid.h>
#include <AliTPCPIDResponse.h>
#include "AliTPCReconstructor.h"
#include "AliRunLoader.h"
#include "AliRun.h"
#include "AliRawReader.h"
#include "AliTPCclusterer.h"
#include "AliTPCtracker.h"
#include "AliTPCParam.h"
#include "AliTPCParamSR.h"
#include "AliTPCcalibDB.h"
#include "AliTracker.h"
#include "AliMagF.h"
#include "TTreeStream.h"

ClassImp(AliTPCReconstructor)

Int_t    AliTPCReconstructor::fgStreamLevel     = 0;             // stream (debug) level
AliTPCAltroEmulator *  AliTPCReconstructor::fAltroEmulator=0;    // ALTRO emulator
TTreeSRedirector    *  AliTPCReconstructor::fgDebugStreamer=0;                          // NOTE -  AliTPCReconstructor is not an owner of the streamer
TString                AliTPCReconstructor::fgPIDRespnonsePath="$ALICE_PHYSICS/OADB/COMMON/PID/data/TPCPIDResponse.root";

TVectorD *  AliTPCReconstructor::fSystematicErrors=0;
TVectorD *  AliTPCReconstructor::fSystematicErrorClusters=0;
TVectorD *  AliTPCReconstructor::fgExtendedRoads=0;
TVectorD *  AliTPCReconstructor::fgPrimaryDCACut=0;
Double_t    AliTPCReconstructor::fgPrimaryZ2XCut = 0;
Double_t    AliTPCReconstructor::fgZOutSectorCut = 0;
Bool_t      AliTPCReconstructor::fgCompactClusters = kFALSE;
Bool_t      AliTPCReconstructor::fgCountMCTrackClusters = kFALSE;

AliTPCReconstructor::AliTPCReconstructor():
AliReconstructor(),
fClusterer(NULL),
fArrSplines(NULL)
{
  //
  // default constructor
  //
  //
  //
  AliTPCcalibDB * calib = AliTPCcalibDB::Instance();
  const AliMagF * field = (AliMagF*)TGeoGlobalMagField::Instance()->GetField();
  calib->SetExBField(field);
  AliTPCParam* param = GetTPCParam();
  if (!param) {
    AliWarning("Loading default TPC parameters !");
    param = new AliTPCParamSR;
  }
  fClusterer = new AliTPCclusterer(param);
}

AliTPCReconstructor::AliTPCReconstructor(const AliTPCReconstructor& /*rec*/):
AliReconstructor(),
fClusterer(NULL),
fArrSplines(NULL)
{
  //
  // Dummy copu constructor
  //
}

AliTPCReconstructor& AliTPCReconstructor::operator=(const AliTPCReconstructor&){
  //
  // dummy operator
  //
  return *this;
}

//_____________________________________________________________________________
AliTPCReconstructor::~AliTPCReconstructor()
{
  if (fClusterer)   delete fClusterer;
  delete fArrSplines;
  delete AliTPCcalibDB::Instance();
}

//_____________________________________________________________________________
void AliTPCReconstructor::Reconstruct(TTree* digitsTree, TTree* clustersTree) const {
  // single event local reconstruction
  // of TPC data
  fClusterer->SetTimeStamp(GetTimeStamp());
  fClusterer->SetInput(digitsTree);
  fClusterer->SetOutput(clustersTree);
  fClusterer->Digits2Clusters();
}

//_____________________________________________________________________________
void AliTPCReconstructor::Reconstruct(AliRawReader* rawReader, TTree* clustersTree) const {
  // single event local reconstruction
  // of TPC data starting from raw data
  fClusterer->SetTimeStamp(GetTimeStamp());
  fClusterer->SetOutput(clustersTree);
  fClusterer->Digits2Clusters(rawReader);
}

//_____________________________________________________________________________
AliTracker* AliTPCReconstructor::CreateTracker() const
{
// create a TPC tracker

  AliTPCParam* param = GetTPCParam();
  if (!param) {
    AliWarning("Loading default TPC parameters !");
    param = new AliTPCParamSR;
  }
  param->ReadGeoMatrices();

  AliTPCtracker* tracker = new AliTPCtracker(param);

  ParseOptions(tracker);

  return tracker;
}

//_____________________________________________________________________________
void AliTPCReconstructor::FillESD(TTree */*digitsTree*/, TTree */*clustersTree*/,
				  AliESDEvent* /*esd*/) const
{
// make PID
/*  Now done in AliESDpid
  Double_t parTPC[] = {50., 0.07, 5.};  // MIP nnormalized to channel 50 -MI
  AliTPCpidESD tpcPID(parTPC);
  tpcPID.MakePID(esd);
*/
}

//_____________________________________________________________________________
AliTPCParam* AliTPCReconstructor::GetTPCParam() const
{
// get the TPC parameters

  AliTPCParam* param = AliTPCcalibDB::Instance()->GetParameters();

  return param;
}

//_____________________________________________________________________________
void AliTPCReconstructor::SetSplinesFromOADB(const char* tmplt, AliESDpid *esdPID)
{
  //
  //  load splines from the OADB using 'template'
  //

  // only load splines if not already set
  if (!fArrSplines) {
    fArrSplines=new TObjArray(Int_t(AliPID::kSPECIES));
    fArrSplines->SetOwner();
    TString stemplate(tmplt);

    TFile f(GetPIDRespnonsePath());

    TObjArray *arrPidResponseMaster=0x0;

    if (f.IsOpen() && !f.IsZombie()){
      arrPidResponseMaster=dynamic_cast<TObjArray*>(f.Get("TPCPIDResponse"));
    }
    f.Close();

    if (!arrPidResponseMaster){
      AliError("PID response array not found, cannot assign proper splines");
      return;
    }

    for (Int_t ispec=0; ispec<AliPID::kSPECIES; ++ispec)
    {
      Int_t ispec2=ispec;
      if (ispec==Int_t(AliPID::kMuon)) ispec2=Int_t(AliPID::kPion);

      TString particle=AliPID::ParticleName(ispec2);
      particle.ToUpper();

      TString splineName;
      splineName.Form(stemplate.Data(),particle.Data());
      TObject *spline=arrPidResponseMaster->FindObject(splineName.Data());
      if (!spline) {
        AliError(Form("No spline found for '%s'", splineName.Data()));
        continue;
      };
      AliInfo(Form("Adding Response function %d:%s",ispec,splineName.Data()));
      fArrSplines->AddAt(spline->Clone(), ispec);
    }
    arrPidResponseMaster->Delete();
    delete arrPidResponseMaster;
    if (fArrSplines->GetEntries()!=Int_t(AliPID::kSPECIES)) {
      AliError("Splines not found for all species, cannot use proper PID");
      delete fArrSplines;
      fArrSplines=NULL;
      return;
    }
  }

  for (Int_t ispec=0; ispec<AliPID::kSPECIES; ++ispec)
  {
    esdPID->GetTPCResponse().SetResponseFunction( (AliPID::EParticleType)ispec, fArrSplines->UncheckedAt(ispec) );
  }

  esdPID->GetTPCResponse().SetUseDatabase(kTRUE);
}

//_____________________________________________________________________________
void AliTPCReconstructor::GetPidSettings(AliESDpid *esdPID)
{
  //
  // Get TPC pid splines. They should be written to the OCDB during the CPass
  // the splines themselves are owned by the OCDB object
  //

  // parse options
  TString allopt(GetOption());
  TObjArray *optArray=allopt.Tokenize(";");

  // defines whether the pid was set via a specific option in the rec.C
  Bool_t pidSetInOptions = kFALSE;

  for (Int_t iopt=0; iopt<optArray->GetEntriesFast(); ++iopt){
    if (!optArray->At(iopt)) continue;
    TString option(static_cast<TObjString*>(optArray->At(iopt))->GetString().Strip(TString::kBoth,' '));

    if (!option.BeginsWith("PID.")) continue;

    // remove 'PID.' identifyer
    option.Remove(0,4);

    // parse PID type
    if (option.BeginsWith("Static=")){
      option.Remove(0,option.First('=')+1);
      if (option.Contains("LHC13b2_fix_PID")) {
        esdPID->GetTPCResponse().SetBetheBlochParameters(0.0320981, 19.9768, 2.52666e-16, 2.72123, 6.08092);
        esdPID->GetTPCResponse().SetMip(53.4968);
        pidSetInOptions=kTRUE;
      }

    } else if (option.BeginsWith("OADB=")) {
      option.Remove(0,option.First('=')+1);
      AliInfo(Form("Setting splines From OADB using template: '%s'",option.Data()));
      SetSplinesFromOADB(option, esdPID);
      pidSetInOptions=kTRUE;
    } else if (option.BeginsWith("OCDB=")){
      option.Remove(0,option.First('=')+1);
      // not yet implemented
    }

  }

  delete optArray;

  //
  // Initialisation of BB parameters from the OCDB.
  // They are stored in the AliTPCParam
  //
  if (!pidSetInOptions) {
    AliTPCParam* param = AliTPCcalibDB::Instance()->GetParameters();
    if (param) {
      TVectorD *paramBB=param->GetBetheBlochParameters();
      const Float_t maxnSigmaRange = param->GetSigmaRangePIDinTracking();
      if (paramBB){
        esdPID->GetTPCResponse().SetBetheBlochParameters((*paramBB)(0),(*paramBB)(1),(*paramBB)(2),(*paramBB)(3),(*paramBB)(4));
        AliInfo(Form("Setting BB parameters from OCDB (AliTPCParam): %.2g, %.2g, %.2g, %.2g, %.2g",
                     (*paramBB)(0),(*paramBB)(1),(*paramBB)(2),(*paramBB)(3),(*paramBB)(4)));
        AliInfoF("Setting max sigma PID range to %.2f", maxnSigmaRange);
        esdPID->SetProbabilityRangeNsigma(maxnSigmaRange);
      } else {
        AliError("Couldn't get BB parameters from OCDB, the old default values will be used instead");
      }
    } else {
      AliError("Couldn't get TPC parameters");
    }
  }

/*
  AliTPCcalibDB * calib = AliTPCcalibDB::Instance();

  //Get pid splines array
  TObjArray *arrSplines=calib->GetPidResponse();
  if (!arrSplines) return;
  AliTPCPIDResponse &tpcPID=esdPID->GetTPCResponse();
  tpcPID.SetUseDatabase(kTRUE);

  // check if parametrisations are already set.
  // since this is uniq for one run, we don't have to reload them
  if (tpcPID.GetResponseFunction(AliPID::kPion)) return;

  // get the default object
  TObject *defaultPID=arrSplines->At(AliPID::kUnknown);

  // loop over all particle species and set the response functions
  for (Int_t ispec=0; ispec<AliPID::kUnknown; ++ispec){
    TObject *pidSpline=arrSplines->At(ispec);
    if (!pidSpline) pidSpline=defaultPID;
    tpcPID.SetResponseFunction((AliPID::EParticleType)ispec,pidSpline);
  }
 */
}

//_____________________________________________________________________________
void AliTPCReconstructor::ParseOptions( AliTPCtracker* tracker ) const
{
// parse options from rec.C and set in clusterer and tracker

  TString option = GetOption();

  Int_t useHLTClusters = 3;

  if (option.Contains("use")) {

    AliInfo(Form("Overide TPC RecoParam with option %s",option.Data()));

    if (option.Contains("useRAW")) {
      useHLTClusters = 1;
      if (option.Contains("useRAWorHLT"))
	useHLTClusters = 2;
    }
    else if (option.Contains("useHLT")) {
      useHLTClusters = 3;
      if (option.Contains("useHLTorRAW"))
	useHLTClusters = 4;
    }
  }
  else {
    const AliTPCRecoParam* param = GetRecoParam();
    useHLTClusters = param->GetUseHLTClusters();
  }

  AliInfo(Form("Usage of HLT clusters in TPC reconstruction : %d", useHLTClusters));

  fClusterer->SetUseHLTClusters(useHLTClusters);
  tracker->SetUseHLTClusters(useHLTClusters);

  return;
}

//_____________________________________________________________________________
void AliTPCReconstructor::SetSystematicErrorCluster( TVectorD *vec )
{
  // set clusters syst.errors which will override persistent data member from AliTPCRecoParam::fSystematicErrors
  fSystematicErrorClusters=vec;
  AliTPCRecoParam::SetSystematicErrorClusterCustom(vec);
}

//_____________________________________________________________________________
void AliTPCReconstructor::SetPrimaryDCACut( TVectorD *dcacut )
{
  // set clusters syst.errors which will override persistent data member from AliTPCRecoParam::fSystematicErrors
  fgPrimaryDCACut=dcacut;
  AliTPCRecoParam::SetPrimaryDCACut(dcacut);
}
<commit_msg>fix typo in comment<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$ */

//--------------------------------------------------------------------
//          Options for the TPC Reconstruction in rec.C
//
//  4 options can be set to change the input for TPC reconstruction
//  which overwrites the usage of fUseHLTClusters of the AliTPCRecoParam
//
//  1) useRAW        - use RAW, if not present -> do nothing
//  2) useRAWorHLT   - use RAW, if not present -> use HLT clusters
//  3) useHLT        - use HLT clusters, if not present -> do nothing
//  4) useHLTorRAW   - use HLT clusters, if not present -> use RAW
//
//  -> The current default is useHLTorRAW
//--------------------------------------------------------------------

///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// class for TPC reconstruction                                              //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include <TObject.h>
#include <TString.h>
#include <TObjString.h>
#include <TObjArray.h>
#include <TFile.h>

#include <AliLog.h>
#include <AliPID.h>
#include <AliESDpid.h>
#include <AliTPCPIDResponse.h>
#include "AliTPCReconstructor.h"
#include "AliRunLoader.h"
#include "AliRun.h"
#include "AliRawReader.h"
#include "AliTPCclusterer.h"
#include "AliTPCtracker.h"
#include "AliTPCParam.h"
#include "AliTPCParamSR.h"
#include "AliTPCcalibDB.h"
#include "AliTracker.h"
#include "AliMagF.h"
#include "TTreeStream.h"

ClassImp(AliTPCReconstructor)

Int_t    AliTPCReconstructor::fgStreamLevel     = 0;             // stream (debug) level
AliTPCAltroEmulator *  AliTPCReconstructor::fAltroEmulator=0;    // ALTRO emulator
TTreeSRedirector    *  AliTPCReconstructor::fgDebugStreamer=0;                          // NOTE -  AliTPCReconstructor is not an owner of the streamer
TString                AliTPCReconstructor::fgPIDRespnonsePath="$ALICE_PHYSICS/OADB/COMMON/PID/data/TPCPIDResponse.root";

TVectorD *  AliTPCReconstructor::fSystematicErrors=0;
TVectorD *  AliTPCReconstructor::fSystematicErrorClusters=0;
TVectorD *  AliTPCReconstructor::fgExtendedRoads=0;
TVectorD *  AliTPCReconstructor::fgPrimaryDCACut=0;
Double_t    AliTPCReconstructor::fgPrimaryZ2XCut = 0;
Double_t    AliTPCReconstructor::fgZOutSectorCut = 0;
Bool_t      AliTPCReconstructor::fgCompactClusters = kFALSE;
Bool_t      AliTPCReconstructor::fgCountMCTrackClusters = kFALSE;

AliTPCReconstructor::AliTPCReconstructor():
AliReconstructor(),
fClusterer(NULL),
fArrSplines(NULL)
{
  //
  // default constructor
  //
  //
  //
  AliTPCcalibDB * calib = AliTPCcalibDB::Instance();
  const AliMagF * field = (AliMagF*)TGeoGlobalMagField::Instance()->GetField();
  calib->SetExBField(field);
  AliTPCParam* param = GetTPCParam();
  if (!param) {
    AliWarning("Loading default TPC parameters !");
    param = new AliTPCParamSR;
  }
  fClusterer = new AliTPCclusterer(param);
}

AliTPCReconstructor::AliTPCReconstructor(const AliTPCReconstructor& /*rec*/):
AliReconstructor(),
fClusterer(NULL),
fArrSplines(NULL)
{
  //
  // Dummy copy constructor
  //
}

AliTPCReconstructor& AliTPCReconstructor::operator=(const AliTPCReconstructor&){
  //
  // dummy operator
  //
  return *this;
}

//_____________________________________________________________________________
AliTPCReconstructor::~AliTPCReconstructor()
{
  if (fClusterer)   delete fClusterer;
  delete fArrSplines;
  delete AliTPCcalibDB::Instance();
}

//_____________________________________________________________________________
void AliTPCReconstructor::Reconstruct(TTree* digitsTree, TTree* clustersTree) const {
  // single event local reconstruction
  // of TPC data
  fClusterer->SetTimeStamp(GetTimeStamp());
  fClusterer->SetInput(digitsTree);
  fClusterer->SetOutput(clustersTree);
  fClusterer->Digits2Clusters();
}

//_____________________________________________________________________________
void AliTPCReconstructor::Reconstruct(AliRawReader* rawReader, TTree* clustersTree) const {
  // single event local reconstruction
  // of TPC data starting from raw data
  fClusterer->SetTimeStamp(GetTimeStamp());
  fClusterer->SetOutput(clustersTree);
  fClusterer->Digits2Clusters(rawReader);
}

//_____________________________________________________________________________
AliTracker* AliTPCReconstructor::CreateTracker() const
{
// create a TPC tracker

  AliTPCParam* param = GetTPCParam();
  if (!param) {
    AliWarning("Loading default TPC parameters !");
    param = new AliTPCParamSR;
  }
  param->ReadGeoMatrices();

  AliTPCtracker* tracker = new AliTPCtracker(param);

  ParseOptions(tracker);

  return tracker;
}

//_____________________________________________________________________________
void AliTPCReconstructor::FillESD(TTree */*digitsTree*/, TTree */*clustersTree*/,
				  AliESDEvent* /*esd*/) const
{
// make PID
/*  Now done in AliESDpid
  Double_t parTPC[] = {50., 0.07, 5.};  // MIP nnormalized to channel 50 -MI
  AliTPCpidESD tpcPID(parTPC);
  tpcPID.MakePID(esd);
*/
}

//_____________________________________________________________________________
AliTPCParam* AliTPCReconstructor::GetTPCParam() const
{
// get the TPC parameters

  AliTPCParam* param = AliTPCcalibDB::Instance()->GetParameters();

  return param;
}

//_____________________________________________________________________________
void AliTPCReconstructor::SetSplinesFromOADB(const char* tmplt, AliESDpid *esdPID)
{
  //
  //  load splines from the OADB using 'template'
  //

  // only load splines if not already set
  if (!fArrSplines) {
    fArrSplines=new TObjArray(Int_t(AliPID::kSPECIES));
    fArrSplines->SetOwner();
    TString stemplate(tmplt);

    TFile f(GetPIDRespnonsePath());

    TObjArray *arrPidResponseMaster=0x0;

    if (f.IsOpen() && !f.IsZombie()){
      arrPidResponseMaster=dynamic_cast<TObjArray*>(f.Get("TPCPIDResponse"));
    }
    f.Close();

    if (!arrPidResponseMaster){
      AliError("PID response array not found, cannot assign proper splines");
      return;
    }

    for (Int_t ispec=0; ispec<AliPID::kSPECIES; ++ispec)
    {
      Int_t ispec2=ispec;
      if (ispec==Int_t(AliPID::kMuon)) ispec2=Int_t(AliPID::kPion);

      TString particle=AliPID::ParticleName(ispec2);
      particle.ToUpper();

      TString splineName;
      splineName.Form(stemplate.Data(),particle.Data());
      TObject *spline=arrPidResponseMaster->FindObject(splineName.Data());
      if (!spline) {
        AliError(Form("No spline found for '%s'", splineName.Data()));
        continue;
      };
      AliInfo(Form("Adding Response function %d:%s",ispec,splineName.Data()));
      fArrSplines->AddAt(spline->Clone(), ispec);
    }
    arrPidResponseMaster->Delete();
    delete arrPidResponseMaster;
    if (fArrSplines->GetEntries()!=Int_t(AliPID::kSPECIES)) {
      AliError("Splines not found for all species, cannot use proper PID");
      delete fArrSplines;
      fArrSplines=NULL;
      return;
    }
  }

  for (Int_t ispec=0; ispec<AliPID::kSPECIES; ++ispec)
  {
    esdPID->GetTPCResponse().SetResponseFunction( (AliPID::EParticleType)ispec, fArrSplines->UncheckedAt(ispec) );
  }

  esdPID->GetTPCResponse().SetUseDatabase(kTRUE);
}

//_____________________________________________________________________________
void AliTPCReconstructor::GetPidSettings(AliESDpid *esdPID)
{
  //
  // Get TPC pid splines. They should be written to the OCDB during the CPass
  // the splines themselves are owned by the OCDB object
  //

  // parse options
  TString allopt(GetOption());
  TObjArray *optArray=allopt.Tokenize(";");

  // defines whether the pid was set via a specific option in the rec.C
  Bool_t pidSetInOptions = kFALSE;

  for (Int_t iopt=0; iopt<optArray->GetEntriesFast(); ++iopt){
    if (!optArray->At(iopt)) continue;
    TString option(static_cast<TObjString*>(optArray->At(iopt))->GetString().Strip(TString::kBoth,' '));

    if (!option.BeginsWith("PID.")) continue;

    // remove 'PID.' identifyer
    option.Remove(0,4);

    // parse PID type
    if (option.BeginsWith("Static=")){
      option.Remove(0,option.First('=')+1);
      if (option.Contains("LHC13b2_fix_PID")) {
        esdPID->GetTPCResponse().SetBetheBlochParameters(0.0320981, 19.9768, 2.52666e-16, 2.72123, 6.08092);
        esdPID->GetTPCResponse().SetMip(53.4968);
        pidSetInOptions=kTRUE;
      }

    } else if (option.BeginsWith("OADB=")) {
      option.Remove(0,option.First('=')+1);
      AliInfo(Form("Setting splines From OADB using template: '%s'",option.Data()));
      SetSplinesFromOADB(option, esdPID);
      pidSetInOptions=kTRUE;
    } else if (option.BeginsWith("OCDB=")){
      option.Remove(0,option.First('=')+1);
      // not yet implemented
    }

  }

  delete optArray;

  //
  // Initialisation of BB parameters from the OCDB.
  // They are stored in the AliTPCParam
  //
  if (!pidSetInOptions) {
    AliTPCParam* param = AliTPCcalibDB::Instance()->GetParameters();
    if (param) {
      TVectorD *paramBB=param->GetBetheBlochParameters();
      const Float_t maxnSigmaRange = param->GetSigmaRangePIDinTracking();
      if (paramBB){
        esdPID->GetTPCResponse().SetBetheBlochParameters((*paramBB)(0),(*paramBB)(1),(*paramBB)(2),(*paramBB)(3),(*paramBB)(4));
        AliInfo(Form("Setting BB parameters from OCDB (AliTPCParam): %.2g, %.2g, %.2g, %.2g, %.2g",
                     (*paramBB)(0),(*paramBB)(1),(*paramBB)(2),(*paramBB)(3),(*paramBB)(4)));
        AliInfoF("Setting max sigma PID range to %.2f", maxnSigmaRange);
        esdPID->SetProbabilityRangeNsigma(maxnSigmaRange);
      } else {
        AliError("Couldn't get BB parameters from OCDB, the old default values will be used instead");
      }
    } else {
      AliError("Couldn't get TPC parameters");
    }
  }

/*
  AliTPCcalibDB * calib = AliTPCcalibDB::Instance();

  //Get pid splines array
  TObjArray *arrSplines=calib->GetPidResponse();
  if (!arrSplines) return;
  AliTPCPIDResponse &tpcPID=esdPID->GetTPCResponse();
  tpcPID.SetUseDatabase(kTRUE);

  // check if parametrisations are already set.
  // since this is uniq for one run, we don't have to reload them
  if (tpcPID.GetResponseFunction(AliPID::kPion)) return;

  // get the default object
  TObject *defaultPID=arrSplines->At(AliPID::kUnknown);

  // loop over all particle species and set the response functions
  for (Int_t ispec=0; ispec<AliPID::kUnknown; ++ispec){
    TObject *pidSpline=arrSplines->At(ispec);
    if (!pidSpline) pidSpline=defaultPID;
    tpcPID.SetResponseFunction((AliPID::EParticleType)ispec,pidSpline);
  }
 */
}

//_____________________________________________________________________________
void AliTPCReconstructor::ParseOptions( AliTPCtracker* tracker ) const
{
// parse options from rec.C and set in clusterer and tracker

  TString option = GetOption();

  Int_t useHLTClusters = 3;

  if (option.Contains("use")) {

    AliInfo(Form("Overide TPC RecoParam with option %s",option.Data()));

    if (option.Contains("useRAW")) {
      useHLTClusters = 1;
      if (option.Contains("useRAWorHLT"))
	useHLTClusters = 2;
    }
    else if (option.Contains("useHLT")) {
      useHLTClusters = 3;
      if (option.Contains("useHLTorRAW"))
	useHLTClusters = 4;
    }
  }
  else {
    const AliTPCRecoParam* param = GetRecoParam();
    useHLTClusters = param->GetUseHLTClusters();
  }

  AliInfo(Form("Usage of HLT clusters in TPC reconstruction : %d", useHLTClusters));

  fClusterer->SetUseHLTClusters(useHLTClusters);
  tracker->SetUseHLTClusters(useHLTClusters);

  return;
}

//_____________________________________________________________________________
void AliTPCReconstructor::SetSystematicErrorCluster( TVectorD *vec )
{
  // set clusters syst.errors which will override persistent data member from AliTPCRecoParam::fSystematicErrors
  fSystematicErrorClusters=vec;
  AliTPCRecoParam::SetSystematicErrorClusterCustom(vec);
}

//_____________________________________________________________________________
void AliTPCReconstructor::SetPrimaryDCACut( TVectorD *dcacut )
{
  // set clusters syst.errors which will override persistent data member from AliTPCRecoParam::fSystematicErrors
  fgPrimaryDCACut=dcacut;
  AliTPCRecoParam::SetPrimaryDCACut(dcacut);
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <fstream>
#include <ctype.h>

#include <metaObject.h>
#include <metaUtils.h>

int testMetaObject(int , char *[])
  {
  MetaObject tObj;

  tObj.InitializeEssential(3);
  tObj.FileName("testObject.txt");
  tObj.Comment("TestObject");
  tObj.ObjectTypeName("Object");
  tObj.ObjectSubTypeName("MinorObject");
  tObj.Position(0, 1);
  tObj.Position(1, 2);
  tObj.Position(2, 3);
  float orient[9];
  int i;
  for(i=0; i<9; i++)
    {
    orient[i] = 0;
    }
  orient[0] = 1;
  orient[5] = 1;
  orient[7] = 1;
  tObj.Orientation(orient);
  tObj.ElementSpacing(0, 1);
  tObj.ElementSpacing(1, 2);
  tObj.ElementSpacing(2, 1);

  // Add user's defined fields
  int myarray[3];
  myarray[0]=1;
  myarray[1]=2;
  myarray[2]=3;
  tObj.AddUserField("MyName", MET_STRING, strlen("Julien"), "Julien");
  tObj.AddUserField("MyArray", MET_INT_ARRAY,3,myarray);

  float myMatrix[4];
  for(i=0; i<4; i++)
    {
    myMatrix[i] = i;
    }
  tObj.AddUserField("MyMatrix", MET_FLOAT_MATRIX,2,myMatrix);

  tObj.PrintInfo();
  tObj.Write();

  tObj.Clear();
  tObj.ClearUserFields();

  tObj.AddUserField("MyName", MET_STRING);
  tObj.AddUserField("MyArray", MET_INT_ARRAY,3);
  tObj.AddUserField("MyMatrix", MET_FLOAT_MATRIX,2);

  std::cout << "Test Reading: ";
  tObj.Read();
  std::cout << "[PASSED]" << std::endl;

  tObj.PrintInfo();

  char* name = static_cast<char*>(tObj.GetUserField("MyName"));
  if(strcmp(name,"Julien"))
  {
    std::cout << "MyName: FAIL" << std::endl;
    return 1;
  }

  delete [] name;

  int* array = static_cast<int*>(tObj.GetUserField("MyArray"));

  for(i=0;i<3;i++)
  {
    if(array[i] != i+1)
    {
      std::cout << "MyArray: FAIL" << std::endl;
      return 1;
    }
  }

  delete [] array;

  float* matrix = static_cast<float*>(tObj.GetUserField("MyMatrix"));
  for(i=0; i<4; i++)
    {
    if(matrix[i] != i)
      {
      std::cout << "MyMatrix: FAIL" << std::endl;
      return 1;
      }
    }

  delete [] matrix;

  std::cout << "PASSED!" << std::endl;

  tObj.Clear();
  tObj.ClearUserFields();

  tObj.FileName("testObject2.txt");
  tObj.InitializeEssential(2);
  tObj.Position(0, 4);
  tObj.ElementSpacing(0,2);
  tObj.PrintInfo();
  tObj.Write();
  tObj.Clear();

  tObj.Read();
  tObj.PrintInfo();
  if(tObj.NDims() != 2)
    {
    std::cout << "NDims: FAIL" << std::endl;
    return 1;
    }
  else
    {
    std::cout << "NDims: PASS" << std::endl;
    }

  int zero = 0;
  if(tObj.Position(zero) != 4)
    {
    std::cout << "Position: FAIL :" << tObj.Position(zero) << std::endl;
    return 1;
    }
  else
    {
    std::cout << "Position: PASS" << std::endl;
    }

  if(tObj.ElementSpacing(zero) != 2)
    {
    std::cout << "ElementSpacing: FAIL: " << tObj.ElementSpacing(zero) << std::endl;
    return 1;
    }
  else
    {
    std::cout << "ElementSpacing: PASS" << std::endl;
    }

  // testing metaUtils

  char* inDataChar = new char[1];
  inDataChar[0]=1;
  char* outDataChar = new char[1];
  if(!MET_ValueToValue(MET_CHAR_ARRAY,inDataChar,0,MET_CHAR_ARRAY,outDataChar))
    {
    std::cout << "MET_ValueToValue: FAIL" << std::endl;
    return 1;
    }
  else
    {
    std::cout << "outDataChar = " << outDataChar[0] << std::endl;
    }

  delete [] inDataChar;
  delete [] outDataChar;

  unsigned char* inDataUChar = new unsigned char[1];
  inDataUChar[0]=1;
  unsigned char* outDataUChar = new unsigned char[1];
  if(!MET_ValueToValue(MET_UCHAR_ARRAY,inDataUChar,0,MET_UCHAR_ARRAY,outDataUChar))
    {
    std::cout << "MET_ValueToValue: FAIL" << std::endl;
    return 1;
    }
  else
    {
    std::cout << "outDataUChar = " << outDataUChar[0] << std::endl;
    }

  delete [] inDataUChar;
  delete [] outDataUChar;

  std::cout << "[DONE]" << std::endl;
  return 0;
  }

<commit_msg>ERR: bad char in output.<commit_after>#include <stdio.h>
#include <fstream>
#include <ctype.h>

#include <metaObject.h>
#include <metaUtils.h>
#include "itkNumericTraits.h"

int testMetaObject(int , char *[])
  {
  MetaObject tObj;

  tObj.InitializeEssential(3);
  tObj.FileName("testObject.txt");
  tObj.Comment("TestObject");
  tObj.ObjectTypeName("Object");
  tObj.ObjectSubTypeName("MinorObject");
  tObj.Position(0, 1);
  tObj.Position(1, 2);
  tObj.Position(2, 3);
  float orient[9];
  int i;
  for(i=0; i<9; i++)
    {
    orient[i] = 0;
    }
  orient[0] = 1;
  orient[5] = 1;
  orient[7] = 1;
  tObj.Orientation(orient);
  tObj.ElementSpacing(0, 1);
  tObj.ElementSpacing(1, 2);
  tObj.ElementSpacing(2, 1);

  // Add user's defined fields
  int myarray[3];
  myarray[0]=1;
  myarray[1]=2;
  myarray[2]=3;
  tObj.AddUserField("MyName", MET_STRING, strlen("Julien"), "Julien");
  tObj.AddUserField("MyArray", MET_INT_ARRAY,3,myarray);

  float myMatrix[4];
  for(i=0; i<4; i++)
    {
    myMatrix[i] = i;
    }
  tObj.AddUserField("MyMatrix", MET_FLOAT_MATRIX,2,myMatrix);

  tObj.PrintInfo();
  tObj.Write();

  tObj.Clear();
  tObj.ClearUserFields();

  tObj.AddUserField("MyName", MET_STRING);
  tObj.AddUserField("MyArray", MET_INT_ARRAY,3);
  tObj.AddUserField("MyMatrix", MET_FLOAT_MATRIX,2);

  std::cout << "Test Reading: ";
  tObj.Read();
  std::cout << "[PASSED]" << std::endl;

  tObj.PrintInfo();

  char* name = static_cast<char*>(tObj.GetUserField("MyName"));
  if(strcmp(name,"Julien"))
  {
    std::cout << "MyName: FAIL" << std::endl;
    return 1;
  }

  delete [] name;

  int* array = static_cast<int*>(tObj.GetUserField("MyArray"));

  for(i=0;i<3;i++)
  {
    if(array[i] != i+1)
    {
      std::cout << "MyArray: FAIL" << std::endl;
      return 1;
    }
  }

  delete [] array;

  float* matrix = static_cast<float*>(tObj.GetUserField("MyMatrix"));
  for(i=0; i<4; i++)
    {
    if(matrix[i] != i)
      {
      std::cout << "MyMatrix: FAIL" << std::endl;
      return 1;
      }
    }

  delete [] matrix;

  std::cout << "PASSED!" << std::endl;

  tObj.Clear();
  tObj.ClearUserFields();

  tObj.FileName("testObject2.txt");
  tObj.InitializeEssential(2);
  tObj.Position(0, 4);
  tObj.ElementSpacing(0,2);
  tObj.PrintInfo();
  tObj.Write();
  tObj.Clear();

  tObj.Read();
  tObj.PrintInfo();
  if(tObj.NDims() != 2)
    {
    std::cout << "NDims: FAIL" << std::endl;
    return 1;
    }
  else
    {
    std::cout << "NDims: PASS" << std::endl;
    }

  int zero = 0;
  if(tObj.Position(zero) != 4)
    {
    std::cout << "Position: FAIL :" << tObj.Position(zero) << std::endl;
    return 1;
    }
  else
    {
    std::cout << "Position: PASS" << std::endl;
    }

  if(tObj.ElementSpacing(zero) != 2)
    {
    std::cout << "ElementSpacing: FAIL: " << tObj.ElementSpacing(zero) << std::endl;
    return 1;
    }
  else
    {
    std::cout << "ElementSpacing: PASS" << std::endl;
    }

  // testing metaUtils

  char* inDataChar = new char[1];
  inDataChar[0]=1;
  char* outDataChar = new char[1];
  if(!MET_ValueToValue(MET_CHAR_ARRAY,inDataChar,0,MET_CHAR_ARRAY,outDataChar))
    {
    std::cout << "MET_ValueToValue: FAIL" << std::endl;
    return 1;
    }
  else
    {
    std::cout << "outDataChar = " << static_cast<itk::NumericTraits<char>::PrintType>(outDataChar[0]) << std::endl;
    }

  delete [] inDataChar;
  delete [] outDataChar;

  unsigned char* inDataUChar = new unsigned char[1];
  inDataUChar[0]=1;
  unsigned char* outDataUChar = new unsigned char[1];
  if(!MET_ValueToValue(MET_UCHAR_ARRAY,inDataUChar,0,MET_UCHAR_ARRAY,outDataUChar))
    {
    std::cout << "MET_ValueToValue: FAIL" << std::endl;
    return 1;
    }
  else
    {
    std::cout << "outDataUChar = " << static_cast<itk::NumericTraits<char>::PrintType>(outDataUChar[0]) << std::endl;
    }

  delete [] inDataUChar;
  delete [] outDataUChar;

  std::cout << "[DONE]" << std::endl;
  return 0;
  }

<|endoftext|>