<commit_before>// Copyright (C) 2010 - 2015 by <NAME>, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

// Copyright (C) 2008 - 2009 by <NAME>, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

// Copyright (C) 2005 - 2007 by <NAME>, Virginia Tech Intellectual
// Properties, Inc. and EML Research, gGmbH.
// All rights reserved.

#include "CQExperimentData.h"

#include <QtCore/QVariant>
#include <QtCore/QTimer>

#include <algorithm>
#include <limits>
#include <cmath>
#include <QtCore/QSignalMapper>
#include <QtGui/QComboBox>

#include "copasi.h"

#include "CCopasiSelectionDialog.h"
#include "CopasiFileDialog.h"
#include "CQValidator.h"
#include "qtUtilities.h"
#include "CQMessageBox.h"
#include "resourcesUI/CQIconResource.h"
#include "CQPushButtonDelegate.h"
#include "CQComboDelegate.h"

#include "parameterFitting/CExperimentSet.h"
#include "parameterFitting/CExperiment.h"
#include "parameterFitting/CExperimentFileInfo.h"
#include "parameterFitting/CExperimentObjectMap.h"

#include "report/CKeyFactory.h"
#include "utilities/CDirEntry.h"
#include "utilities/utility.h"
#include "copasi/report/CCopasiRootContainer.h"
#include "commandline/CLocaleString.h"

#define COL_NAME 0
#define COL_TYPE 1
#define COL_TYPE_HIDDEN 2
#define COL_BTN 3
#define COL_OBJECT 4
#define COL_OBJECT_HIDDEN 5
#define COL_SCALE 6

#define InvalidIndex std::numeric_limits< unsigned C_INT32 >::max()

/*
 *  Constructs a CQExperimentData as a child of 'parent', with the
 *  name 'name' and widget flags set to 'f'.
 *
 *  The dialog will by default be modeless, unless you set 'modal' to
 *  true to construct a modal dialog.
 */
CQExperimentData::CQExperimentData(QWidget* parent, const char* name, bool modal, Qt::WindowFlags fl):
  QDialog(parent, fl),
  mOldWeightMethod(),
  mpValidatorHeader(NULL),
  mpValidatorLast(NULL),
  mpExperiment(NULL),
  mpFileInfo(NULL),
  mpExperimentSet(NULL),
  mpExperimentSetCopy(NULL),
  mKeyMap(),
  mFileMap(),
  mpValidatorFirst(),
  mShown(-1),
  mpValidatorName(NULL),
  mCrossValidation(false),
  mShowError(true),
  mpDataModel(NULL),
  mpComboDelegate(NULL),
  mTypeItems(),
  mTypeWithoutTimeItems(),
  mModelObjectRow(-1)
{
  setObjectName(QString::fromUtf8(name));
  setModal(modal);
  setupUi(this);

  init();
}

/*
 *  Destroys the object and frees any allocated resources
 */
CQExperimentData::~CQExperimentData()
{
  destroy();
  // no need to delete child widgets, Qt does it all for us
}

class CQExperimentDataValidator: public CQValidatorNotEmpty
{
public:
  enum Type
  {
    Name = 0,
    FirstRow,
    LastRow,
    HeaderRow
  };

  // Operations
public:
  CQExperimentDataValidator(QLineEdit * parent,
                            const char * name,
                            CQExperimentData * pContext,
                            const Type & type):
    CQValidatorNotEmpty(parent, name),
    mpIntValidator(new QIntValidator(1, std::numeric_limits< int >::max(), parent)),
    mpContext(pContext),
    mType(type)
  {}

