Skip to content

Commit 8e49d8d

Browse files
committed
- warn if multiple fit items are defined for the same parameter
1 parent a6a63fa commit 8e49d8d

2 files changed

Lines changed: 69 additions & 3 deletions

File tree

copasi/parameterFitting/CFitProblem.cpp

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2019 - 2025 by Pedro Mendes, Rector and Visitors of the
1+
// Copyright (C) 2019 - 2026 by Pedro Mendes, Rector and Visitors of the
22
// University of Virginia, University of Heidelberg, and University
33
// of Connecticut School of Medicine.
44
// All rights reserved.
@@ -927,7 +927,6 @@ CFitConstraint & CFitProblem::addFitConstraint(const CRegisteredCommonName & obj
927927
return *pItem;
928928
}
929929

930-
931930
bool CFitProblem::calculate()
932931
{
933932
sCounter Counters;
@@ -1795,6 +1794,12 @@ bool CFitProblem::calcCov(const CMatrix< C_FLOAT64 >& fim, CMatrix< C_FLOAT64 >&
17951794
corr = std::numeric_limits<C_FLOAT64>::quiet_NaN();
17961795
sd = std::numeric_limits<C_FLOAT64>::quiet_NaN();
17971796
CCopasiMessage(CCopasiMessage::WARNING, MCFitting + 12);
1797+
1798+
// verify that we dont have duplicates in the list of
1799+
// fit items, as they are a common cause
1800+
bool logWarnings = true;
1801+
checkForDuplicateFitItems(logWarnings);
1802+
17981803
return false;
17991804
}
18001805

@@ -2184,6 +2189,56 @@ bool CFitProblem::calculateStatistics(const C_FLOAT64 & factor,
21842189
return true;
21852190
}
21862191

2192+
bool CFitProblem::checkForDuplicateFitItems(bool logWarnings) const
2193+
{
2194+
if (!mpOptItems)
2195+
return false;
2196+
2197+
// map counting how many time a specific
2198+
// fit item (and experiment combination) appears in the list of fit items
2199+
std::map< std::string, size_t > FitItemNames;
2200+
2201+
// map counting for each object underlying a fit item
2202+
// how many times a combination of experiments appears in the list of
2203+
// fit items
2204+
std::map< std::string, std::map<std::string, size_t> > ObjectsWithExperiments;
2205+
2206+
bool hasDuplicates = false;
2207+
for (auto * optItem : *mpOptItems)
2208+
{
2209+
auto * item = static_cast< CFitItem * >(optItem);
2210+
auto * obj = item->getItemObject();
2211+
std::string name = obj != NULL ? obj->getObjectDisplayName() : "Not found";
2212+
auto experiments = item->getExperiments();
2213+
if (!experiments.empty())
2214+
name += " {" + experiments + "}";
2215+
2216+
if (FitItemNames.find(name) == FitItemNames.end())
2217+
{
2218+
FitItemNames[name] = 1;
2219+
}
2220+
else
2221+
{
2222+
hasDuplicates = true;
2223+
FitItemNames[name] += 1;
2224+
}
2225+
}
2226+
2227+
if (hasDuplicates && logWarnings)
2228+
{
2229+
std::stringstream ss;
2230+
ss << "Duplicate fit items detected. This prevents calculation of summary statistics." << std::endl;
2231+
for (const auto & pair : FitItemNames)
2232+
{
2233+
if (pair.second > 1)
2234+
ss << "Fit item '" << pair.first << "' appears " << pair.second << " times." << std::endl;
2235+
}
2236+
2237+
CCopasiMessage(CCopasiMessage::WARNING, "%s", ss.str().c_str());
2238+
}
2239+
return hasDuplicates;
2240+
}
2241+
21872242
const C_FLOAT64 & CFitProblem::getRMS() const
21882243
{
21892244
return mRMS;

copasi/parameterFitting/CFitProblem.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2019 - 2025 by Pedro Mendes, Rector and Visitors of the
1+
// Copyright (C) 2019 - 2026 by Pedro Mendes, Rector and Visitors of the
22
// University of Virginia, University of Heidelberg, and University
33
// of Connecticut School of Medicine.
44
// All rights reserved.
@@ -187,6 +187,17 @@ class CFitProblem : public COptProblem
187187
virtual bool calculateStatistics(const C_FLOAT64 & factor = 1.0e-003,
188188
const C_FLOAT64 & resolution = 1.0e-009) override;
189189

190+
/**
191+
* @brief verifies that ther are no duplicate fit items in the problem.
192+
*
193+
* Note that this function does not log warnings about duplicates if logWarnings
194+
* is false, so it may return true without logging a warning if logWarnings is false.
195+
*
196+
* @param logWarnings boolean, indicating whether to log warnings about duplicats
197+
* @return true if duplicates are found, false otherwise.
198+
*/
199+
bool checkForDuplicateFitItems(bool logWarnings) const;
200+
190201
/**
191202
* Retrieve the root mean square of the objective value.
192203
* @return const C_FLOAT64 & RMS

0 commit comments

Comments
 (0)