Something went wrong on our end
Select Git revision
correct_and_smooth.py
-
Clara Betancourt authoredClara Betancourt authored
Analysis.cpp 23.39 KiB
/**
* \file Analysis.cpp
* \date Oct 10, 2014
* \version v0.7
* \copyright <2009-2016> Forschungszentrum Juelich GmbH. All rights reserved.
*
* \section License
* This file is part of JuPedSim.
*
* JuPedSim is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* JuPedSim is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with JuPedSim. If not, see <http://www.gnu.org/licenses/>.
*
* \section Description
* The Analysis class represents a process of analyzing groups of pedestrian
* trajectories from experiment or simulation. Different measurement methods
* can be used and are defined by various parameters and functions.
*
*
**/
#include "Analysis.h"
#include "geometry/Room.h"
#include "geometry/SubRoom.h"
#include "methods/VoronoiDiagram.h"
#include "methods/Method_A.h"
#include "methods/Method_B.h"
#include "methods/Method_C.h"
#include "methods/Method_D.h"
#include "methods/Method_I.h"
#include "methods/PedData.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <cfloat>
#include <stdlib.h>
#include <algorithm> // std::min_element, std::max_element
#ifdef __linux__
#include <sys/stat.h>
#include <dirent.h>
#elif __APPLE__
#include <sys/stat.h>
#include <dirent.h>
#else
#include <direct.h>
#endif
using boost::geometry::dsv;
using namespace std;
OutputHandler* Log = new STDIOHandler();
/************************************************
// Konstruktoren
************************************************/
Analysis::Analysis()
{
_building = NULL;
_projectRootDir="";
_deltaF=5; // half of the time interval that used to calculate instantaneous velocity of ped i. Here v_i = (X(t+deltaF) - X(t+deltaF))/(2*deltaF). X is location.
_DoesUseMethodA = false; // Method A (Zhang2011a)
_DoesUseMethodB = false; // Method B (Zhang2011a)
_DoesUseMethodC = false; // Method C //calculate and save results of classic in separate file
_DoesUseMethodD = false; // Method D--Voronoi method
_cutByCircle = false; //Adjust whether cut each original voronoi cell by a circle
_getProfile = false; // Whether make field analysis or not
_outputGraph = false; // Whether output the data for plot the fundamental diagram each frame
_calcIndividualFD = false; //Adjust whether analyze the individual density and velocity of each pedestrian in stationary state (ALWAYS VORONOI-BASED)
_vComponent = "B"; // to mark whether x, y or x and y coordinate are used when calculating the velocity
_IgnoreBackwardMovement = false;
_grid_size_X = 0.10; // the size of the grid
_grid_size_Y = 0.10;
_lowVertexX = 0;// LOWest vertex of the geometry (x coordinate)
_lowVertexY = 0; // LOWest vertex of the geometry (y coordinate)
_highVertexX = 10; // Highest vertex of the geometry
_highVertexY = 10;
_cutRadius=1.0;
_circleEdges=6;
_trajFormat=FileFormat::FORMAT_PLAIN;
_isOneDimensional=false;
_plotGraph=false;
}
Analysis::~Analysis()
{
delete _building;
}
// file.txt ---> file
std::string Analysis::GetBasename (const std::string& str)
{
std::cout << "Splitting: " << str << '\n';
unsigned found = str.find_last_of(".");
return str.substr(0,found);
}
// c:\\windows\\winhelp.exe ---> winhelp.exe
std::string Analysis::GetFilename (const std::string& str)
{
std::cout << "GetFilename: " << str << '\n';
unsigned found = str.find_last_of("/\\");
return str.substr(found+1);
}
void Analysis::InitArgs(ArgumentParser* args)
{
string s = "Parameter:\n";
_building = new Building();
_building->LoadGeometry(args->GetGeometryFilename());
// create the polygons
_building->InitGeometry();
// _building->AddSurroundingRoom();
if(args->GetIsMethodA()) {
_DoesUseMethodA = true;
vector<int> Measurement_Area_IDs = args->GetAreaIDforMethodA();
for(unsigned int i=0; i<Measurement_Area_IDs.size(); i++)
{
_areaForMethod_A.push_back(dynamic_cast<MeasurementArea_L*>( args->GetMeasurementArea(Measurement_Area_IDs[i])));
}
_deltaT = args->GetTimeIntervalA();
_plotTimeseriesA=args->GetIsPlotTimeSeriesA();
}
if(args->GetIsMethodB()) {
_DoesUseMethodB = true;
vector<int> Measurement_Area_IDs = args->GetAreaIDforMethodB();
for(unsigned int i=0; i<Measurement_Area_IDs.size(); i++)
{
_areaForMethod_B.push_back(dynamic_cast<MeasurementArea_B*>( args->GetMeasurementArea(Measurement_Area_IDs[i])));
}
}
if(args->GetIsMethodC()) {
_DoesUseMethodC = true;
vector<int> Measurement_Area_IDs = args->GetAreaIDforMethodC();
for(unsigned int i=0; i<Measurement_Area_IDs.size(); i++)
{
_areaForMethod_C.push_back(dynamic_cast<MeasurementArea_B*>( args->GetMeasurementArea(Measurement_Area_IDs[i])));
}
_plotTimeseriesC=args->GetIsPlotTimeSeriesC();
}
if(args->GetIsMethodD()) {
_DoesUseMethodD = true;
vector<int> Measurement_Area_IDs = args->GetAreaIDforMethodD();
for(unsigned int i=0; i<Measurement_Area_IDs.size(); i++)
{
_areaForMethod_D.push_back(dynamic_cast<MeasurementArea_B*>( args->GetMeasurementArea(Measurement_Area_IDs[i])));
}
_StartFramesMethodD = args->GetStartFramesMethodD();
_StopFramesMethodD = args->GetStopFramesMethodD();
_IndividualFDFlags = args->GetIndividualFDFlags();
_plotTimeseriesD=args->GetIsPlotTimeSeriesD();
_geoPolyMethodD = ReadGeometry(args->GetGeometryFilename(), _areaForMethod_D);
}
if(args->GetIsMethodI()) {
_DoesUseMethodI = true;
vector<int> Measurement_Area_IDs = args->GetAreaIDforMethodI();
for(unsigned int i=0; i<Measurement_Area_IDs.size(); i++)
{
_areaForMethod_I.push_back(dynamic_cast<MeasurementArea_B*>( args->GetMeasurementArea(Measurement_Area_IDs[i])));
}
_StartFramesMethodI = args->GetStartFramesMethodI();
_StopFramesMethodI = args->GetStopFramesMethodI();
_IndividualFDFlags = args->GetIndividualFDFlags();
_plotTimeseriesI=args->GetIsPlotTimeSeriesI();
_geoPolyMethodI = ReadGeometry(args->GetGeometryFilename(), _areaForMethod_I);
}
// ToDo: obsolete ?
// if( _DoesUseMethodD && _DoesUseMethodI)
// {
// Log->Write("Warning:\t Using both method D and I is not safe!");
// // because ReadGeometry() may be called twice (line 169 and 182)
// // overwrite _geoPoly -> new value for each Method
// Log->Write("Info:\t Using both method D and I is safe! :-)");
// }
_deltaF = args->GetDelatT_Vins();
_cutByCircle = args->GetIsCutByCircle();
_getProfile = args->GetIsGetProfile();
_outputGraph = args->GetIsOutputGraph();
_plotGraph = args->GetIsPlotGraph();
_plotIndex = args->GetIsPlotIndex();
_isOneDimensional=args->GetIsOneDimensional();
_vComponent = args->GetVComponent();
_IgnoreBackwardMovement =args->GetIgnoreBackwardMovement();
_grid_size_X = int(args->GetGridSizeX());
_grid_size_Y = int(args->GetGridSizeY());
_geometryFileName=args->GetGeometryFilename();
_projectRootDir=args->GetProjectRootDir();
_trajFormat=args->GetFileFormat();
_cutRadius=args->GetCutRadius();
_circleEdges=args->GetCircleEdges();
_scriptsLocation=args->GetScriptsLocation();
_outputLocation=args->GetOutputLocation();
}
std::map<int, polygon_2d> Analysis::ReadGeometry(const fs::path& geometryFile, const std::vector<MeasurementArea_B*>& areas)
{
Log->Write("INFO:\tReadGeometry with %s", geometryFile.string().c_str());
double geo_minX = FLT_MAX;
double geo_minY = FLT_MAX;
double geo_maxX = -FLT_MAX;
double geo_maxY = -FLT_MAX;
std::map<int, polygon_2d> geoPoly;
//loop over all areas
for(auto&& area: areas)
{
//search for the subroom that contains that area
for (auto&& it_room : _building->GetAllRooms())
{
for (auto&& it_sub : it_room.second->GetAllSubRooms())
{
SubRoom* subroom = it_sub.second.get();
point_2d point(0,0);
boost::geometry::centroid(area->_poly,point);
//check if the area is contained in the obstacle
if(subroom->IsInSubRoom(Point(point.x()/M2CM,point.y()/M2CM)))
{
for (auto&& tmp_point : subroom->GetPolygon())
{
append(geoPoly[area->_id], make<point_2d>(tmp_point._x*M2CM, tmp_point._y*M2CM));
geo_minX = (tmp_point._x*M2CM<=geo_minX) ? (tmp_point._x*M2CM) : geo_minX;
geo_minY = (tmp_point._y*M2CM<=geo_minY) ? (tmp_point._y*M2CM) : geo_minY;
geo_maxX = (tmp_point._x*M2CM>=geo_maxX) ? (tmp_point._x*M2CM) : geo_maxX;
geo_maxY = (tmp_point._y*M2CM>=geo_maxY) ? (tmp_point._y*M2CM) : geo_maxY;
}
correct(geoPoly[area->_id]);
//cout<<"this is:\t"<<subroom->GetAllObstacles().size()<<endl;
//appen the holes/obstacles if any
int k=1;
for(auto&& obst: subroom->GetAllObstacles())
{
geoPoly[area->_id].inners().resize(k++);
geoPoly[area->_id].inners().back();
model::ring<point_2d>& inner = geoPoly[area->_id].inners().back();
for(auto&& tmp_point:obst->GetPolygon())
{
append(inner, make<point_2d>(tmp_point._x*M2CM, tmp_point._y*M2CM));
}
correct(geoPoly[area->_id]);
}
}
}
}//room
if(geoPoly.count(area->_id)==0)
{
Log->Write("ERROR: \t No polygon containing the measurement id [%d]", area->_id);
geoPoly[area->_id] = area->_poly;
}
}
_highVertexX = geo_maxX;
_highVertexY = geo_maxY;
_lowVertexX = geo_minX;
_lowVertexY = geo_minY;
return geoPoly;
}
int Analysis::RunAnalysis(const fs::path& filename, const fs::path& path)
{
PedData data;
if(data.ReadData(_projectRootDir, _outputLocation, path, filename, _trajFormat, _deltaF, _vComponent, _IgnoreBackwardMovement)==false)
{
Log->Write("ERROR:\tCould not parse the file %d", filename.c_str());
return -1;
}
//-----------------------------check whether there is pedestrian outside the whole geometry--------------------------------------------
std::map<int , std::vector<int> > _peds_t=data.GetPedsFrame();
for(int frameNr = 0; frameNr < data.GetNumFrames(); frameNr++ )
{
vector<int> ids=_peds_t[frameNr];
vector<int> IdInFrame = data.GetIdInFrame(frameNr, ids);
vector<double> XInFrame = data.GetXInFrame(frameNr, ids);
vector<double> YInFrame = data.GetYInFrame(frameNr, ids);
for( unsigned int i=0;i<IdInFrame.size();i++)
{
bool IsInBuilding=false;
for (auto&& it_room : _building->GetAllRooms())
{
for (auto&& it_sub : it_room.second->GetAllSubRooms())
{
SubRoom* subroom = it_sub.second.get();
if(subroom->IsInSubRoom(Point(XInFrame[i]*CMtoM,YInFrame[i]*CMtoM)))
{
IsInBuilding=true;
break;
}
}
if(IsInBuilding)
{
break;
}
}
if(false==IsInBuilding)
{
Log->Write("Warning:\tAt %dth frame pedestrian at <x=%.4f, y=%.4f> is not in geometry!", frameNr+data.GetMinFrame(), XInFrame[i]*CMtoM, YInFrame[i]*CMtoM );
}
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
if(_DoesUseMethodA) //Method A
{
if(_areaForMethod_A.empty())
{
Log->Write("ERROR: Method A selected with no measurement area!");
exit(EXIT_FAILURE);
}
#pragma omp parallel for
for(long unsigned int i=0; i < _areaForMethod_A.size(); i++)
{
Method_A method_A ;
method_A.SetMeasurementArea(_areaForMethod_A[i]);
method_A.SetTimeInterval(_deltaT[i]);
method_A.SetPlotTimeSeries(_plotTimeseriesA[i]);
bool result_A=method_A.Process(data,_scriptsLocation,_areaForMethod_A[i]->_zPos);
if(result_A)
{
Log->Write("INFO:\tSuccess with Method A using measurement area id %d!\n",_areaForMethod_A[i]->_id);
std::cout << "INFO:\tSuccess with Method A using measurement area id "<< _areaForMethod_A[i]->_id << "\n";
}
else
{
Log->Write("INFO:\tFailed with Method A using measurement area id %d!\n",_areaForMethod_A[i]->_id);
}
}
}
if(_DoesUseMethodB) //Method_B
{
if(_areaForMethod_B.empty())
{
Log->Write("ERROR: Method B selected with no measurement area!");
exit(EXIT_FAILURE);
}
#pragma omp parallel for
for(long unsigned int i=0; i < _areaForMethod_B.size(); i++)
{
Method_B method_B;
method_B.SetMeasurementArea(_areaForMethod_B[i]);
bool result_B = method_B.Process(data);
if(result_B)
{
Log->Write("INFO:\tSuccess with Method B using measurement area id %d!\n",_areaForMethod_B[i]->_id);
std::cout << "INFO:\tSuccess with Method B using measurement area id "<< _areaForMethod_B[i]->_id << "\n";
}
else
{
Log->Write("INFO:\tFailed with Method B using measurement area id %d!\n",_areaForMethod_B[i]->_id);
}
}
}
if(_DoesUseMethodC) //Method C
{
if(_areaForMethod_C.empty())
{
Log->Write("ERROR: Method C selected with no measurement area!");
exit(EXIT_FAILURE);
}
#pragma omp parallel for
for(long unsigned int i=0; i < _areaForMethod_C.size(); i++)
{
Method_C method_C;
method_C.SetMeasurementArea(_areaForMethod_C[i]);
bool result_C =method_C.Process(data,_areaForMethod_C[i]->_zPos);
if(result_C)
{
Log->Write("INFO:\tSuccess with Method C using measurement area id %d!\n",_areaForMethod_C[i]->_id);
std::cout << "INFO:\tSuccess with Method C using measurement area id "<< _areaForMethod_C[i]->_id << "\n";
if(_plotTimeseriesC[i])
{
string parameters_Timeseries=" " + _scriptsLocation.string()+
"/_Plot_timeseries_rho_v.py -p "+ _projectRootDir.string()+VORO_LOCATION + " -n "+filename.string()+
" -f "+boost::lexical_cast<std::string>(data.GetFps());
parameters_Timeseries = PYTHON + parameters_Timeseries;
int res=system(parameters_Timeseries.c_str());
Log->Write("INFO:\t time series result: %d ",res);
}
}
else
{
Log->Write("INFO:\tFailed with Method C using measurement area id %d!\n",_areaForMethod_C[i]->_id);
}
}
}
if(_DoesUseMethodD) //method_D
{
if(_areaForMethod_D.empty())
{
Log->Write("ERROR: Method D selected with no measurement area!");
exit(EXIT_FAILURE);
}
#pragma omp parallel for
for(long unsigned int i=0; i<_areaForMethod_D.size(); i++)
{
Method_D method_D;
method_D.SetStartFrame(_StartFramesMethodD[i]);
method_D.SetStopFrame(_StopFramesMethodD[i]);
method_D.SetCalculateIndividualFD(_IndividualFDFlags[i]);
method_D.SetGeometryPolygon(_geoPolyMethodD[_areaForMethod_D[i]->_id]);
method_D.SetGeometryFileName(_geometryFileName);
method_D.SetGeometryBoundaries(_lowVertexX, _lowVertexY, _highVertexX, _highVertexY);
method_D.SetGridSize(_grid_size_X, _grid_size_Y);
method_D.SetOutputVoronoiCellData(_outputGraph);
method_D.SetPlotVoronoiGraph(_plotGraph);
method_D.SetPlotVoronoiIndex(_plotIndex);
method_D.SetDimensional(_isOneDimensional);
method_D.SetCalculateProfiles(_getProfile);
method_D.SetTrajectoriesLocation(path);
if(_cutByCircle)
{
method_D.Setcutbycircle(_cutRadius, _circleEdges);
}
method_D.SetMeasurementArea(_areaForMethod_D[i]);
bool result_D = method_D.Process(data,_scriptsLocation, _areaForMethod_D[i]->_zPos);
if(result_D)
{
Log->Write("INFO:\tSuccess with Method D using measurement area id %d!\n",_areaForMethod_D[i]->_id);
std::cout << "INFO:\tSuccess with Method D using measurement area id "<< _areaForMethod_D[i]->_id << "\n";
if(_plotTimeseriesD[i])
{
string parameters_Timeseries= " " +_scriptsLocation.string()+"/_Plot_timeseries_rho_v.py -p "+ _projectRootDir.string()+VORO_LOCATION + " -n "+filename.string()+
" -f "+boost::lexical_cast<std::string>(data.GetFps());
parameters_Timeseries = PYTHON + parameters_Timeseries;
std::cout << parameters_Timeseries << "\n;";
int res=system(parameters_Timeseries.c_str());
Log->Write("INFO:\t time series result: %d ",res);
}
}
else
{
Log->Write("INFO:\tFailed with Method D using measurement area id %d!\n",_areaForMethod_D[i]->_id);
}
}
}
if(_DoesUseMethodI) //method_I
{
if(_areaForMethod_I.empty())
{
Log->Write("ERROR: Method I selected with no measurement area!");
exit(EXIT_FAILURE);
}
#pragma omp parallel for
for(long unsigned int i=0; i<_areaForMethod_I.size(); i++)
{
Method_I method_I;
method_I.SetStartFrame(_StartFramesMethodI[i]);
method_I.SetStopFrame(_StopFramesMethodI[i]);
method_I.SetCalculateIndividualFD(_IndividualFDFlags[i]);
method_I.SetGeometryPolygon(_geoPolyMethodI[_areaForMethod_I[i]->_id]);
method_I.SetGeometryFileName(_geometryFileName);
method_I.SetGeometryBoundaries(_lowVertexX, _lowVertexY, _highVertexX, _highVertexY);
method_I.SetGridSize(_grid_size_X, _grid_size_Y);
method_I.SetOutputVoronoiCellData(_outputGraph);
// method_I.SetPlotVoronoiGraph(_plotGraph);
method_I.SetPlotVoronoiIndex(_plotIndex);
method_I.SetDimensional(_isOneDimensional);
// method_I.SetCalculateProfiles(_getProfile);
method_I.SetTrajectoriesLocation(path);
if(_cutByCircle)
{
method_I.Setcutbycircle(_cutRadius, _circleEdges);
}
method_I.SetMeasurementArea(_areaForMethod_I[i]);
bool result_I = method_I.Process(data,_scriptsLocation, _areaForMethod_I[i]->_zPos);
if(result_I)
{
Log->Write("INFO:\tSuccess with Method I using measurement area id %d!\n",_areaForMethod_I[i]->_id);
std::cout << "INFO:\tSuccess with Method I using measurement area id "<< _areaForMethod_I[i]->_id << "\n";
if(_plotTimeseriesI[i])
{
string parameters_Timeseries= " " +_scriptsLocation.string()+"/_Plot_timeseries_rho_v.py -p "+ _projectRootDir.string()+VORO_LOCATION + " -n "+filename.string()+
" -f "+boost::lexical_cast<std::string>(data.GetFps());
parameters_Timeseries = PYTHON + parameters_Timeseries;
std::cout << parameters_Timeseries << "\n;";
int res=system(parameters_Timeseries.c_str());
Log->Write("INFO:\t time series result: %d ",res);
}
}
else
{
Log->Write("INFO:\tFailed with Method I using measurement area id %d!\n",_areaForMethod_I[i]->_id);
}
}
}
return 0;
}
FILE* Analysis::CreateFile(const string& filename)
{
//first try to create the file
FILE* fHandle= fopen(filename.c_str(),"w");
if(fHandle) return fHandle;
unsigned int found=filename.find_last_of("/\\");
string dir = filename.substr(0,found)+"/";
//string file= filename.substr(found+1);
// the directories are probably missing, create it
if (mkpath((char*)dir.c_str())==-1) {
Log->Write("ERROR:\tcannot create the directory <%s>",dir.c_str());
return NULL;
}
//second and last attempt
return fopen(filename.c_str(),"w");
}
#if defined(_WIN32)
// @todo: rewrite using boost
int Analysis::mkpath(char* file_path)
{
assert(file_path && *file_path);
char* p;
for (p=strchr(file_path+1, '/'); p; p=strchr(p+1, '/')) {
*p='\0';
if (_mkdir(file_path)==-1) {
if (errno!=EEXIST) {
*p='/';
return -1;
}
}
*p='/';
}
return 0;
}
#else
// @todo: rewrite using boost
int Analysis::mkpath(char* file_path, mode_t mode)
{
assert(file_path && *file_path);
char* p;
for (p=strchr(file_path+1, '/'); p; p=strchr(p+1, '/')) {
*p='\0';
if (mkdir(file_path, mode)==-1) {
if (errno!=EEXIST) {
*p='/';
return -1;
}
}
*p='/';
}
return 0;
}
// delete
#endif