  virtual State validate(QString & input, int & pos) const
  {
    if (mpContext->mShown == -1) return Acceptable;

    if (mType == Name)
      {
        if (input == "All")
          {
            setColor(Invalid);
            return Intermediate;
          }

        if (mLastAccepted != input &&
            mpContext->mpExperimentSetCopy->getParameter(TO_UTF8(input)))
          {
            setColor(Invalid);
            return Intermediate;
          }
      }
    else
      {
        if (mpIntValidator->validate(input, pos) != Acceptable)
          {
            setColor(Invalid);
            return Intermediate;
          }

        size_t First, Last;

        switch (mType)
          {
            case FirstRow:

              if (!mpContext->mpFileInfo->validateFirst(mpContext->mShown, input.toULong()))
                {
                  size_t NewFirst = input.toULong();

                  mpContext->mpFileInfo->getFirstUnusedSection(First, Last);

                  while (NewFirst > Last)
                    mpContext->mpFileInfo->getNextUnusedSection(First, Last);

                  if (First <= NewFirst && NewFirst <= Last)
                    {
                      if (First > mpContext->mpExperiment->getLastRow())
                        {
                          mpContext->mpExperiment->setLastRow((unsigned C_INT32) Last);
                          mpContext->mpExperiment->setFirstRow((unsigned C_INT32) First);
                        }
                      else
                        {
                          mpContext->mpExperiment->setFirstRow((unsigned C_INT32) First);
                          mpContext->mpExperiment->setLastRow((unsigned C_INT32) Last);
                        }

                      mpContext->syncExperiments();

                      mpContext->mpEditFirst->setText(QString::number(First));
                      mpContext->mpEditLast->setText(QString::number(Last));
                      mpContext->mpValidatorLast->revalidate();

                      return validate(input, pos);
                    }

                  setColor(Invalid);
                  return Intermediate;
                }

              mpContext->mpExperiment->setFirstRow(input.toULong());
              mpContext->mpFileInfo->sync();
              mpContext->mpBtnExperimentAdd->setEnabled(mpContext->mpFileInfo->getFirstUnusedSection(First, Last));
              break;

            case LastRow:

              if (!mpContext->mpFileInfo->validateLast(mpContext->mShown, input.toULong()))
                {
                  setColor(Invalid);
                  return Intermediate;
                }

              mpContext->mpExperiment->setLastRow(input.toULong());
              mpContext->mpFileInfo->sync();
              mpContext->mpBtnExperimentAdd->setEnabled(mpContext->mpFileInfo->getFirstUnusedSection(First, Last));
              break;

            case HeaderRow:

              if (!mpContext->mpFileInfo->validateHeader(mpContext->mShown, input.toULong()))
                {
                  setColor(Invalid);
                  return Intermediate;
                }

              mpContext->mpExperiment->setHeaderRow(input.toULong());
              break;

            default:
              break;
          }
      }

    return CQValidatorNotEmpty::validate(input, pos);
  }

  // virtual State revalidate();

  // virtual void forceAcceptance(const QString & input) const;

  // virtual void saved() const;

  // Attributes
private:
  QIntValidator * mpIntValidator;

  CQExperimentData * mpContext;

  Type mType;
};

void CQExperimentData::slotRevert()
{
  load(mpExperimentSet, mpDataModel);
}

void CQExperimentData::slotFirst()
{
  qWarning("CQExperimentData::slotFirst(): Not implemented yet");

  size_t Row = C_INVALID_INDEX;

  if (mpEditFirst->text() != "")
    Row = mpEditFirst->text().toULong();

  if (Row == C_INVALID_INDEX)
    {
      //  Row = find first non used row in file
    }

  // display dialog with table showing file section of First row

  // if accept
  //  set mpEditFirst
}

void CQExperimentData::slotLast()
{
  size_t Row = C_INVALID_INDEX;

  if (mpEditLast->text() != "")
    Row = mpEditLast->text().toULong();

  if (Row == C_INVALID_INDEX && mpEditFirst->text() != "")
    Row = mpEditFirst->text().toULong();

  // display dialog with table showing file section of First row

  // if accept
  //  set mpEditFirst
  // if last row
  //  display table showing file section of last row inexperiment
  // else if  first
  //  display table showing file section of  first row in file
  // else
  //  display table showing file section of last non used row in file

  // if accept
  //  set mpEditLast
}

