#include "StrideSearchTypeDefs.h" #include "StrideSearchConfig.h" #include "StrideSearchUtilities.h" #include "StrideSearchDataBase.h" #include "StrideSearchSectorListBase.h" #include "StrideSearchMinMaxCriteria.h" #include "StrideSearchExtraCriteria.h" #include "StrideSearchTimer.h" #include "StrideSearchEvent.h" #include "StrideSearchDateTime.h" #include "StrideSearchNanoflannTree.h" #include #include #include #include #include #include #include using namespace StrideSearch; typedef std::shared_ptr event_ptr_type; struct Input{ Input(int argc, char* argv[]); std::string outputFilename; index_type nInputFiles; std::vector inFiles; std::string program_name; DateTime startDate; std::string pvarname = "PRECT"; std::string pvarname1 = "PRECC"; std::string pvarname2 = "PRECL"; std::string olrvarname = "FLU"; int pvarcount; scalar_type olr_threshold = std::numeric_limits::max(); scalar_type precip_threshold = std::numeric_limits::max(); scalar_type precip_olr_dist_threshold = std::numeric_limits::lowest(); scalar_type west_boundary = 220.0; scalar_type east_boundary = 300.0; scalar_type south_boundary = 30.0; scalar_type north_boundary = 45.0; scalar_type sector_size_km = 200.0; index_type start_year = 1850; index_type start_month = 1; index_type start_day = 1; index_type start_hour = 0; void usageMessage(std::ostream &os) const; std::string infoString() const; }; int main(int argc, char* argv[]) { print_copyright(); Timer programTimer("MCSDriver"); programTimer.start(); /* Get input from command line */ Input input(argc, argv); input.usageMessage(std::cout); std::cout << std::endl; std::cout << input.infoString(); std::cout << std::endl; Timer setupTimer("MCS_setup"); setupTimer.start(); /* set up data for reading */ if (input.inFiles.empty()) { std::cout << "ERROR: no input files defined." << std::endl; return 1; } std::shared_ptr ssData(new StrideSearchData(input.inFiles[0])); // one-time initialization of stride search data, assumes grid is the same for all files ssData->initDimensions(); std::cout << ssData->infoString(); // build tree NanoflannTree tree(ssData); tree.buildTree(); /* set up search region, link to data */ SectorList sectors(input.south_boundary, input.north_boundary, input.west_boundary, input.east_boundary, input.sector_size_km); sectors.linkSectorsToData(ssData, tree); std::cout << sectors.infoString(); /* set up identification criteria */ std::shared_ptr olr(new MaxCriterion(input.olrvarname, input.olr_threshold)); std::shared_ptr precip; if (input.pvarcount == 1) { precip = std::shared_ptr(new MaxCriterion(input.pvarname, input.precip_threshold)); } else if (input.pvarcount == 2) { precip = std::shared_ptr(new MaxSumCriterion(input.pvarname1, input.pvarname2, input.precip_threshold)); } else { std::cout << "ERROR: either -precip_var_name or both -precip_var1 and -precip_var2 must be defined." << std::endl; return 1; } std::vector loc_criteria = {precip.get()}; std::vector id_criteria = {precip.get(), olr.get()}; // collocation criteria const scalar_type precip_olr_dist_threshold = input.precip_olr_dist_threshold; sectors.buildWorkspaces(loc_criteria); setupTimer.end(); std::cout << "setup complete " << setupTimer.infoString(); /* run spatial search */ Timer searchTimer("MCSDriver_spatial_search"); searchTimer.start(); EventList mainList; // // Loop over each data file // int fileCounter = 0; std::stringstream ss; std::string nullstr; for (auto& file : input.inFiles) { ssData->updateSourceFile(file); std::cout << "... processing file " << ++fileCounter << " of " << input.nInputFiles << std::endl; // // Loop over each time step in file // ss << " of " << ssData->nTimesteps() << "; "; const std::string nTimestepsStr = ss.str(); ss.str(nullstr); for (index_type k=0; k < ssData->nTimesteps(); ++k) { const DateTime currentDate(ssData->getTime(k), input.startDate); std::cout << "\ttimestep " << std::setw(3) << std::setfill(' ') << k << nTimestepsStr << " " << currentDate.DTGString(); // // loop over each sector using location criteria only // std::vector> possibleEvents; int possCounter = 0; for (index_type i=0; iloadSectorWorkingData(sectors.sectors[i].get(), k); possibleEvents.push_back( sectors.sectors[i]->evaluateCriteriaAtTimestep(loc_criteria, currentDate, file, k)); possCounter += possibleEvents[i].size(); } // // create new sectors centered at each possible event // EventList possibleList(possibleEvents); possibleList.removeDuplicates(input.sector_size_km); SectorList timestepSecList(possibleList, input.sector_size_km); timestepSecList.linkSectorsToData(ssData, tree); timestepSecList.buildWorkspaces(id_criteria); // // loop over possible events, load data, and evaluate all criteria // int eventCounter = 0; std::vector> foundEvents; for (index_type i=0; iloadSectorWorkingData(timestepSecList.sectors[i].get(), k); foundEvents.push_back( timestepSecList.sectors[i]->evaluateCriteriaAtTimestep(id_criteria, currentDate, file, k)); eventCounter += foundEvents[i].size(); } EventList foundEventList(foundEvents); foundEventList.removeDuplicates(input.sector_size_km); // // apply collocation criteria // foundEventList.consolidateRelatedEvents(input.sector_size_km); foundEventList.requireCollocation(precip.get(), olr.get(), input.precip_olr_dist_threshold); std::cout << " : " << std::setw(2) << std::setfill(' ') << eventCounter << " events." << std::endl; // // save timestep data // mainList.extend(foundEventList); } } searchTimer.end(); // // write output // std::ofstream outfile(input.outputFilename); const int indent_tabs = 0; const bool printAll = true; outfile << mainList.infoString(indent_tabs, printAll); outfile.close(); std::cout << setupTimer.infoString(); std::cout << searchTimer.infoString(); programTimer.end(); std::cout << programTimer.infoString(); return 0; } Input::Input(int argc, char* argv[]) { program_name = argv[0]; outputFilename = "strideSearchDefaultOutput.txt"; inFiles = std::vector(); nInputFiles = 0; pvarcount = 0; if (argc == 1 && argv[1] == "-h") { usageMessage(std::cout); } if (argc > 1) { for (int i=1; i