From aa8204c60a5b9c95d7901b879e3c347c71cfdf7c Mon Sep 17 00:00:00 2001 From: SoftwareLiteracy Date: Fri, 5 Apr 2024 16:03:34 -0400 Subject: [PATCH] v1.15.4 cppEDM: Move SMap NaN warning to verbose. Improve ComputeError NaN handling. --- .Rbuildignore | 1 + .gitignore | 2 ++ DESCRIPTION | 4 ++-- NEWS.md | 3 ++- src/cppEDM/src/API.cc | 18 +++++++-------- src/cppEDM/src/Common.cc | 44 ++++++++++++++++--------------------- src/cppEDM/src/Parameter.cc | 2 +- 7 files changed, 35 insertions(+), 39 deletions(-) diff --git a/.Rbuildignore b/.Rbuildignore index 531bf97..b0ab1e6 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -8,3 +8,4 @@ ^Meta$ ^vignettes/rEDM-tutorial_cache$ ^vignettes/vignette_figs/ +^CITATION.cff diff --git a/.gitignore b/.gitignore index cff0354..a5b95d6 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ Meta +/doc/ +/Meta/ diff --git a/DESCRIPTION b/DESCRIPTION index 4521119..39012af 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,8 +1,8 @@ Package: rEDM Type: Package Title: Empirical Dynamic Modeling ('EDM') -Version: 1.15.3 -Date: 2024-01-07 +Version: 1.15.4 +Date: 2024-04-05 Authors@R: c( person("Joseph", "Park", role = c("aut", "cre"), email = "JosephPark@IEEE.org", comment = c(ORCID = "0000-0001-5411-1409")), diff --git a/NEWS.md b/NEWS.md index 1e0e056..356af02 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,6 @@ #### rEDM NEWS -2023-10-27 version 1.15.1 +2024-04-05 version 1.15.4 --- @@ -21,6 +21,7 @@ - Version 1.15.1 `ignoreNan` added in `PredictNonlinear()`. Replace unicode in pLot labels with mathplot expression. cppEDM initialize `nanFound` in DataFrame.h for UBSAN. Sync with cppEDM 1.15.1. - Version 1.15.2 Allow `columns` names with spaces. If the `columns` argument is a string use the "," delimiter to separate names. Remove `SMap` warning for disjoint library. - Version 1.15.3 Allow `columns` and `target` names with spaces in CCM. +- Version 1.15.4 Move `SMap` warning for NaN into `verbose` mode. cppEDM `ComputeError` NaN removal improved, require more than 5 observation : prediction pairs. ##### Version 1.14 - cppEDM core added `generateLibrary` parameter to `Simplex()` and `SMap()`. If `TRUE` the state-space library has newly generated points added. Not available due to Rcpp 20 parameter limit. diff --git a/src/cppEDM/src/API.cc b/src/cppEDM/src/API.cc index d46d2bc..3c3770a 100644 --- a/src/cppEDM/src/API.cc +++ b/src/cppEDM/src/API.cc @@ -458,7 +458,7 @@ SMapValues SMap( DataFrame< double > & DF, } DF.FindNan( nanColsCheck ); // If nan, set DF.nanFound, DF.nanRows - if ( DF.NanFound() ) { + if ( parameters.verbose and DF.NanFound() ) { // Issue warning std::stringstream msg; msg << "WARNING: SMap() " << DF.NanRows().size() @@ -466,15 +466,13 @@ SMapValues SMap( DataFrame< double > & DF, << "Original number of rows " << DF.NRows() << ".\n"; std::cout << msg.str(); - if ( parameters.verbose ) { - msg.str( std::string() ); // clear msg - msg << "WARNING: SMap() nan rows: "; - std::vector< size_t >::iterator ni; - for ( ni = DF.NanRows().begin(); ni != DF.NanRows().end(); ++ni ) { - msg << *ni + 1 << " "; - } msg << "\n"; - std::cout << msg.str(); - } + msg.str( std::string() ); // clear msg + msg << "WARNING: SMap() nan rows: "; + std::vector< size_t >::iterator ni; + for ( ni = DF.NanRows().begin(); ni != DF.NanRows().end(); ++ni ) { + msg << *ni + 1 << " "; + } msg << "\n"; + std::cout << msg.str(); } //----------------------------------------------------------------- diff --git a/src/cppEDM/src/Common.cc b/src/cppEDM/src/Common.cc index a8c1fe0..49f026e 100644 --- a/src/cppEDM/src/Common.cc +++ b/src/cppEDM/src/Common.cc @@ -113,7 +113,7 @@ VectorError ComputeError( std::valarray< double > obsIn, // We need to find the appropriate slice parameters // To try and be efficient, we first scan for nans, if none: stats - // If there are nans, then assess the overlapping subset and slice + // If there are nans, copy from the overlapping values bool nanObs = false; bool nanPred = false; @@ -130,46 +130,34 @@ VectorError ComputeError( std::valarray< double > obsIn, pred = std::valarray< double >( predIn ); } else { - // Handle nans... + // Handle nans // Build concurrent vector of bool pairs : isnan on obsIn, predIn std::vector< std::pair< bool, bool > > nanIndexPairs( Nin ); for ( size_t i = 0; i < Nin; i++ ) { nanIndexPairs[ i ] = std::make_pair( std::isnan( obsIn[i] ), std::isnan( predIn[i] ) ); } - // Find overlapping subset indices + // Find overlapping subset indices or use set::intersection // Condense pairs into one boolean value in nonNanOverlap + size_t Nout = 0; std::vector< bool > nonNanOverlap( Nin ); for ( size_t i = 0; i < Nin; i++ ) { if ( not nanIndexPairs[ i ].first and not nanIndexPairs[ i ].second ) { nonNanOverlap[ i ] = true; // Both are not nan, valid index + Nout++; } else { nonNanOverlap[ i ] = false; } } - // Get the slice parameters - auto firstValid = std::find( nonNanOverlap.begin(), - nonNanOverlap.end(), true ); - auto lastValid = std::find( nonNanOverlap.rbegin(), - nonNanOverlap.rend(), true ); - size_t firstValidIndex = std::distance( nonNanOverlap.begin(), - firstValid ); - size_t lastValidIndex = std::distance( nonNanOverlap.rbegin(), - lastValid ); - - lastValidIndex = Nin - lastValidIndex; // reverse iterator used... - - int Nout = (int) lastValidIndex - (int) firstValidIndex; - - if ( Nout < 0 ) { + + if ( Nout < 6 ) { std::stringstream msg; - msg << "WARNING: ComputeError(): nan predictions found" - << " error not computed." << std::endl; + msg << "WARNING: ComputeError(): nan found. Not enough data" + << " to compute error." << std::endl; std::cout << msg.str(); - Nout = 0; obs = std::valarray< double >( 0., 1 ); // vector [0.] N = 1 pred = std::valarray< double >( 0., 1 ); // vector [0.] N = 1 } @@ -177,10 +165,16 @@ VectorError ComputeError( std::valarray< double > obsIn, // Allocate the output arrays and fill with slices obs = std::valarray< double >( Nout ); pred = std::valarray< double >( Nout ); - - std::slice nonNan = std::slice( firstValidIndex, Nout, 1 ); - obs [ std::slice( 0, Nout, 1 ) ] = obsIn [ nonNan ]; - pred[ std::slice( 0, Nout, 1 ) ] = predIn[ nonNan ]; + + // Copy valid values into obs & pred + size_t n = 0; + for ( size_t i = 0; i < nonNanOverlap.size(); i++ ) { + if ( nonNanOverlap[ i ] ) { + obs [ n ] = obsIn [ i ]; + pred[ n ] = predIn[ i ]; + n++; + } + } } } diff --git a/src/cppEDM/src/Parameter.cc b/src/cppEDM/src/Parameter.cc index f0bd77c..aea8864 100644 --- a/src/cppEDM/src/Parameter.cc +++ b/src/cppEDM/src/Parameter.cc @@ -102,7 +102,7 @@ Parameters::Parameters( validated ( false ), // Instantiate Version - version( 1, 15, 3, "2023-11-31" ) + version( 1, 15, 4, "2024-04-05" ) { // Constructor code if ( method != Method::None ) {