void CQExperimentData::slotHeader()
{
  qWarning("CQExperimentData::slotHeader(): Not implemented yet");

  // if header row
  //  display table showing file section of header row inexperiment
  // if first row
  //  display table showing file section of first row inexperiment
  // else if last row
  //  display table showing file section of last row inexperiment
  // else
  //  display table showing file section of  first non used row in file

  // if accept
  //  set mpEditHeader
  //  check mpCheckHeader
  // else
  // uncheck mpCheckHeader
}

void CQExperimentData::slotExprimentType(bool isSteadyState)
{
  if (!mpExperiment) return;

  if (isSteadyState)
    {
      mpBtnSteadystate->setFocus();
      mpExperiment->setExperimentType(CCopasiTask::steadyState);
    }
  else
    {
      mpBtnTimeCourse->setFocus();
      mpExperiment->setExperimentType(CCopasiTask::timeCourse);
    }

  saveTable(mpExperiment);

  // Undo the changes so that copy from and to work.
  if (isSteadyState)
    {
      mpExperiment->setExperimentType(CCopasiTask::timeCourse);
    }
  else
    {
      mpExperiment->setExperimentType(CCopasiTask::steadyState);
    }

  size_t i, imax = mpTable->rowCount();

  if (isSteadyState)
    for (i = 0; i < imax; i++)
      {
        CExperiment::Type Type = static_cast< CExperiment::Type >(mpTable->item((int) i, COL_TYPE_HIDDEN)->data(Qt::DisplayRole).toInt());

        if (Type == CExperiment::time)
          mpExperiment->getObjectMap().setRole(i, CExperiment::ignore);
      };

  loadTable(mpExperiment, true);
  return;
}

void CQExperimentData::slotCheckTab(bool checked)
{
  mpEditSeparator->setEnabled(!checked);

  if (checked)
    mpCheckTab->setFocus();
  else
    mpEditSeparator->setFocus();

  if (mpEditSeparator->isEnabled() &&
      mpEditSeparator->text().isEmpty())
    mpEditSeparator->setText(",");
  else
    slotSeparator();
}

void CQExperimentData::slotCheckHeader(bool checked)
{
  mpEditHeader->setEnabled(checked);

  if (!checked)
    {
      this->mpEditHeader->setText("");
    }
}

void CQExperimentData::slotExperimentAdd()
{
  mShowError = false;

  CExperiment Experiment(mpDataModel);
  CExperiment * pExperiment = mpExperimentSetCopy->addExperiment(Experiment);

  size_t First, Last;
  mpFileInfo->getFirstUnusedSection(First, Last);
  pExperiment->setFirstRow((unsigned C_INT32) First);
  pExperiment->setLastRow((unsigned C_INT32) Last);
  pExperiment->setHeaderRow((unsigned C_INT32) First);
  pExperiment->setFileName(mpFileInfo->getFileName());

  pExperiment->setNormalizeWeightsPerExperiment(false);

  pExperiment->setNumColumns((unsigned C_INT32) pExperiment->guessColumnNumber());
  mpFileInfo->sync();

  mpBoxExperiment->addItem(FROM_UTF8(pExperiment->getObjectName()));
  mpBoxExperiment->setCurrentRow(mpBoxExperiment->count() - 1);

  syncExperiments();
  mpBtnExperimentAdd->setEnabled(mpFileInfo->getFirstUnusedSection(First, Last));

  mShowError = true;
}

void CQExperimentData::slotExperimentChanged(QListWidgetItem * pCurrentItem, QListWidgetItem * /* pPreviousItem */)
{
  std::string Name;<commit_msg>The default for 'Normalize Weights per Experiment' is now consistently set to false which id the original behavior.<commit_after>// Copyright (C) 2010 - 2015 by <NAME>, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

// Copyright (C) 2008 - 2009 by <NAME>, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

// Copyright (C) 2005 - 2007 by <NAME>, Virginia Tech Intellectual
// Properties, Inc. and EML Research, gGmbH.
// All rights reserved.

#include "CQExperimentData.h"

#include <QtCore/QVariant>
#include <QtCore/QTimer>

#include <algorithm>
#include <limits>
#include <cmath>
#include <QtCore/QSignalMapper>
#include <QtGui/QComboBox>

#include "copasi.h"

#include "CCopasiSelectionDialog.h"
#include "CopasiFileDialog.h"
#include "CQValidator.h"
#include "qtUtilities.h"
#include "CQMessageBox.h"
#include "resourcesUI/CQIconResource.h"
#include "CQPushButtonDelegate.h"
#include "CQComboDelegate.h"

#include "parameterFitting/CExperimentSet.h"
#include "parameterFitting/CExperiment.h"
#include "parameterFitting/CExperimentFileInfo.h"
#include "parameterFitting/CExperimentObjectMap.h"

#include "report/CKeyFactory.h"
#include "utilities/CDirEntry.h"
#include "utilities/utility.h"
#include "copasi/report/CCopasiRootContainer.h"
#include "commandline/CLocaleString.h"

#define COL_NAME 0
#define COL_TYPE 1
#define COL_TYPE_HIDDEN 2
#define COL_BTN 3
#define COL_OBJECT 4
#define COL_OBJECT_HIDDEN 5
#define COL_SCALE 6

#define InvalidIndex std::numeric_limits< unsigned C_INT32 >::max()

/*
 *  Constructs a CQExperimentData as a child of 'parent', with the
 *  name 'name' and widget flags set to 'f'.
 *
 *  The dialog will by default be modeless, unless you set 'modal' to
 *  true to construct a modal dialog.
 */
CQExperimentData::CQExperimentData(QWidget* parent, const char* name, bool modal, Qt::WindowFlags fl):
  QDialog(parent, fl),
  mOldWeightMethod(),
  mpValidatorHeader(NULL),
  mpValidatorLast(NULL),
  mpExperiment(NULL),
  mpFileInfo(NULL),
  mpExperimentSet(NULL),
  mpExperimentSetCopy(NULL),
  mKeyMap(),
  mFileMap(),
  mpValidatorFirst(),
  mShown(-1),
  mpValidatorName(NULL),
  mCrossValidation(false),
  mShowError(true),
  mpDataModel(NULL),
  mpComboDelegate(NULL),
  mTypeItems(),
  mTypeWithoutTimeItems(),
  mModelObjectRow(-1)
{
  setObjectName(QString::fromUtf8(name));
  setModal(modal);
  setupUi(this);

  init();
}

/*
 *  Destroys the object and frees any allocated resources
 */
CQExperimentData::~CQExperimentData()
{
  destroy();
  // no need to delete child widgets, Qt does it all for us
}

class CQExperimentDataValidator: public CQValidatorNotEmpty
{
public:
  enum Type
  {
    Name = 0,
    FirstRow,
    LastRow,
    HeaderRow
  };

  // Operations
public:
  CQExperimentDataValidator(QLineEdit * parent,
                            const char * name,
                            CQExperimentData * pContext,
                            const Type & type):
    CQValidatorNotEmpty(parent, name),
    mpIntValidator(new QIntValidator(1, std::numeric_limits< int >::max(), parent)),
    mpContext(pContext),
    mType(type)
  {}

  virtual State validate(QString & input, int & pos) const
  {
    if (mpContext->mShown == -1) return Acceptable;

    if (mType == Name)
      {
        if (input == "All")
          {
            setColor(Invalid);
            return Intermediate;
          }

        if (mLastAccepted != input &&
            mpContext->mpExperimentSetCopy->getParameter(TO_UTF8(input)))
          {
            setColor(Invalid);
            return Intermediate;
          }
      }
    else
      {
        if (mpIntValidator->validate(input, pos) != Acceptable)
          {
            setColor(Invalid);
            return Intermediate;
          }

        size_t First, Last;

        switch (mType)
          {
            case FirstRow:

              if (!mpContext->mpFileInfo->validateFirst(mpContext->mShown, input.toULong()))
                {
                  size_t NewFirst = input.toULong();

                  mpContext->mpFileInfo->getFirstUnusedSection(First, Last);

                  while (NewFirst > Last)
                    mpContext->mpFileInfo->getNextUnusedSection(First, Last);

                  if (First <= NewFirst && NewFirst <= Last)
                    {
                      if (First > mpContext->mpExperiment->getLastRow())
                        {
                          mpContext->mpExperiment->setLastRow((unsigned C_INT32) Last);
                          mpContext->mpExperiment->setFirstRow((unsigned C_INT32) First);
                        }
                      else
                        {
                          mpContext->mpExperiment->setFirstRow((unsigned C_INT32) First);
                          mpContext->mpExperiment->setLastRow((unsigned C_INT32) Last);
                        }

                      mpContext->syncExperiments();

                      mpContext->mpEditFirst->setText(QString::number(First));
                      mpContext->mpEditLast->setText(QString::number(Last));
                      mpContext->mpValidatorLast->revalidate();

                      return validate(input, pos);
                    }

                  setColor(Invalid);
                  return Intermediate;
                }

              mpContext->mpExperiment->setFirstRow(input.toULong());
              mpContext->mpFileInfo->sync();
              mpContext->mpBtnExperimentAdd->setEnabled(mpContext->mpFileInfo->getFirstUnusedSection(First, Last));
              break;

            case LastRow:

              if (!mpContext->mpFileInfo->validateLast(mpContext->mShown, input.toULong()))
                {
                  setColor(Invalid);
                  return Intermediate;
                }

              mpContext->mpExperiment->setLastRow(input.toULong());
              mpContext->mpFileInfo->sync();
              mpContext->mpBtnExperimentAdd->setEnabled(mpContext->mpFileInfo->getFirstUnusedSection(First, Last));
              break;

            case HeaderRow:

              if (!mpContext->mpFileInfo->validateHeader(mpContext->mShown, input.toULong()))
                {
                  setColor(Invalid);
                  return Intermediate;
                }

              mpContext->mpExperiment->setHeaderRow(input.toULong());
              break;

            default:
              break;
          }
      }

    return CQValidatorNotEmpty::validate(input, pos);
  }

  // virtual State revalidate();

  // virtual void forceAcceptance(const QString & input) const;

  // virtual void saved() const;

  // Attributes
private:
  QIntValidator * mpIntValidator;

  CQExperimentData * mpContext;

  Type mType;
};

void CQExperimentData::slotRevert()
{
  load(mpExperimentSet, mpDataModel);
}

void CQExperimentData::slotFirst()
{
  qWarning("CQExperimentData::slotFirst(): Not implemented yet");

  size_t Row = C_INVALID_INDEX;

  if (mpEditFirst->text() != "")
    Row = mpEditFirst->text().toULong();

  if (Row == C_INVALID_INDEX)
    {
      //  Row = find first non used row in file
    }

  // display dialog with table showing file section of First row

  // if accept
  //  set mpEditFirst
}

void CQExperimentData::slotLast()
{
  size_t Row = C_INVALID_INDEX;

  if (mpEditLast->text() != "")
    Row = mpEditLast->text().toULong();

  if (Row == C_INVALID_INDEX && mpEditFirst->text() != "")
    Row = mpEditFirst->text().toULong();

  // display dialog with table showing file section of First row

  // if accept
  //  set mpEditFirst
  // if last row
  //  display table showing file section of last row inexperiment
  // else if  first
  //  display table showing file section of  first row in file
  // else
  //  display table showing file section of last non used row in file

  // if accept
  //  set mpEditLast
}

void CQExperimentData::slotHeader()
{
  qWarning("CQExperimentData::slotHeader(): Not implemented yet");

  // if header row
  //  display table showing file section of header row inexperiment
  // if first row
  //  display table showing file section of first row inexperiment
  // else if last row
  //  display table showing file section of last row inexperiment
  // else
  //  display table showing file section of  first non used row in file

  // if accept
  //  set mpEditHeader
  //  check mpCheckHeader
  // else
  // uncheck mpCheckHeader
}

void CQExperimentData::slotExprimentType(bool isSteadyState)
{
  if (!mpExperiment) return;

  if (isSteadyState)
    {
      mpBtnSteadystate->setFocus();
      mpExperiment->setExperimentType(CCopasiTask::steadyState);
    }
  else
    {
      mpBtnTimeCourse->setFocus();
      mpExperiment->setExperimentType(CCopasiTask::timeCourse);
    }

  saveTable(mpExperiment);

  // Undo the changes so that copy from and to work.
  if (isSteadyState)
    {
      mpExperiment->setExperimentType(CCopasiTask::timeCourse);
    }
  else
    {
      mpExperiment->setExperimentType(CCopasiTask::steadyState);
    }

  size_t i, imax = mpTable->rowCount();

  if (isSteadyState)
    for (i = 0; i < imax; i++)
      {
        CExperiment::Type Type = static_cast< CExperiment::Type >(mpTable->item((int) i, COL_TYPE_HIDDEN)->data(Qt::DisplayRole).toInt());

        if (Type == CExperiment::time)
          mpExperiment->getObjectMap().setRole(i, CExperiment::ignore);
      };

  loadTable(mpExperiment, true);
  return;
}

void CQExperimentData::slotCheckTab(bool checked)
{
  mpEditSeparator->setEnabled(!checked);

  if (checked)
    mpCheckTab->setFocus();
  else
    mpEditSeparator->setFocus();

  if (mpEditSeparator->isEnabled() &&
      mpEditSeparator->text().isEmpty())
    mpEditSeparator->setText(",");
  else
    slotSeparator();
}

void CQExperimentData::slotCheckHeader(bool checked)
{
  mpEditHeader->setEnabled(checked);

  if (!checked)
    {
      this->mpEditHeader->setText("");
    }
}

void CQExperimentData::slotExperimentAdd()
{
  mShowError = false;

  CExperiment Experiment(mpDataModel);
  CExperiment * pExperiment = mpExperimentSetCopy->addExperiment(Experiment);

  size_t First, Last;
  mpFileInfo->getFirstUnusedSection(First, Last);
  pExperiment->setFirstRow((unsigned C_INT32) First);
  pExperiment->setLastRow((unsigned C_INT32) Last);
  pExperiment->setHeaderRow((unsigned C_INT32) First);
  pExperiment->setFileName(mpFileInfo->getFileName());

  pExperiment->setNormalizeWeightsPerExperiment(true);

  pExperiment->setNumColumns((unsigned C_INT32) pExperiment->guessColumnNumber());
  mpFileInfo->sync();

  mpBoxExperiment->addItem(FROM_UTF8(pExperiment->getObjectName()));
  mpBoxExperiment->setCurrentRow(mpBoxExperiment->count() - 1);

  syncExperiments();
  mpBtnExperimentAdd->setEnabled(mpFileInfo->getFirstUnusedSection(First, Last));

  mShowError = true;
}

void CQExperimentData::slotExperimentChanged(QListWidgetItem * pCurrentItem, QListWidgetItem * /* pPreviousItem */)
{
  std::string Name;
{'fraction_non_alphanumeric': 0.1135613900311808, 'fraction_numerical': 0.00533236928916806, 'mean_word_length': 2.738807230951174, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 221, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3720143', 'n_tokens_mistral': 6797, 'n_tokens_neox': 6526, 'n_words': 1440}