<commit_before>// main.cpp

/* Copyright (c)  2009 Stanford University
 * Use of the OpenSim software in source form is permitted provided that the following
 * conditions are met:
 *   1. The software is used only for non-commercial research and education. It may not
 *     be used in relation to any commercial activity.
 *   2. The software is not distributed or redistributed.  Software distribution is allowed
 *     only through https://simtk.org/home/opensim.
 *   3. Use of the OpenSim software or derivatives must be acknowledged in all publications,
 *      presentations, or documents describing work in which OpenSim or derivatives are used.
 *   4. Credits to developers may not be removed from executables
 *     created from modifications of the source.
 *   5. Modifications of source code must retain the above copyright notice, this list of
 *     conditions and the following disclaimer.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 *  SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 *  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 *  OR BUSINESS INTERRUPTION) OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
 *  WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 *  Below is an example of an OpenSim application that provides its own
 *  main() routine.  This application is a forward simulation of tug-of-war between two
 *  muscles pulling on a block.
 */

// Author:  Jeff Reinbolt, Ayman Habib, Ajay Seth, Jack Middleton, Samuel Hamner

//==============================================================================
//==============================================================================
#include <OpenSim/OpenSim.h>
#include <OpenSim/Auxiliary/auxiliaryTestFunctions.h>

using namespace OpenSim;
using namespace std;

//______________________________________________________________________________
/**
 * Run a simulation of block sliding with contact on by two muscles sliding with contact
 */
int main(int argc, char **argv)
{
	using namespace SimTK;

	bool waitForUserInput = (argc<2);
	try {
		const clock_t start = clock();

		///////////////////////////////////////////
		// DEFINE BODIES AND JOINTS OF THE MODEL //
		///////////////////////////////////////////

		// Create an OpenSim model and set its name
		Model osimModel;
		osimModel.setName("tugOfWar");

		// GROUND BODY

		// Get a reference to the model's ground body
		OpenSim::Body& ground = osimModel.getGroundBody();

		// Add display geometry to the ground to visualize in the GUI
		ground.addDisplayGeometry("ground.vtp");
		ground.addDisplayGeometry("anchor1.vtp");
		ground.addDisplayGeometry("anchor2.vtp");

		// BLOCK BODY

		// Specify properties of a 20 kg, 0.1 m^3 block body
		double blockMass = 20.0, blockSideLength = 0.1;
		Vec3 blockMassCenter(0);
		Inertia blockInertia = blockMass*Inertia::brick(blockSideLength, blockSideLength, blockSideLength);

		// Create a new block body with the specified properties
		OpenSim::Body *block = new OpenSim::Body("block", blockMass, blockMassCenter, blockInertia);

		// Add display geometry to the block to visualize in the GUI
		block->addDisplayGeometry("block.vtp");

		// FREE JOINT

		// Create a new free joint with 6 degrees-of-freedom (coordinates) between the block and ground bodies
		Vec3 locationInParent(0, blockSideLength/2, 0), orientationInParent(0), locationInBody(0), orientationInBody(0);
		FreeJoint *blockToGround = new FreeJoint("blockToGround", ground, locationInParent, orientationInParent, *block, locationInBody, orientationInBody);

		// Get a reference to the coordinate set (6 degrees-of-freedom) between the block and ground bodies
		CoordinateSet& jointCoordinateSet = blockToGround->getCoordinateSet();

		// Set the angle and position ranges for the coordinate set
		double angleRange[2] = {-Pi/2, Pi/2};
		double positionRange[2] = {-1, 1};
		jointCoordinateSet[0].setRange(angleRange);
		jointCoordinateSet[1].setRange(angleRange);
		jointCoordinateSet[2].setRange(angleRange);
		jointCoordinateSet[3].setRange(positionRange);
		jointCoordinateSet[4].setRange(positionRange);
		jointCoordinateSet[5].setRange(positionRange);

		// Add the block body to the model
		osimModel.addBody(block);

		///////////////////////////////////////////////
		// DEFINE THE SIMULATION START AND END TIMES //
		///////////////////////////////////////////////

		// Define the initial and final simulation times
		double initialTime = 0.0;
		double finalTime = 0.6;

		/////////////////////////////////////////////
		// DEFINE CONSTRAINTS IMPOSED ON THE MODEL //
		/////////////////////////////////////////////

		// Specify properties of a point on a line constraint to limit the block's motion
		Vec3 lineDirection(1,0,-1);
		Vec3 pointOnLine(1,0,-1);
		Vec3 pointOnFollowerBody(0,-0.05,0);

		// Create a new point on a line constraint
		PointOnLineConstraint *lineConstraint = new PointOnLineConstraint(ground, lineDirection, pointOnLine, *block, pointOnFollowerBody);

		// Add the new point on a line constraint to the model
		osimModel.addConstraint(lineConstraint);

		///////////////////////////////////////
		// DEFINE FORCES ACTING ON THE MODEL //
		///////////////////////////////////////
		// GRAVITY

		// Define the acceleration due to gravity
		osimModel.setGravity(Vec3(0,-9.80665,0));

		// MUSCLE FORCES

		// Create two new muscles
		double maxIsometricForce = 1000.0, optimalFiberLength = 0.1, tendonSlackLength = 0.2, pennationAngle = 0.0, activation = 0.0001, deactivation = 1.0;
		// Create new muscle 1
		Schutte1993Muscle *muscle1 = new Schutte1993Muscle("muscle1",maxIsometricForce,optimalFiberLength,tendonSlackLength,pennationAngle);
		muscle1->setActivation1(activation);
		muscle1->setActivation2(deactivation);
		// Create new muscle 2
		Thelen2003Muscle *muscle2 = new Thelen2003Muscle("muscle2",maxIsometricForce,optimalFiberLength,tendonSlackLength,pennationAngle);
		muscle2->setActivationTimeConstant(activation);
		muscle2->setDeactivationTimeConstant(deactivation);

		// Specify the paths for the two muscles
		// Path for muscle 1
		muscle1->addNewPathPoint("muscle1-point1", ground, Vec3(0.0,0.05,-0.35));
		muscle1->addNewPathPoint("muscle1-point2", *block, Vec3(0.0,0.0,-0.05));
		// Path for muscle 2
		muscle2->addNewPathPoint("muscle2-point1", ground, Vec3(0.0,0.05,0.35));
		muscle2->addNewPathPoint("muscle2-point2", *block, Vec3(0.0,0.0,0.05));

		// Add the two muscles (as forces) to the model
		osimModel.addForce(muscle1);
		osimModel.addForce(muscle2);

		// CONTACT FORCE

		// Define contact geometry
		// Create new floor contact halfspace
		ContactHalfSpace *floor = new ContactHalfSpace(Vec3(0), Vec3(0, 0, -0.5*SimTK_PI), ground, "floor");
		// Create new cube contact mesh
		OpenSim::ContactMesh *cube = new OpenSim::ContactMesh("blockRemesh192.obj", Vec3(0), Vec3(0), *block, "cube");

		// Add contact geometry to the model
		osimModel.addContactGeometry(floor);
		osimModel.addContactGeometry(cube);

		// Contact parameters
		double stiffness = 1.0e8, dissipation = 0.01, friction = 0.25;

		// Define contact parameters for elastic foundation force
		OpenSim::ElasticFoundationForce::ContactParameters *contactParams =
			new OpenSim::ElasticFoundationForce::ContactParameters(stiffness, dissipation, friction, 0, 0);
		contactParams->addGeometry("cube");
		contactParams->addGeometry("floor");

		// Create a new elastic foundation (contact) force between the floor and cube.
		OpenSim::ElasticFoundationForce *contactForce = new OpenSim::ElasticFoundationForce(contactParams);
		contactForce->setName("contactForce");

		// Add the new elastic foundation force to the model
		osimModel.addForce(contactForce);

		// PRESCRIBED FORCE

		// Specify properties of a force function to be applied to the block
		double time[2] = {0, finalTime};					// time nodes for linear function
		double fXofT[2] = {0,  -blockMass*9.80665*3.0};		// force values at t1 and t2
		double pXofT[2] = {0, 0.1};							// point in x values at t1 and t2

		// Create a new linear functions for the force and point components
		PiecewiseLinearFunction *forceX = new PiecewiseLinearFunction(2, time, fXofT);
		PiecewiseLinearFunction *pointX = new PiecewiseLinearFunction(2, time, pXofT);

		// Create a new prescribed force applied to the block
		PrescribedForce *prescribedForce = new PrescribedForce(block);
		prescribedForce->setName("prescribedForce");

		// Set the force and point functions for the new prescribed force
		prescribedForce->setForceFunctions(forceX, new Constant(0.0), new Constant(0.0));
		prescribedForce->setPointFunctions(pointX, new Constant(0.0), new Constant(0.0));

		// Add the new prescribed force to the model
		osimModel.addForce(prescribedForce);

		//osimModel.print("tugOfWar_musclesContactPres.osim");

		///////////////////////////////////
		// DEFINE CONTROLS FOR THE MODEL //
		///////////////////////////////////
		// Create a prescribed controller that simply applies controls as function of time
		PrescribedController *muscleController = new PrescribedController();
		muscleController->setActuators(osimModel.updActuators());
		// Define linear functions for the control values for the two muscles
		Array<double> slopeAndIntercept1(0.0, 2);  // array of 2 doubles
		Array<double> slopeAndIntercept2(0.0, 2);
		// muscle1 control has slope of -1 starting 1 at t = 0
		slopeAndIntercept1[0] = -1.0/(finalTime-initialTime);  slopeAndIntercept1[1] = 1.0;
		// muscle2 control has slope of 1 starting 0.05 at t = 0
		slopeAndIntercept2[0] = 1.0/(finalTime-initialTime);  slopeAndIntercept2[1] = 0.05;

		// Set the indiviudal muscle control functions for the prescribed muscle controller
		muscleController->prescribeControlForActuator("muscle1", new LinearFunction(slopeAndIntercept1));
		muscleController->prescribeControlForActuator("muscle2", new LinearFunction(slopeAndIntercept2));

		// Add the control set controller to the model
		osimModel.addController(muscleController);

		//////////////////////////
		// PERFORM A SIMULATION //
		//////////////////////////

		// Define the default states for the two muscles
		// Activation
		muscle1->setDefaultActivation(slopeAndIntercept1[1]);
		muscle2->setDefaultActivation(slopeAndIntercept2[1]);
		// Fiber length
		muscle2->setDefaultFiberLength(0.1);
		muscle1->setDefaultFiberLength(0.1);

		// Initialize the system and get the default state
		State& si = osimModel.initSystem();

		// Define non-zero (defaults are 0) states for the free joint
		CoordinateSet& modelCoordinateSet = osimModel.updCoordinateSet();
		modelCoordinateSet[3].setValue(si, blockSideLength); // set x-translation value
		modelCoordinateSet[3].setSpeedValue(si, 0.1); // set x-speed value
		modelCoordinateSet[4].setValue(si, blockSideLength/2+0.01); // set y-translation value

		// Compute initial conditions for muscles
		osimModel.computeEquilibriumForAuxiliaryStates(si);

		// Create the integrator, force reporter, and manager for the simulation.
		// Create the integrator
		RungeKuttaMersonIntegrator integrator(osimModel.getMultibodySystem());
		integrator.setAccuracy(1.0e-3);
		integrator.setAbsoluteTolerance(1.0e-3);

		// Create the force reporter
		ForceReporter* reporter = new ForceReporter(&osimModel);
		osimModel.addAnalysis(reporter);

		// Create the manager
		Manager manager(osimModel, integrator);

		// Print out details of the model
		osimModel.printDetailedInfo(si, cout);

		// Print out the initial position and velocity states
		si.getQ().dump("Initial q's"); // block positions
		si.getU().dump("Initial u's"); // block velocities
		cout << "Initial time: " << si.getTime() << endl;

		// Integrate from initial time to final time
		manager.setInitialTime(initialTime);
		manager.setFinalTime(finalTime);
		cout<<"\n\nIntegrating from "<<initialTime<<" to "<<finalTime<<endl;
		manager.integrate(si);

		//////////////////////////////
		// SAVE THE RESULTS TO FILE //
		//////////////////////////////

		// Save the simulation results
		// Save the states
		Storage statesDegrees(manager.getStateStorage());
		statesDegrees.print("tugOfWar_states.sto");
		osimModel.updSimbodyEngine().convertRadiansToDegrees(statesDegrees);
		statesDegrees.setWriteSIMMHeader(true);
		statesDegrees.print("tugOfWar_states_degrees.mot");
		// Save the forces
		reporter->getForceStorage().print("tugOfWar_forces.mot");

		// Save the model to a file
		osimModel.print("tugOfWar_model.osim");

		cout << "OpenSim Installation verified.\n" << endl;
		cout << "main() routine time = " << (double)(clock()-start)/CLOCKS_PER_SEC << " seconds" << endl;
	}
    catch (exception ex)
    {
        cout << ex.what() << endl;
		cout << "press any key to continue..." << endl;
		if (waitForUserInput) getchar();
        return 1;
    }
    catch (...)
    {
        cout << "UNRECOGNIZED EXCEPTION" << endl;
 		cout << "press any key to continue..." << endl;
		if (waitForUserInput) getchar();
       return 1;
    }

	cout << "press any key to continue..." << endl;
	if (waitForUserInput) getchar();
	return 0;
}
<commit_msg>Increase simulation time to generate significant movement. Commented out visualizer code, since it hangs test.<commit_after>// main.cpp

/* Copyright (c)  2009 Stanford University
 * Use of the OpenSim software in source form is permitted provided that the following
 * conditions are met:
 *   1. The software is used only for non-commercial research and education. It may not
 *     be used in relation to any commercial activity.
 *   2. The software is not distributed or redistributed.  Software distribution is allowed
 *     only through https://simtk.org/home/opensim.
 *   3. Use of the OpenSim software or derivatives must be acknowledged in all publications,
 *      presentations, or documents describing work in which OpenSim or derivatives are used.
 *   4. Credits to developers may not be removed from executables
 *     created from modifications of the source.
 *   5. Modifications of source code must retain the above copyright notice, this list of
 *     conditions and the following disclaimer.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 *  SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 *  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 *  OR BUSINESS INTERRUPTION) OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
 *  WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 *  Below is an example of an OpenSim application that provides its own
 *  main() routine.  This application is a forward simulation of tug-of-war between two
 *  muscles pulling on a block.
 */

// Author:  Jeff Reinbolt, Ayman Habib, Ajay Seth, Jack Middleton, Samuel Hamner

//==============================================================================
//==============================================================================
#include <OpenSim/OpenSim.h>
#include <OpenSim/Auxiliary/auxiliaryTestFunctions.h>

using namespace OpenSim;
using namespace std;

//______________________________________________________________________________
/**
 * Run a simulation of block sliding with contact on by two muscles sliding with contact
 */
int main(int argc, char **argv)
{
	using namespace SimTK;

	bool waitForUserInput = (argc<2);
	try {
		const clock_t start = clock();

		///////////////////////////////////////////
		// DEFINE BODIES AND JOINTS OF THE MODEL //
		///////////////////////////////////////////

		// Create an OpenSim model and set its name
		Model osimModel;
		osimModel.setName("tugOfWar");

		// GROUND BODY

		// Get a reference to the model's ground body
		OpenSim::Body& ground = osimModel.getGroundBody();

		// Add display geometry to the ground to visualize in the GUI
		ground.addDisplayGeometry("ground.vtp");
		ground.addDisplayGeometry("anchor1.vtp");
		ground.addDisplayGeometry("anchor2.vtp");

		// BLOCK BODY

		// Specify properties of a 20 kg, 0.1 m^3 block body
		double blockMass = 20.0, blockSideLength = 0.1;
		Vec3 blockMassCenter(0);
		Inertia blockInertia = blockMass*Inertia::brick(blockSideLength, blockSideLength, blockSideLength);

		// Create a new block body with the specified properties
		OpenSim::Body *block = new OpenSim::Body("block", blockMass, blockMassCenter, blockInertia);

		// Add display geometry to the block to visualize in the GUI
		block->addDisplayGeometry("block.vtp");

		// FREE JOINT

		// Create a new free joint with 6 degrees-of-freedom (coordinates) between the block and ground bodies
		Vec3 locationInParent(0, blockSideLength/2, 0), orientationInParent(0), locationInBody(0), orientationInBody(0);
		FreeJoint *blockToGround = new FreeJoint("blockToGround", ground, locationInParent, orientationInParent, *block, locationInBody, orientationInBody);

		// Get a reference to the coordinate set (6 degrees-of-freedom) between the block and ground bodies
		CoordinateSet& jointCoordinateSet = blockToGround->getCoordinateSet();

		// Set the angle and position ranges for the coordinate set
		double angleRange[2] = {-Pi/2, Pi/2};
		double positionRange[2] = {-1, 1};
		jointCoordinateSet[0].setRange(angleRange);
		jointCoordinateSet[1].setRange(angleRange);
		jointCoordinateSet[2].setRange(angleRange);
		jointCoordinateSet[3].setRange(positionRange);
		jointCoordinateSet[4].setRange(positionRange);
		jointCoordinateSet[5].setRange(positionRange);

		// Add the block body to the model
		osimModel.addBody(block);

		///////////////////////////////////////////////
		// DEFINE THE SIMULATION START AND END TIMES //
		///////////////////////////////////////////////

		// Define the initial and final simulation times
		double initialTime = 0.0;
		double finalTime = 4.0;

		/////////////////////////////////////////////
		// DEFINE CONSTRAINTS IMPOSED ON THE MODEL //
		/////////////////////////////////////////////

		// Specify properties of a point on a line constraint to limit the block's motion
		Vec3 lineDirection(1,0,-1);
		Vec3 pointOnLine(1,0,-1);
		Vec3 pointOnFollowerBody(0,-0.05,0);

		// Create a new point on a line constraint
		PointOnLineConstraint *lineConstraint = new PointOnLineConstraint(ground, lineDirection, pointOnLine, *block, pointOnFollowerBody);

		// Add the new point on a line constraint to the model
		osimModel.addConstraint(lineConstraint);

		///////////////////////////////////////
		// DEFINE FORCES ACTING ON THE MODEL //
		///////////////////////////////////////
		// GRAVITY

		// Define the acceleration due to gravity
		osimModel.setGravity(Vec3(0,-9.80665,0));

		// MUSCLE FORCES

		// Create two new muscles
		double maxIsometricForce = 1000.0, optimalFiberLength = 0.1, tendonSlackLength = 0.2, pennationAngle = 0.0, activation = 0.0001, deactivation = 1.0;
		// Create new muscle 1
		Schutte1993Muscle *muscle1 = new Schutte1993Muscle("muscle1",maxIsometricForce,optimalFiberLength,tendonSlackLength,pennationAngle);
		muscle1->setActivation1(activation);
		muscle1->setActivation2(deactivation);
		// Create new muscle 2
		Thelen2003Muscle *muscle2 = new Thelen2003Muscle("muscle2",maxIsometricForce,optimalFiberLength,tendonSlackLength,pennationAngle);
		muscle2->setActivationTimeConstant(activation);
		muscle2->setDeactivationTimeConstant(deactivation);

		// Specify the paths for the two muscles
		// Path for muscle 1
		muscle1->addNewPathPoint("muscle1-point1", ground, Vec3(0.0,0.05,-0.35));
		muscle1->addNewPathPoint("muscle1-point2", *block, Vec3(0.0,0.0,-0.05));
		// Path for muscle 2
		muscle2->addNewPathPoint("muscle2-point1", ground, Vec3(0.0,0.05,0.35));
		muscle2->addNewPathPoint("muscle2-point2", *block, Vec3(0.0,0.0,0.05));

		// Add the two muscles (as forces) to the model
		osimModel.addForce(muscle1);
		osimModel.addForce(muscle2);

		// CONTACT FORCE

		// Define contact geometry
		// Create new floor contact halfspace
		ContactHalfSpace *floor = new ContactHalfSpace(Vec3(0), Vec3(0, 0, -0.5*SimTK_PI), ground, "floor");
		// Create new cube contact mesh
		OpenSim::ContactMesh *cube = new OpenSim::ContactMesh("blockRemesh192.obj", Vec3(0), Vec3(0), *block, "cube");

		// Add contact geometry to the model
		osimModel.addContactGeometry(floor);
		osimModel.addContactGeometry(cube);

		// Contact parameters
		double stiffness = 1.0e8, dissipation = 0.01, friction = 0.25;

		// Define contact parameters for elastic foundation force
		OpenSim::ElasticFoundationForce::ContactParameters *contactParams =
			new OpenSim::ElasticFoundationForce::ContactParameters(stiffness, dissipation, friction, 0, 0);
		contactParams->addGeometry("cube");
		contactParams->addGeometry("floor");

		// Create a new elastic foundation (contact) force between the floor and cube.
		OpenSim::ElasticFoundationForce *contactForce = new OpenSim::ElasticFoundationForce(contactParams);
		contactForce->setName("contactForce");

		// Add the new elastic foundation force to the model
		osimModel.addForce(contactForce);

		// PRESCRIBED FORCE

		// Specify properties of a force function to be applied to the block
		double time[2] = {0, finalTime};					// time nodes for linear function
		double fXofT[2] = {0,  -blockMass*9.80665*3.0};		// force values at t1 and t2
		double pXofT[2] = {0, 0.1};							// point in x values at t1 and t2

		// Create a new linear functions for the force and point components
		PiecewiseLinearFunction *forceX = new PiecewiseLinearFunction(2, time, fXofT);
		PiecewiseLinearFunction *pointX = new PiecewiseLinearFunction(2, time, pXofT);

		// Create a new prescribed force applied to the block
		PrescribedForce *prescribedForce = new PrescribedForce(block);
		prescribedForce->setName("prescribedForce");

		// Set the force and point functions for the new prescribed force
		prescribedForce->setForceFunctions(forceX, new Constant(0.0), new Constant(0.0));
		prescribedForce->setPointFunctions(pointX, new Constant(0.0), new Constant(0.0));

		// Add the new prescribed force to the model
		osimModel.addForce(prescribedForce);

		//osimModel.print("tugOfWar_musclesContactPres.osim");

		///////////////////////////////////
		// DEFINE CONTROLS FOR THE MODEL //
		///////////////////////////////////
		// Create a prescribed controller that simply applies controls as function of time
		PrescribedController *muscleController = new PrescribedController();
		muscleController->setActuators(osimModel.updActuators());
		// Define linear functions for the control values for the two muscles
		Array<double> slopeAndIntercept1(0.0, 2);  // array of 2 doubles
		Array<double> slopeAndIntercept2(0.0, 2);
		// muscle1 control has slope of -1 starting 1 at t = 0
		slopeAndIntercept1[0] = -1.0/(finalTime-initialTime);  slopeAndIntercept1[1] = 1.0;
		// muscle2 control has slope of 1 starting 0.05 at t = 0
		slopeAndIntercept2[0] = 1.0/(finalTime-initialTime);  slopeAndIntercept2[1] = 0.05;

		// Set the indiviudal muscle control functions for the prescribed muscle controller
		muscleController->prescribeControlForActuator("muscle1", new LinearFunction(slopeAndIntercept1));
		muscleController->prescribeControlForActuator("muscle2", new LinearFunction(slopeAndIntercept2));

		// Add the control set controller to the model
		osimModel.addController(muscleController);

		//////////////////////////
		// PERFORM A SIMULATION //
		//////////////////////////

		// Define the default states for the two muscles
		// Activation
		muscle1->setDefaultActivation(slopeAndIntercept1[1]);
		muscle2->setDefaultActivation(slopeAndIntercept2[1]);
		// Fiber length
		muscle2->setDefaultFiberLength(0.1);
		muscle1->setDefaultFiberLength(0.1);

		// Initialize the system and get the default state
		State& si = osimModel.initSystem();

		// Define non-zero (defaults are 0) states for the free joint
		CoordinateSet& modelCoordinateSet = osimModel.updCoordinateSet();
		modelCoordinateSet[3].setValue(si, blockSideLength); // set x-translation value
		modelCoordinateSet[3].setSpeedValue(si, 0.1); // set x-speed value
		modelCoordinateSet[4].setValue(si, blockSideLength/2+0.01); // set y-translation value

		// Compute initial conditions for muscles
		osimModel.computeEquilibriumForAuxiliaryStates(si);

		//osimModel.updMultibodySystem().updMatterSubsystem().setShowDefaultGeometry(false);
		//Visualizer viz(osimModel.getMultibodySystem());
		//osimModel.updMultibodySystem().addEventReporter(new Visualizer::Reporter(viz, 0.1));

		// Create the integrator, force reporter, and manager for the simulation.
		// Create the integrator
		RungeKuttaMersonIntegrator integrator(osimModel.getMultibodySystem());
		integrator.setAccuracy(1.0e-3);
		integrator.setAbsoluteTolerance(1.0e-3);

		// Create the force reporter
		ForceReporter* reporter = new ForceReporter(&osimModel);
		osimModel.addAnalysis(reporter);

		// Create the manager
		Manager manager(osimModel, integrator);

		// Print out details of the model
		osimModel.printDetailedInfo(si, cout);

		// Print out the initial position and velocity states
		si.getQ().dump("Initial q's"); // block positions
		si.getU().dump("Initial u's"); // block velocities
		cout << "Initial time: " << si.getTime() << endl;

		// Integrate from initial time to final time
		manager.setInitialTime(initialTime);
		manager.setFinalTime(finalTime);
		cout<<"\n\nIntegrating from "<<initialTime<<" to "<<finalTime<<endl;
		manager.integrate(si);

		//////////////////////////////
		// SAVE THE RESULTS TO FILE //
		//////////////////////////////

		// Save the simulation results
		// Save the states
		Storage statesDegrees(manager.getStateStorage());
		statesDegrees.print("tugOfWar_states.sto");
		osimModel.updSimbodyEngine().convertRadiansToDegrees(statesDegrees);
		statesDegrees.setWriteSIMMHeader(true);
		statesDegrees.print("tugOfWar_states_degrees.mot");
		// Save the forces
		reporter->getForceStorage().print("tugOfWar_forces.mot");

		// Save the model to a file
		osimModel.print("tugOfWar_model.osim");

		cout << "OpenSim Installation verified.\n" << endl;
		cout << "main() routine time = " << (double)(clock()-start)/CLOCKS_PER_SEC << " seconds" << endl;
	}
    catch (exception ex)
    {
        cout << ex.what() << endl;
		cout << "press any key to continue..." << endl;
		if (waitForUserInput) getchar();
        return 1;
    }
    catch (...)
    {
        cout << "UNRECOGNIZED EXCEPTION" << endl;
 		cout << "press any key to continue..." << endl;
		if (waitForUserInput) getchar();
       return 1;
    }

	cout << "press any key to continue..." << endl;
	if (waitForUserInput) getchar();
	return 0;
}
<|endoftext|>


<commit_before>#include "AliFemtoDreamControlSample.h"
#include "AliLog.h"
#include "TDatabasePDG.h"
#include "TLorentzVector.h"
#include "TMath.h"

ClassImp(AliFemtoDreamControlSample)

AliFemtoDreamControlSample::AliFemtoDreamControlSample()
    : fHigherMath(nullptr),
      fPDGParticleSpecies(),
      fRejPairs(),
      fMultBins(),
      fRandom(),
      fPi(TMath::Pi()),
      fmode(AliFemtoDreamCollConfig::kNone),
      fSpinningDepth(0),
      fCorrelationRange(0.),
      fDeltaEtaMax(0.f),
      fDeltaPhiMax(0.f),
      fDoDeltaEtaDeltaPhiCut(false),
      fMult(0),
      fCent(0) {
  fRandom.SetSeed(0);
}

AliFemtoDreamControlSample::AliFemtoDreamControlSample(
    const AliFemtoDreamControlSample &samp)
    : fHigherMath(samp.fHigherMath),
      fPDGParticleSpecies(samp.fPDGParticleSpecies),
      fRejPairs(samp.fRejPairs),
      fMultBins(samp.fMultBins),
      fRandom(),
      fPi(TMath::Pi()),
      fmode(samp.fmode),
      fSpinningDepth(samp.fSpinningDepth),
      fCorrelationRange(samp.fCorrelationRange),
      fDeltaEtaMax(samp.fDeltaEtaMax),
      fDeltaPhiMax(samp.fDeltaPhiMax),
      fDoDeltaEtaDeltaPhiCut(samp.fDoDeltaEtaDeltaPhiCut),
      fMult(samp.fMult),
      fCent(samp.fCent) {
  fRandom.SetSeed(0);
}

AliFemtoDreamControlSample::AliFemtoDreamControlSample(
    AliFemtoDreamCollConfig *conf)
    : fHigherMath(new AliFemtoDreamHigherPairMath(conf)),
      fPDGParticleSpecies(conf->GetPDGCodes()),
      fRejPairs(conf->GetClosePairRej()),
      fMultBins(conf->GetMultBins()),
      fRandom(),
      fPi(TMath::Pi()),
      fmode(conf->GetControlMode()),
      fSpinningDepth(conf->GetSpinningDepth()),
      fCorrelationRange(conf->GetCorrelationRange()),
      fDeltaEtaMax(conf->GetDeltaEtaMax()),
      fDeltaPhiMax(conf->GetDeltaPhiMax()),
      fDoDeltaEtaDeltaPhiCut(false),
      fMult(0),
      fCent(0) {
  fRandom.SetSeed(0);
}

AliFemtoDreamControlSample& AliFemtoDreamControlSample::operator=(
    const AliFemtoDreamControlSample& samp) {
  if (this == &samp) {
    return *this;
  }
  this->fHigherMath = samp.fHigherMath;
  this->fPDGParticleSpecies = samp.fPDGParticleSpecies;
  this->fRejPairs = samp.fRejPairs;
  this->fMultBins = samp.fMultBins;
  this->fRandom.SetSeed(0);
  this->fPi = TMath::Pi();
  this->fSpinningDepth = samp.fSpinningDepth;
  this->fDeltaEtaMax = samp.fDeltaEtaMax;
  this->fDeltaPhiMax = samp.fDeltaPhiMax;
  this->fDoDeltaEtaDeltaPhiCut = samp.fDoDeltaEtaDeltaPhiCut;
  this->fMult = samp.fMult;
  this->fCent = samp.fCent;
  return *this;
}

AliFemtoDreamControlSample::~AliFemtoDreamControlSample() {
}

void AliFemtoDreamControlSample::SetEvent(
    std::vector<std::vector<AliFemtoDreamBasePart>> &Particles,
    AliFemtoDreamEvent *evt) {
  fMult = FindBin(evt->GetMultiplicity());
  fCent = evt->GetV0MCentrality();
  fHigherMath->SetBField(evt->GetMagneticField());
  int HistCounter = 0;
  auto itPDGPar1 = fPDGParticleSpecies.begin();
  auto itSpec1 = Particles.begin();
  bool sameParticle = false;
  size_t minimumSize;
  while (itSpec1 != Particles.end()) {
    auto itSpec2 = itSpec1;
    auto itPDGPar2 = itPDGPar1;
    while (itSpec2 != Particles.end()) {
      fHigherMath->FillPairCounterSE(HistCounter, itSpec1->size(),
                                     itSpec2->size());
      if (itSpec1 == itSpec2) {
        sameParticle = true;
        minimumSize = 1;
      } else {
        minimumSize = 0;
        sameParticle = false;
      }
      //if it is the same particle, then we need at least two to pair them 2*2 is the minimum
      if ((itSpec1->size() > minimumSize) && (itSpec2->size() > minimumSize)) {  // for single particle pairs, this is pointless
        CorrelatedSample(*itSpec1, *itPDGPar1, *itSpec2, *itPDGPar2,
                         sameParticle, HistCounter);
        UncorrelatedSample(*itSpec1, *itPDGPar1, *itSpec2, *itPDGPar2,
                           sameParticle, HistCounter);
      }
      ++itSpec2;
      ++HistCounter;
      ++itPDGPar2;
    }
    itPDGPar1++;
    itSpec1++;
  }
}

int AliFemtoDreamControlSample::FindBin(float Multiplicity) {
  int binCounter = fMultBins.size();
  for (std::vector<int>::reverse_iterator itBin = fMultBins.rbegin();
      itBin != fMultBins.rend(); ++itBin) {
    binCounter--;
    if (Multiplicity >= *itBin) {
      break;
    }
  }
  return binCounter;
}

void AliFemtoDreamControlSample::CorrelatedSample(
    std::vector<AliFemtoDreamBasePart> &part1, int &PDGPart1,
    std::vector<AliFemtoDreamBasePart> &part2, int &PDGPart2, bool SameParticle,
    int HistCounter) {
  float RelativeK = 0;
  auto itPart1 = part1.begin();
  bool CPR = fRejPairs.at(HistCounter);
  while (itPart1 != part1.end()) {
    auto itPart2 = SameParticle ? itPart1 + 1 : part2.begin();
    while (itPart2 != part2.end()) {
      if (fDoDeltaEtaDeltaPhiCut && CPR) {
        if (fHigherMath->PassesPairSelection(&(*itPart1), &(*itPart2), false)) {
          ++itPart2;
          continue;
        }
      }
      RelativeK = fHigherMath->FillSameEvent(HistCounter, fMult, fCent,
                                             itPart1->GetMomentum(), PDGPart1,
                                             itPart2->GetMomentum(), PDGPart2);
      fHigherMath->MassQA(HistCounter, RelativeK, itPart1->GetInvMass(),
                          itPart2->GetInvMass());
      fHigherMath->SEDetaDPhiPlots(HistCounter, *itPart1, PDGPart1, *itPart2,
                                   PDGPart2, RelativeK, true);

      itPart2++;
    }
    itPart1++;
  }
}

void AliFemtoDreamControlSample::UncorrelatedSample(
    std::vector<AliFemtoDreamBasePart> &part1, int &PDGPart1,
    std::vector<AliFemtoDreamBasePart> &part2, int &PDGPart2, bool SameParticle,
    int HistCounter) {
  if (fmode == AliFemtoDreamCollConfig::kPhiSpin
      || fmode == AliFemtoDreamCollConfig::kStravinsky) {
    PhiSpinning(part1, PDGPart1, part2, PDGPart2, SameParticle, HistCounter);
  } else if (fmode == AliFemtoDreamCollConfig::kCorrelatedPhi) {
    for (int iSpin = 0; iSpin < fSpinningDepth; ++iSpin) {
      LimitedPhiSpinning(part1, PDGPart1, part2, PDGPart2, SameParticle,
                         HistCounter);
    }
  } else {
    Error("AliFemtoDreamControlSample::UncorrelatedSample",
          "None implemented mode\n");
  }
  return;
}

void AliFemtoDreamControlSample::PhiSpinning(
    std::vector<AliFemtoDreamBasePart> &part1, int PDGPart1,
    std::vector<AliFemtoDreamBasePart> &part2, int PDGPart2, bool SameParticle,
    int HistCounter) {
  float RelativeK = 0;
  auto itPart1 = part1.begin();
  bool CPR = fRejPairs.at(HistCounter);
  while (itPart1 != part1.end()) {
    auto itPart2 = SameParticle ? itPart1 + 1 : part2.begin();
    while (itPart2 != part2.end()) {
      //in this case it does NOT work as intended since the new phi of the particle has to
      //be considered for this cut
      if (fDoDeltaEtaDeltaPhiCut && CPR) {
        if (fHigherMath->PassesPairSelection(&(*itPart1), &(*itPart2), true)) {
          ++itPart2;
          continue;
        }
      }
      for (int i = 0; i < fSpinningDepth; ++i) {
        // randomized sample - who is the father???
        RelativeK = fHigherMath->FillMixedEvent(HistCounter, fMult, fCent,
                                                itPart1->GetMomentum(),
                                                PDGPart1,
                                                itPart2->GetMomentum(),
                                                PDGPart2, fmode);
        fHigherMath->MEDetaDPhiPlots(HistCounter, *itPart1, PDGPart1, *itPart2,
                                     PDGPart2, RelativeK, true);
      }
      itPart2++;
    }
    itPart1++;
  }
}

void AliFemtoDreamControlSample::LimitedPhiSpinning(
    std::vector<AliFemtoDreamBasePart> &part1, int PDGPart1,
    std::vector<AliFemtoDreamBasePart> &part2, int PDGPart2, bool SameParticle,
    int HistCounter) {
  //copy input to not touch the initial state & make it to pointers to do some nasty things.
  std::vector<AliFemtoDreamBasePart*> CopyPart1;
  std::vector<AliFemtoDreamBasePart*> CopyPart2;

  for (auto it : part1) {
    CopyPart1.emplace_back(new AliFemtoDreamBasePart(it));
  }
  // randomize the sample: add references to all particles to a vector
  std::vector<AliFemtoDreamBasePart*> RandomizeMe;
  for (auto it : CopyPart1) {
    RandomizeMe.push_back(it);
  }
  // Only add the second particle, in case it is a different particle
  if (!SameParticle) {
    for (auto it : part2) {
      CopyPart2.emplace_back(new AliFemtoDreamBasePart(it));
    }
    for (auto it : CopyPart2) {
      RandomizeMe.push_back(it);
    }
  } else {  // if the particles are the same this should point to the same vector as particle 1
    CopyPart2 = CopyPart1;
  }
  Randomizer(RandomizeMe);
  // calculate the relative momentum
  float RelativeK = 0;
  bool CPR = fRejPairs.at(HistCounter);
  auto itPart1 = CopyPart1.begin();
  while (itPart1 != CopyPart1.end()) {
    auto itPart2 = SameParticle ? itPart1 + 1 : CopyPart2.begin();
    while (itPart2 != (SameParticle ? CopyPart1 : CopyPart2).end()) {
      //in this case it does NOT work as intended since the new phi of the particle has to
      //be considered for this cut
      if (fDoDeltaEtaDeltaPhiCut && CPR) {
        if (fDoDeltaEtaDeltaPhiCut && CPR) {
          if (fHigherMath->PassesPairSelection(*itPart1, *itPart2, true)) {
            ++itPart2;
            continue;
          }
        }
      }
      // randomized sample - who is the father???
      RelativeK = fHigherMath->FillMixedEvent(HistCounter, fMult, fCent,
                                              (*itPart1)->GetMomentum(),
                                              PDGPart1,
                                              (*itPart2)->GetMomentum(),
                                              PDGPart2,
                                              AliFemtoDreamCollConfig::kNone);
      fHigherMath->MEDetaDPhiPlots(HistCounter, *itPart1, PDGPart1, *itPart2,
                                   PDGPart2, RelativeK, true);
      itPart2++;
    }
    itPart1++;
  }
  for (auto iDel : RandomizeMe) {
    delete iDel;
  }
  RandomizeMe.clear();
//  it was checked with massif that there is no memory leak and even if the pointer and its members
//  still exist.
//  for (auto iTest : CopyPart1) {
//    if (iTest){
//      Warning("LimitedPhiSpinning",
//              "This should be deleted, think about your code \n");
//    }
//  }
  CopyPart1.clear();
  CopyPart2.clear();
  return;
}

void AliFemtoDreamControlSample::Randomizer(
    std::vector<AliFemtoDreamBasePart*> &part) {
  if (part.size() < 2) {
    Warning("AliFemtoDreamControlSample::Randomizer",
            "this should not happen, check the vector size\n");
  }
  auto itPart1 = part.begin();
  auto itPart2 = itPart1;  // dummy vale to start the while
  while (itPart1 != part.end()) {  // this doersn't work
    itPart2 = itPart1 + 1;  //pick the next particle
    if (itPart2 == part.end()) {  // if this is out of range, finish the while
      break;
    }
    // Get the momenta
    TVector3 Part1Mom = (*itPart1)->GetMomentum();
    TVector3 Part2Mom = (*itPart2)->GetMomentum();
    Part2Mom += Part1Mom;
    // give the first particle a phi kick
    Part1Mom.SetPhi(
        Part1Mom.Phi()
            + fRandom.Uniform(-fCorrelationRange, fCorrelationRange));
    Part2Mom -= Part1Mom;
    (*itPart1)->SetMomentum(Part1Mom);
    (*itPart2)->SetMomentum(Part2Mom);
    itPart1 += 2;
  }
}
<commit_msg>Fixes the arguments of the higher mass class in the control sample<commit_after>#include "AliFemtoDreamControlSample.h"
#include "AliLog.h"
#include "TDatabasePDG.h"
#include "TLorentzVector.h"
#include "TMath.h"

ClassImp(AliFemtoDreamControlSample)

AliFemtoDreamControlSample::AliFemtoDreamControlSample()
    : fHigherMath(nullptr),
      fPDGParticleSpecies(),
      fRejPairs(),
      fMultBins(),
      fRandom(),
      fPi(TMath::Pi()),
      fmode(AliFemtoDreamCollConfig::kNone),
      fSpinningDepth(0),
      fCorrelationRange(0.),
      fDeltaEtaMax(0.f),
      fDeltaPhiMax(0.f),
      fDoDeltaEtaDeltaPhiCut(false),
      fMult(0),
      fCent(0) {
  fRandom.SetSeed(0);
}

AliFemtoDreamControlSample::AliFemtoDreamControlSample(
    const AliFemtoDreamControlSample &samp)
    : fHigherMath(samp.fHigherMath),
      fPDGParticleSpecies(samp.fPDGParticleSpecies),
      fRejPairs(samp.fRejPairs),
      fMultBins(samp.fMultBins),
      fRandom(),
      fPi(TMath::Pi()),
      fmode(samp.fmode),
      fSpinningDepth(samp.fSpinningDepth),
      fCorrelationRange(samp.fCorrelationRange),
      fDeltaEtaMax(samp.fDeltaEtaMax),
      fDeltaPhiMax(samp.fDeltaPhiMax),
      fDoDeltaEtaDeltaPhiCut(samp.fDoDeltaEtaDeltaPhiCut),
      fMult(samp.fMult),
      fCent(samp.fCent) {
  fRandom.SetSeed(0);
}

AliFemtoDreamControlSample::AliFemtoDreamControlSample(
    AliFemtoDreamCollConfig *conf)
    : fHigherMath(new AliFemtoDreamHigherPairMath(conf)),
      fPDGParticleSpecies(conf->GetPDGCodes()),
      fRejPairs(conf->GetClosePairRej()),
      fMultBins(conf->GetMultBins()),
      fRandom(),
      fPi(TMath::Pi()),
      fmode(conf->GetControlMode()),
      fSpinningDepth(conf->GetSpinningDepth()),
      fCorrelationRange(conf->GetCorrelationRange()),
      fDeltaEtaMax(conf->GetDeltaEtaMax()),
      fDeltaPhiMax(conf->GetDeltaPhiMax()),
      fDoDeltaEtaDeltaPhiCut(false),
      fMult(0),
      fCent(0) {
  fRandom.SetSeed(0);
}

AliFemtoDreamControlSample& AliFemtoDreamControlSample::operator=(
    const AliFemtoDreamControlSample& samp) {
  if (this == &samp) {
    return *this;
  }
  this->fHigherMath = samp.fHigherMath;
  this->fPDGParticleSpecies = samp.fPDGParticleSpecies;
  this->fRejPairs = samp.fRejPairs;
  this->fMultBins = samp.fMultBins;
  this->fRandom.SetSeed(0);
  this->fPi = TMath::Pi();
  this->fSpinningDepth = samp.fSpinningDepth;
  this->fDeltaEtaMax = samp.fDeltaEtaMax;
  this->fDeltaPhiMax = samp.fDeltaPhiMax;
  this->fDoDeltaEtaDeltaPhiCut = samp.fDoDeltaEtaDeltaPhiCut;
  this->fMult = samp.fMult;
  this->fCent = samp.fCent;
  return *this;
}

AliFemtoDreamControlSample::~AliFemtoDreamControlSample() {
}

void AliFemtoDreamControlSample::SetEvent(
    std::vector<std::vector<AliFemtoDreamBasePart>> &Particles,
    AliFemtoDreamEvent *evt) {
  fMult = FindBin(evt->GetMultiplicity());
  fCent = evt->GetV0MCentrality();
  fHigherMath->SetBField(evt->GetMagneticField());
  int HistCounter = 0;
  auto itPDGPar1 = fPDGParticleSpecies.begin();
  auto itSpec1 = Particles.begin();
  bool sameParticle = false;
  size_t minimumSize;
  while (itSpec1 != Particles.end()) {
    auto itSpec2 = itSpec1;
    auto itPDGPar2 = itPDGPar1;
    while (itSpec2 != Particles.end()) {
      fHigherMath->FillPairCounterSE(HistCounter, itSpec1->size(),
                                     itSpec2->size());
      if (itSpec1 == itSpec2) {
        sameParticle = true;
        minimumSize = 1;
      } else {
        minimumSize = 0;
        sameParticle = false;
      }
      //if it is the same particle, then we need at least two to pair them 2*2 is the minimum
      if ((itSpec1->size() > minimumSize) && (itSpec2->size() > minimumSize)) {  // for single particle pairs, this is pointless
        CorrelatedSample(*itSpec1, *itPDGPar1, *itSpec2, *itPDGPar2,
                         sameParticle, HistCounter);
        UncorrelatedSample(*itSpec1, *itPDGPar1, *itSpec2, *itPDGPar2,
                           sameParticle, HistCounter);
      }
      ++itSpec2;
      ++HistCounter;
      ++itPDGPar2;
    }
    itPDGPar1++;
    itSpec1++;
  }
}

int AliFemtoDreamControlSample::FindBin(float Multiplicity) {
  int binCounter = fMultBins.size();
  for (std::vector<int>::reverse_iterator itBin = fMultBins.rbegin();
      itBin != fMultBins.rend(); ++itBin) {
    binCounter--;
    if (Multiplicity >= *itBin) {
      break;
    }
  }
  return binCounter;
}

void AliFemtoDreamControlSample::CorrelatedSample(
    std::vector<AliFemtoDreamBasePart> &part1, int &PDGPart1,
    std::vector<AliFemtoDreamBasePart> &part2, int &PDGPart2, bool SameParticle,
    int HistCounter) {
  float RelativeK = 0;
  auto itPart1 = part1.begin();
  bool CPR = fRejPairs.at(HistCounter);
  while (itPart1 != part1.end()) {
    auto itPart2 = SameParticle ? itPart1 + 1 : part2.begin();
    while (itPart2 != part2.end()) {
      if (fDoDeltaEtaDeltaPhiCut && CPR) {
        if (fHigherMath->PassesPairSelection(*itPart1, *itPart2, false)) {
          ++itPart2;
          continue;
        }
      }
      RelativeK = fHigherMath->FillSameEvent(HistCounter, fMult, fCent,
                                             itPart1->GetMomentum(), PDGPart1,
                                             itPart2->GetMomentum(), PDGPart2);
      fHigherMath->MassQA(HistCounter, RelativeK, *itPart1, *itPart2);
      fHigherMath->SEDetaDPhiPlots(HistCounter, *itPart1, PDGPart1, *itPart2,
                                   PDGPart2, RelativeK, true);

      itPart2++;
    }
    itPart1++;
  }
}

void AliFemtoDreamControlSample::UncorrelatedSample(
    std::vector<AliFemtoDreamBasePart> &part1, int &PDGPart1,
    std::vector<AliFemtoDreamBasePart> &part2, int &PDGPart2, bool SameParticle,
    int HistCounter) {
  if (fmode == AliFemtoDreamCollConfig::kPhiSpin
      || fmode == AliFemtoDreamCollConfig::kStravinsky) {
    PhiSpinning(part1, PDGPart1, part2, PDGPart2, SameParticle, HistCounter);
  } else if (fmode == AliFemtoDreamCollConfig::kCorrelatedPhi) {
    for (int iSpin = 0; iSpin < fSpinningDepth; ++iSpin) {
      LimitedPhiSpinning(part1, PDGPart1, part2, PDGPart2, SameParticle,
                         HistCounter);
    }
  } else {
    Error("AliFemtoDreamControlSample::UncorrelatedSample",
          "None implemented mode\n");
  }
  return;
}

void AliFemtoDreamControlSample::PhiSpinning(
    std::vector<AliFemtoDreamBasePart> &part1, int PDGPart1,
    std::vector<AliFemtoDreamBasePart> &part2, int PDGPart2, bool SameParticle,
    int HistCounter) {
  float RelativeK = 0;
  auto itPart1 = part1.begin();
  bool CPR = fRejPairs.at(HistCounter);
  while (itPart1 != part1.end()) {
    auto itPart2 = SameParticle ? itPart1 + 1 : part2.begin();
    while (itPart2 != part2.end()) {
      //in this case it does NOT work as intended since the new phi of the particle has to
      //be considered for this cut
      if (fDoDeltaEtaDeltaPhiCut && CPR) {
        if (fHigherMath->PassesPairSelection(*itPart1, *itPart2, true)) {
          ++itPart2;
          continue;
        }
      }
      for (int i = 0; i < fSpinningDepth; ++i) {
        // randomized sample - who is the father???
        RelativeK = fHigherMath->FillMixedEvent(HistCounter, fMult, fCent,
                                                itPart1->GetMomentum(),
                                                PDGPart1,
                                                itPart2->GetMomentum(),
                                                PDGPart2, fmode);
        fHigherMath->MEDetaDPhiPlots(HistCounter, *itPart1, PDGPart1, *itPart2,
                                     PDGPart2, RelativeK, true);
      }
      itPart2++;
    }
    itPart1++;
  }
}

void AliFemtoDreamControlSample::LimitedPhiSpinning(
    std::vector<AliFemtoDreamBasePart> &part1, int PDGPart1,
    std::vector<AliFemtoDreamBasePart> &part2, int PDGPart2, bool SameParticle,
    int HistCounter) {
  //copy input to not touch the initial state & make it to pointers to do some nasty things.
  std::vector<AliFemtoDreamBasePart*> CopyPart1;
  std::vector<AliFemtoDreamBasePart*> CopyPart2;

  for (auto it : part1) {
    CopyPart1.emplace_back(new AliFemtoDreamBasePart(it));
  }
  // randomize the sample: add references to all particles to a vector
  std::vector<AliFemtoDreamBasePart*> RandomizeMe;
  for (auto it : CopyPart1) {
    RandomizeMe.push_back(it);
  }
  // Only add the second particle, in case it is a different particle
  if (!SameParticle) {
    for (auto it : part2) {
      CopyPart2.emplace_back(new AliFemtoDreamBasePart(it));
    }
    for (auto it : CopyPart2) {
      RandomizeMe.push_back(it);
    }
  } else {  // if the particles are the same this should point to the same vector as particle 1
    CopyPart2 = CopyPart1;
  }
  Randomizer(RandomizeMe);
  // calculate the relative momentum
  float RelativeK = 0;
  bool CPR = fRejPairs.at(HistCounter);
  auto itPart1 = CopyPart1.begin();
  while (itPart1 != CopyPart1.end()) {
    auto itPart2 = SameParticle ? itPart1 + 1 : CopyPart2.begin();
    while (itPart2 != (SameParticle ? CopyPart1 : CopyPart2).end()) {
      //in this case it does NOT work as intended since the new phi of the particle has to
      //be considered for this cut
      if (fDoDeltaEtaDeltaPhiCut && CPR) {
        if (fDoDeltaEtaDeltaPhiCut && CPR) {
          if (fHigherMath->PassesPairSelection(*(*itPart1), *(*itPart2), true)) {
            ++itPart2;
            continue;
          }
        }
      }
      // randomized sample - who is the father???
      RelativeK = fHigherMath->FillMixedEvent(HistCounter, fMult, fCent,
                                              (*itPart1)->GetMomentum(),
                                              PDGPart1,
                                              (*itPart2)->GetMomentum(),
                                              PDGPart2,
                                              AliFemtoDreamCollConfig::kNone);
      fHigherMath->MEDetaDPhiPlots(HistCounter, *(*itPart1), PDGPart1, *(*itPart2),
                                   PDGPart2, RelativeK, true);
      itPart2++;
    }
    itPart1++;
  }
  for (auto iDel : RandomizeMe) {
    delete iDel;
  }
  RandomizeMe.clear();
//  it was checked with massif that there is no memory leak and even if the pointer and its members
//  still exist.
//  for (auto iTest : CopyPart1) {
//    if (iTest){
//      Warning("LimitedPhiSpinning",
//              "This should be deleted, think about your code \n");
//    }
//  }
  CopyPart1.clear();
  CopyPart2.clear();
  return;
}

void AliFemtoDreamControlSample::Randomizer(
    std::vector<AliFemtoDreamBasePart*> &part) {
  if (part.size() < 2) {
    Warning("AliFemtoDreamControlSample::Randomizer",
            "this should not happen, check the vector size\n");
  }
  auto itPart1 = part.begin();
  auto itPart2 = itPart1;  // dummy vale to start the while
  while (itPart1 != part.end()) {  // this doersn't work
    itPart2 = itPart1 + 1;  //pick the next particle
    if (itPart2 == part.end()) {  // if this is out of range, finish the while
      break;
    }
    // Get the momenta
    TVector3 Part1Mom = (*itPart1)->GetMomentum();
    TVector3 Part2Mom = (*itPart2)->GetMomentum();
    Part2Mom += Part1Mom;
    // give the first particle a phi kick
    Part1Mom.SetPhi(
        Part1Mom.Phi()
            + fRandom.Uniform(-fCorrelationRange, fCorrelationRange));
    Part2Mom -= Part1Mom;
    (*itPart1)->SetMomentum(Part1Mom);
    (*itPart2)->SetMomentum(Part2Mom);
    itPart1 += 2;
  }
}
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////
//                                                               //
// AddMyTask                                                     //
// Author: Z. Yasin & A. Kalweit, CERN, 2017                     //
//                                                               //
///////////////////////////////////////////////////////////////////
class AliAnalysisDataContainer;

AliAnalysisTaskDeuteronAbsorption* AddTaskDeuteronAbsorption(TString name = "standard")
{
    // get the manager via the static access member. since it's static, you don't need
    // an instance of the class to call the function
    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
    if (!mgr) {
        return 0x0;
    }
    // get the input event handler, again via a static method.
    // this handler is part of the managing system and feeds events
    // to your task
    if (!mgr->GetInputEventHandler()) {
        return 0x0;
    }
    // by default, a file is open for writing. here, we get the filename
    TString fileName = AliAnalysisManager::GetCommonFileName();
    fileName += ":DeuteronAbsorption";      // create a subfolder in the file
    // now we create an instance of your task
    AliAnalysisTaskDeuteronAbsorption* task = new AliAnalysisTaskDeuteronAbsorption(Form("AbsorptionTask_%s",name.Data()));
    if(!task) return 0x0;
    // add your task to the manager
    mgr->AddTask(task);
    // your task needs input: here we connect the manager to your task
    mgr->ConnectInput(task,0,mgr->GetCommonInputContainer());
    // same for the output
    mgr->ConnectOutput(task,1,mgr->CreateContainer(name.Data(), TList::Class(), AliAnalysisManager::kOutputContainer, fileName.Data()));
    // in the end, this macro returns a pointer to your task. this will be convenient later on
    // when you will run your analysis in an analysis train on grid
    return task;
}
<commit_msg>Add B field requirement to the Absorption task<commit_after>///////////////////////////////////////////////////////////////////
//                                                               //
// AddMyTask                                                     //
// Author: Z. Yasin & A. Kalweit, CERN, 2017                     //
//                                                               //
///////////////////////////////////////////////////////////////////
class AliAnalysisDataContainer;

AliAnalysisTaskDeuteronAbsorption* AddTaskDeuteronAbsorption(TString name = "standard")
{
    // get the manager via the static access member. since it's static, you don't need
    // an instance of the class to call the function
    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
    if (!mgr) {
        return 0x0;
    }
    // get the input event handler, again via a static method.
    // this handler is part of the managing system and feeds events
    // to your task
    if (!mgr->GetInputEventHandler()) {
        return 0x0;
    }
    //
    AliInputEventHandler* hdl = (AliInputEventHandler*)mgr->GetInputEventHandler();
    if (hdl) hdl->SetNeedField();
    // by default, a file is open for writing. here, we get the filename
    TString fileName = AliAnalysisManager::GetCommonFileName();
    fileName += ":DeuteronAbsorption";      // create a subfolder in the file
    // now we create an instance of your task
    AliAnalysisTaskDeuteronAbsorption* task = new AliAnalysisTaskDeuteronAbsorption(Form("AbsorptionTask_%s",name.Data()));
    if(!task) return 0x0;
    // add your task to the manager
    mgr->AddTask(task);
    // your task needs input: here we connect the manager to your task
    mgr->ConnectInput(task,0,mgr->GetCommonInputContainer());
    // same for the output
    mgr->ConnectOutput(task,1,mgr->CreateContainer(name.Data(), TList::Class(), AliAnalysisManager::kOutputContainer, fileName.Data()));
    // in the end, this macro returns a pointer to your task. this will be convenient later on
    // when you will run your analysis in an analysis train on grid
    return task;
}
<|endoftext|>


<commit_before>// $Id$

//**************************************************************************
//* This file is property of and copyright by the ALICE HLT Project        *
//* ALICE Experiment at CERN, All rights reserved.                         *
//*                                                                        *
//* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
//*                  for The ALICE HLT Project.                            *
//*                                                                        *
//* Permission to use, copy, modify and distribute this software and its   *
//* documentation strictly for non-commercial purposes is hereby granted   *
//* without fee, provided that the above copyright notice appears in all   *
//* copies and that both the copyright notice and this permission notice   *
//* appear in the supporting documentation. The authors make no claims     *
//* about the suitability of this software for any purpose. It is          *
//* provided "as is" without express or implied warranty.                  *
//**************************************************************************

/// @file   AliHLTMisc.cxx
/// @author Matthias Richter
/// @date
/// @brief  Miscellaneous methods for the HLT AliRoot integration

#include "AliHLTMiscImplementation.h"
#include "AliHLTLogging.h"
#include "AliLog.h"
#include "AliCDBManager.h"
#include "AliCDBStorage.h"
#include "AliCDBEntry.h"
#include "AliGRPManager.h"
#include "AliRawReader.h"
#include "AliRawEventHeaderBase.h"
#include "AliTracker.h"
#ifndef HAVE_NOT_ALIESDHLTDECISION
#include "AliESDHLTDecision.h"
#endif //HAVE_NOT_ALIESDHLTDECISION
#include "TGeoGlobalMagField.h"
#include "AliHLTGlobalTriggerDecision.h"
#include "TClass.h"
#include "TStreamerInfo.h"
#include "TObjArray.h"

/** ROOT macro for the implementation of ROOT specific class methods */
ClassImp(AliHLTMiscImplementation);

AliHLTMiscImplementation::AliHLTMiscImplementation()
{
}

AliHLTMiscImplementation::~AliHLTMiscImplementation()
{
  // see header file for function documentation
}

int AliHLTMiscImplementation::InitCDB(const char* cdbpath)
{
  // see header file for function documentation
  int iResult=0;
  AliCDBManager* pCDB = AliCDBManager::Instance();
  AliHLTLogging log;
  if (!pCDB) {
    log.Logging(kHLTLogError, "InitCDB", "CDB handling", "Could not get CDB instance");
  } else {
    if (cdbpath && cdbpath[0]!=0) {
      TString uri=cdbpath;
      if (!uri.BeginsWith("local://") &&
	  !uri.Contains("://")) {
	// assume a local path if no uri specifier is found
	uri="local://";
	uri+=cdbpath;
      }
      pCDB->SetDefaultStorage(uri);
      log.Logging(kHLTLogDebug, "InitCDB", "CDB handling", "CDB instance 0x%x", pCDB);
    } else if (!pCDB->IsDefaultStorageSet()) {
      const char* cdbUri="local://$ALICE_ROOT/OCDB";
      pCDB->SetDefaultStorage(cdbUri);
      pCDB->SetRun(0);
      log.Logging(kHLTLogInfo, "InitCDB", "CDB handling", "set default URI: %s", cdbUri);
    }
  }
  return iResult;
}

int AliHLTMiscImplementation::SetCDBRunNo(int runNo)
{
  // see header file for function documentation
  int iResult=0;
  AliCDBManager* pCDB = AliCDBManager::Instance();
  AliHLTLogging log;
  if (!pCDB) {
    log.Logging(kHLTLogError, "SetCDBRunNo", "CDB handling", "Could not get CDB instance");
  } else {
    pCDB->SetRun(runNo);
  }
  return iResult;
}

int AliHLTMiscImplementation::GetCDBRunNo() const
{
  // see header file for function documentation
  AliCDBManager* pCDB = AliCDBManager::Instance();
  AliHLTLogging log;
  if (!pCDB) {
    log.Logging(kHLTLogError, "SetCDBRunNo", "CDB handling", "Could not get CDB instance");
  } else {
    return pCDB->GetRun();
  }
  return -1;
}

AliCDBEntry* AliHLTMiscImplementation::LoadOCDBEntry(const char* path, int runNo, int version, int subVersion) const
{
  // see header file for function documentation
  AliCDBManager* man = AliCDBManager::Instance();
  if (!man) return NULL;

  const char* uri=man->GetURI(path);
  if (!uri) return NULL;

  AliCDBStorage* store = AliCDBManager::Instance()->GetStorage(uri);
  if (!store) {
    return NULL;
  }

  TString strUri=store->GetURI();
  bool bIsGrid=strUri.BeginsWith("alien://");

  if (version<0) version = store->GetLatestVersion(path, runNo);

  // OCDB objects on GRID have no sub version
  if (subVersion<0 && !bIsGrid) subVersion = store->GetLatestSubVersion(path, runNo, version);
  AliCDBEntry* entry=man->Get(path, runNo, version, subVersion);
  if (entry) {
    // there seems to be a problem with the caching of objects in the CDBManager
    // regardless what version is specified it returns the object from the cache
    AliCDBId id=entry->GetId();
    if (id.GetVersion()==version &&
	id.GetSubVersion()==subVersion) {
      // entry in the cache has the correct version
      return entry;
    }
  }
  return store->Get(path, runNo, version, subVersion);
}

TObject* AliHLTMiscImplementation::ExtractObject(AliCDBEntry* entry) const
{
  // see header file for function documentation
  if (!entry) return NULL;
  return entry->GetObject();
}

int AliHLTMiscImplementation::CheckOCDBEntries(const TMap* const pMap) const
{
  // check the availability of the OCDB entry descriptions in the TMap
  //  key : complete OCDB path of the entry
  //  value : auxiliary object - short description
  int iResult=0;
  if (!pMap) return -EINVAL;

  const TMap* pStorages=AliCDBManager::Instance()->GetStorageMap();
  Int_t runNo = GetCDBRunNo();

  TIterator* next=pMap->MakeIterator();
  if (!next) return -ENOENT;

  TObject* pEntry=NULL;
  while ((pEntry=next->Next())) {
    // check if the entry has specific storage
    AliCDBStorage* pStorage=NULL;
    TObject* pStorageId=pStorages->GetValue(pEntry->GetName());
    if (pStorageId) {
      pStorage=AliCDBManager::Instance()->GetStorage(pStorageId->GetName());
    } else {
      pStorage=AliCDBManager::Instance()->GetDefaultStorage();
    }

    // FIXME: this will fail as soon as we have several specific storages
    // access to the internal mapping information for specific storages is needed
    if (pStorage->GetLatestVersion(pEntry->GetName(), runNo)<0) {
      AliHLTLogging log;
      log.Logging(kHLTLogError, "CheckOCDBEntries", "CDB handling", "can not find required OCDB object %s for run number %d in storage %s", pEntry->GetName(), runNo, pStorage->GetURI().Data());
      iResult=-ENOENT;
    } else {
      AliHLTLogging log;
      log.Logging(kHLTLogDebug, "CheckOCDBEntries", "CDB handling", "found required OCDB object %s for run number %d in storage %s", pEntry->GetName(), runNo, pStorage->GetURI().Data());
    }
  }
  delete next;
  next=NULL;

  return iResult;
}

int AliHLTMiscImplementation::InitMagneticField() const
{
  // see header file for function documentation

  // BAD: unit test fails if I call TGeoGlobalMagField::Instance()
  // at this point. Something goes wrong in the cleaning of the global
  // ROOT onject
  /*
  if (TGeoGlobalMagField::Instance()->GetField()) {
    // everything set, but think about storing the currents for
    // a cross-check
    return 0;
  }
  */

  // The magnetic field is initialized once at the start
  // of run. The fields are supposed to be constant througout the
  // data taking of one run. The run is aborted if the changes
  // exceed a certain limit.
  AliGRPManager grpman;
  if (grpman.ReadGRPEntry() && grpman.SetMagField()) {
    return 0;
  }

  return -ENOENT;
}

AliHLTUInt64_t AliHLTMiscImplementation::GetTriggerMask(AliRawReader* rawReader) const
{
  // see header file for function documentation
  if (!rawReader) return 0;
  AliHLTUInt64_t trgMask=0;
  if (rawReader) {
    const UInt_t* pattern=rawReader->GetTriggerPattern();
    trgMask=pattern[1]&0xfffffff; // 28 upper bits of the 50 bit mask
    trgMask<<=32;
    trgMask|=pattern[0]; // 32 lower bits of the mask
  }
  return trgMask;
}

AliHLTUInt32_t AliHLTMiscImplementation::GetTimeStamp(AliRawReader* rawReader) const
{
  // extract time stamp of the event from the event header
  if (!rawReader) return 0;
  const AliRawEventHeaderBase* eventHeader = rawReader->GetEventHeader();
  if (!eventHeader) return 0;
  return eventHeader->Get("Timestamp");
}

AliHLTUInt32_t AliHLTMiscImplementation::GetEventType(AliRawReader* rawReader) const
{
  // extract event type from the event header
  if (!rawReader) return 0;
  const AliRawEventHeaderBase* eventHeader = rawReader->GetEventHeader();
  if (!eventHeader) return 0;
  return eventHeader->Get("Type");
}

const char* AliHLTMiscImplementation::GetBeamTypeFromGRP() const
{
  // get beam type from GRP
  return NULL;
}

Double_t AliHLTMiscImplementation::GetBz()
{
  // Returns Bz.
  return AliTracker::GetBz();
}

Double_t AliHLTMiscImplementation::GetBz(const Double_t *r)
{
  // Returns Bz (kG) at the point "r" .
  return AliTracker::GetBz(r);
}

void AliHLTMiscImplementation::GetBxByBz(const Double_t r[3], Double_t b[3])
{
  // Returns Bx, By and Bz (kG) at the point "r" .
  return AliTracker::GetBxByBz(r, b);
}

const TClass* AliHLTMiscImplementation::IsAliESDHLTDecision() const
{
  // Return the IsA of the AliESDHLTDecision class
#ifndef HAVE_NOT_ALIESDHLTDECISION
  return AliESDHLTDecision::Class();
#else // HAVE_NOT_ALIESDHLTDECISION
  return NULL;
#endif // HAVE_NOT_ALIESDHLTDECISION
}

int AliHLTMiscImplementation::Copy(const AliHLTGlobalTriggerDecision* pDecision, TObject* object) const
{
  // Copy HLT global trigger decision to AliESDHLTDecision container
  if (!pDecision || !object) return -EINVAL;
#ifndef HAVE_NOT_ALIESDHLTDECISION
  AliESDHLTDecision* pESDHLTDecision=NULL;
  if (object->IsA()==NULL ||
      object->IsA() != AliESDHLTDecision::Class() ||
      (pESDHLTDecision=dynamic_cast<AliESDHLTDecision*>(object))==NULL) {
//     HLTError("can not copy HLT global decision to object of class \"%s\"",
// 	     object->IsA()?object->IsA()->GetName():"NULL");
    return -EINVAL;
  }

  pESDHLTDecision->~AliESDHLTDecision();
  new (pESDHLTDecision) AliESDHLTDecision(pDecision->Result(), pDecision->GetTitle());

#endif // HAVE_NOT_ALIESDHLTDECISION
  return 0;
}

int AliHLTMiscImplementation::InitStreamerInfos(const char* ocdbEntry) const
{
  // init streamer infos for HLT reconstruction
  // Root schema evolution is not enabled for AliHLTMessage and all streamed objects.
  // Objects in the raw data payload rely on the availability of the correct stream info.
  // The relevant streamer info for a specific run is stored in the OCDB.
  int iResult=0;

  AliCDBEntry* pEntry=LoadOCDBEntry(ocdbEntry);
  TObject* pObject=NULL;
  if (pEntry && (pObject=ExtractObject(pEntry))!=NULL)
    {
    TObjArray* pSchemas=dynamic_cast<TObjArray*>(pObject);
    if (pSchemas) {
      iResult=InitStreamerInfos(pSchemas);
    } else {
      AliError(Form("internal mismatch in OCDB entry %s: wrong class type", ocdbEntry));
    }
  } else {
    AliWarning(Form("missing HLT reco data (%s), skipping initialization of streamer info for TObjects in HLT raw data payload", ocdbEntry));
  }
  return iResult;
}

int AliHLTMiscImplementation::InitStreamerInfos(TObjArray* pSchemas) const
{
  // init streamer infos for HLT reconstruction from an array of TStreamerInfo objects

  for (int i=0; i<pSchemas->GetEntriesFast(); i++) {
    if (pSchemas->At(i)) {
      TStreamerInfo* pSchema=dynamic_cast<TStreamerInfo*>(pSchemas->At(i));
      if (pSchema) {
	int version=pSchema->GetClassVersion();
	TClass* pClass=TClass::GetClass(pSchema->GetName());
	if (pClass) {
	  if (pClass->GetClassVersion()==version) {
	    AliDebug(0,Form("skipping schema definition %d version %d to class %s as this is the native version", i, version, pSchema->GetName()));
	    continue;
	  }
	  TObjArray* pInfos=pClass->GetStreamerInfos();
	  if (pInfos /*&& version<pInfos->GetEntriesFast()*/) {
	    if (pInfos->At(version)==NULL) {
	      TStreamerInfo* pClone=(TStreamerInfo*)pSchema->Clone();
	      if (pClone) {
		pClone->SetClass(pClass);
		pClone->BuildOld();
		pInfos->AddAtAndExpand(pClone, version);
		AliDebug(0,Form("adding schema definition %d version %d to class %s", i, version, pSchema->GetName()));
	      } else {
		AliError(Form("skipping schema definition %d (%s), unable to create clone object", i, pSchema->GetName()));
	      }
	    } else {
	      TStreamerInfo* pInfo=dynamic_cast<TStreamerInfo*>(pInfos->At(version));
	      if (pInfo && pInfo->GetClassVersion()==version) {
		AliDebug(0,Form("schema definition %d version %d already available in class %s, skipping ...", i, version, pSchema->GetName()));
	      } else {
		AliError(Form("can not verify version for already existing schema definition %d (%s) version %d: version of existing definition is %d", i, pSchema->GetName(), version, pInfo?pInfo->GetClassVersion():-1));
	      }
	    }
	  } else {
	    AliError(Form("skipping schema definition %d (%s), unable to set version %d in info array of size %d", i, pSchema->GetName(), version, pInfos?pInfos->GetEntriesFast():-1));
	  }
	} else {
	  AliError(Form("skipping schema definition %d (%s), unable to find class", i, pSchema->GetName()));
	}
      } else {
	AliError(Form("skipping schema definition %d, not of TStreamerInfo", i));
      }
    }
  }

  return 0;
}
<commit_msg>bugfix: CDBManager caching was overrun for objects on the GRID due to missing subversion bugfix: HLT/Calib/StreamerInfo could not be loaded because the run number was invalid in the request<commit_after>// $Id$

//**************************************************************************
//* This file is property of and copyright by the ALICE HLT Project        *
//* ALICE Experiment at CERN, All rights reserved.                         *
//*                                                                        *
//* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
//*                  for The ALICE HLT Project.                            *
//*                                                                        *
//* Permission to use, copy, modify and distribute this software and its   *
//* documentation strictly for non-commercial purposes is hereby granted   *
//* without fee, provided that the above copyright notice appears in all   *
//* copies and that both the copyright notice and this permission notice   *
//* appear in the supporting documentation. The authors make no claims     *
//* about the suitability of this software for any purpose. It is          *
//* provided "as is" without express or implied warranty.                  *
//**************************************************************************

/// @file   AliHLTMisc.cxx
/// @author Matthias Richter
/// @date
/// @brief  Miscellaneous methods for the HLT AliRoot integration

#include "AliHLTMiscImplementation.h"
#include "AliHLTLogging.h"
#include "AliLog.h"
#include "AliCDBManager.h"
#include "AliCDBStorage.h"
#include "AliCDBEntry.h"
#include "AliGRPManager.h"
#include "AliRawReader.h"
#include "AliRawEventHeaderBase.h"
#include "AliTracker.h"
#ifndef HAVE_NOT_ALIESDHLTDECISION
#include "AliESDHLTDecision.h"
#endif //HAVE_NOT_ALIESDHLTDECISION
#include "TGeoGlobalMagField.h"
#include "AliHLTGlobalTriggerDecision.h"
#include "TClass.h"
#include "TStreamerInfo.h"
#include "TObjArray.h"

/** ROOT macro for the implementation of ROOT specific class methods */
ClassImp(AliHLTMiscImplementation);

AliHLTMiscImplementation::AliHLTMiscImplementation()
{
}

AliHLTMiscImplementation::~AliHLTMiscImplementation()
{
  // see header file for function documentation
}

int AliHLTMiscImplementation::InitCDB(const char* cdbpath)
{
  // see header file for function documentation
  int iResult=0;
  AliCDBManager* pCDB = AliCDBManager::Instance();
  AliHLTLogging log;
  if (!pCDB) {
    log.Logging(kHLTLogError, "InitCDB", "CDB handling", "Could not get CDB instance");
  } else {
    if (cdbpath && cdbpath[0]!=0) {
      TString uri=cdbpath;
      if (!uri.BeginsWith("local://") &&
	  !uri.Contains("://")) {
	// assume a local path if no uri specifier is found
	uri="local://";
	uri+=cdbpath;
      }
      pCDB->SetDefaultStorage(uri);
      log.Logging(kHLTLogDebug, "InitCDB", "CDB handling", "CDB instance 0x%x", pCDB);
    } else if (!pCDB->IsDefaultStorageSet()) {
      const char* cdbUri="local://$ALICE_ROOT/OCDB";
      pCDB->SetDefaultStorage(cdbUri);
      pCDB->SetRun(0);
      log.Logging(kHLTLogInfo, "InitCDB", "CDB handling", "set default URI: %s", cdbUri);
    }
  }
  return iResult;
}

int AliHLTMiscImplementation::SetCDBRunNo(int runNo)
{
  // see header file for function documentation
  int iResult=0;
  AliCDBManager* pCDB = AliCDBManager::Instance();
  AliHLTLogging log;
  if (!pCDB) {
    log.Logging(kHLTLogError, "SetCDBRunNo", "CDB handling", "Could not get CDB instance");
  } else {
    pCDB->SetRun(runNo);
  }
  return iResult;
}

int AliHLTMiscImplementation::GetCDBRunNo() const
{
  // see header file for function documentation
  AliCDBManager* pCDB = AliCDBManager::Instance();
  AliHLTLogging log;
  if (!pCDB) {
    log.Logging(kHLTLogError, "SetCDBRunNo", "CDB handling", "Could not get CDB instance");
  } else {
    return pCDB->GetRun();
  }
  return -1;
}

AliCDBEntry* AliHLTMiscImplementation::LoadOCDBEntry(const char* path, int runNo, int version, int subVersion) const
{
  // see header file for function documentation
  AliCDBManager* man = AliCDBManager::Instance();
  if (!man) return NULL;
  if (runNo<0) runNo=man->GetRun();

  const char* uri=man->GetURI(path);
  if (!uri) return NULL;

  AliCDBStorage* store = AliCDBManager::Instance()->GetStorage(uri);
  if (!store) {
    return NULL;
  }

  TString strUri=store->GetURI();
  bool bIsGrid=strUri.BeginsWith("alien://");

  if (version<0) version = store->GetLatestVersion(path, runNo);

  // OCDB objects on GRID have no sub version
  if (subVersion<0 && !bIsGrid) subVersion = store->GetLatestSubVersion(path, runNo, version);
  AliCDBEntry* entry=man->Get(path, runNo, version, subVersion);
  if (entry) {
    // there seems to be a problem with the caching of objects in the CDBManager
    // regardless what version is specified it returns the object from the cache
    AliCDBId id=entry->GetId();
    if ((version<0 || id.GetVersion()==version) &&
	(subVersion<0 || id.GetSubVersion()==subVersion)) {
      // entry in the cache has the correct version
      return entry;
    }
  }
  return store->Get(path, runNo, version, subVersion);
}

TObject* AliHLTMiscImplementation::ExtractObject(AliCDBEntry* entry) const
{
  // see header file for function documentation
  if (!entry) return NULL;
  return entry->GetObject();
}

int AliHLTMiscImplementation::CheckOCDBEntries(const TMap* const pMap) const
{
  // check the availability of the OCDB entry descriptions in the TMap
  //  key : complete OCDB path of the entry
  //  value : auxiliary object - short description
  int iResult=0;
  if (!pMap) return -EINVAL;

  const TMap* pStorages=AliCDBManager::Instance()->GetStorageMap();
  Int_t runNo = GetCDBRunNo();

  TIterator* next=pMap->MakeIterator();
  if (!next) return -ENOENT;

  TObject* pEntry=NULL;
  while ((pEntry=next->Next())) {
    // check if the entry has specific storage
    AliCDBStorage* pStorage=NULL;
    TObject* pStorageId=pStorages->GetValue(pEntry->GetName());
    if (pStorageId) {
      pStorage=AliCDBManager::Instance()->GetStorage(pStorageId->GetName());
    } else {
      pStorage=AliCDBManager::Instance()->GetDefaultStorage();
    }

    // FIXME: this will fail as soon as we have several specific storages
    // access to the internal mapping information for specific storages is needed
    if (pStorage->GetLatestVersion(pEntry->GetName(), runNo)<0) {
      AliHLTLogging log;
      log.Logging(kHLTLogError, "CheckOCDBEntries", "CDB handling", "can not find required OCDB object %s for run number %d in storage %s", pEntry->GetName(), runNo, pStorage->GetURI().Data());
      iResult=-ENOENT;
    } else {
      AliHLTLogging log;
      log.Logging(kHLTLogDebug, "CheckOCDBEntries", "CDB handling", "found required OCDB object %s for run number %d in storage %s", pEntry->GetName(), runNo, pStorage->GetURI().Data());
    }
  }
  delete next;
  next=NULL;

  return iResult;
}

int AliHLTMiscImplementation::InitMagneticField() const
{
  // see header file for function documentation

  // BAD: unit test fails if I call TGeoGlobalMagField::Instance()
  // at this point. Something goes wrong in the cleaning of the global
  // ROOT onject
  /*
  if (TGeoGlobalMagField::Instance()->GetField()) {
    // everything set, but think about storing the currents for
    // a cross-check
    return 0;
  }
  */

  // The magnetic field is initialized once at the start
  // of run. The fields are supposed to be constant througout the
  // data taking of one run. The run is aborted if the changes
  // exceed a certain limit.
  AliGRPManager grpman;
  if (grpman.ReadGRPEntry() && grpman.SetMagField()) {
    return 0;
  }

  return -ENOENT;
}

AliHLTUInt64_t AliHLTMiscImplementation::GetTriggerMask(AliRawReader* rawReader) const
{
  // see header file for function documentation
  if (!rawReader) return 0;
  AliHLTUInt64_t trgMask=0;
  if (rawReader) {
    const UInt_t* pattern=rawReader->GetTriggerPattern();
    trgMask=pattern[1]&0xfffffff; // 28 upper bits of the 50 bit mask
    trgMask<<=32;
    trgMask|=pattern[0]; // 32 lower bits of the mask
  }
  return trgMask;
}

AliHLTUInt32_t AliHLTMiscImplementation::GetTimeStamp(AliRawReader* rawReader) const
{
  // extract time stamp of the event from the event header
  if (!rawReader) return 0;
  const AliRawEventHeaderBase* eventHeader = rawReader->GetEventHeader();
  if (!eventHeader) return 0;
  return eventHeader->Get("Timestamp");
}

AliHLTUInt32_t AliHLTMiscImplementation::GetEventType(AliRawReader* rawReader) const
{
  // extract event type from the event header
  if (!rawReader) return 0;
  const AliRawEventHeaderBase* eventHeader = rawReader->GetEventHeader();
  if (!eventHeader) return 0;
  return eventHeader->Get("Type");
}

const char* AliHLTMiscImplementation::GetBeamTypeFromGRP() const
{
  // get beam type from GRP
  return NULL;
}

Double_t AliHLTMiscImplementation::GetBz()
{
  // Returns Bz.
  return AliTracker::GetBz();
}

Double_t AliHLTMiscImplementation::GetBz(const Double_t *r)
{
  // Returns Bz (kG) at the point "r" .
  return AliTracker::GetBz(r);
}

void AliHLTMiscImplementation::GetBxByBz(const Double_t r[3], Double_t b[3])
{
  // Returns Bx, By and Bz (kG) at the point "r" .
  return AliTracker::GetBxByBz(r, b);
}

const TClass* AliHLTMiscImplementation::IsAliESDHLTDecision() const
{
  // Return the IsA of the AliESDHLTDecision class
#ifndef HAVE_NOT_ALIESDHLTDECISION
  return AliESDHLTDecision::Class();
#else // HAVE_NOT_ALIESDHLTDECISION
  return NULL;
#endif // HAVE_NOT_ALIESDHLTDECISION
}

int AliHLTMiscImplementation::Copy(const AliHLTGlobalTriggerDecision* pDecision, TObject* object) const
{
  // Copy HLT global trigger decision to AliESDHLTDecision container
  if (!pDecision || !object) return -EINVAL;
#ifndef HAVE_NOT_ALIESDHLTDECISION
  AliESDHLTDecision* pESDHLTDecision=NULL;
  if (object->IsA()==NULL ||
      object->IsA() != AliESDHLTDecision::Class() ||
      (pESDHLTDecision=dynamic_cast<AliESDHLTDecision*>(object))==NULL) {
//     HLTError("can not copy HLT global decision to object of class \"%s\"",
// 	     object->IsA()?object->IsA()->GetName():"NULL");
    return -EINVAL;
  }

  pESDHLTDecision->~AliESDHLTDecision();
  new (pESDHLTDecision) AliESDHLTDecision(pDecision->Result(), pDecision->GetTitle());

#endif // HAVE_NOT_ALIESDHLTDECISION
  return 0;
}

int AliHLTMiscImplementation::InitStreamerInfos(const char* ocdbEntry) const
{
  // init streamer infos for HLT reconstruction
  // Root schema evolution is not enabled for AliHLTMessage and all streamed objects.
  // Objects in the raw data payload rely on the availability of the correct stream info.
  // The relevant streamer info for a specific run is stored in the OCDB.
  int iResult=0;

  AliCDBEntry* pEntry=LoadOCDBEntry(ocdbEntry);
  TObject* pObject=NULL;
  if (pEntry && (pObject=ExtractObject(pEntry))!=NULL)
    {
    TObjArray* pSchemas=dynamic_cast<TObjArray*>(pObject);
    if (pSchemas) {
      iResult=InitStreamerInfos(pSchemas);
    } else {
      AliError(Form("internal mismatch in OCDB entry %s: wrong class type", ocdbEntry));
    }
  } else {
    AliWarning(Form("missing HLT reco data (%s), skipping initialization of streamer info for TObjects in HLT raw data payload", ocdbEntry));
  }
  return iResult;
}

int AliHLTMiscImplementation::InitStreamerInfos(TObjArray* pSchemas) const
{
  // init streamer infos for HLT reconstruction from an array of TStreamerInfo objects

  for (int i=0; i<pSchemas->GetEntriesFast(); i++) {
    if (pSchemas->At(i)) {
      TStreamerInfo* pSchema=dynamic_cast<TStreamerInfo*>(pSchemas->At(i));
      if (pSchema) {
	int version=pSchema->GetClassVersion();
	TClass* pClass=TClass::GetClass(pSchema->GetName());
	if (pClass) {
	  if (pClass->GetClassVersion()==version) {
	    AliDebug(0,Form("skipping schema definition %d version %d to class %s as this is the native version", i, version, pSchema->GetName()));
	    continue;
	  }
	  TObjArray* pInfos=pClass->GetStreamerInfos();
	  if (pInfos /*&& version<pInfos->GetEntriesFast()*/) {
	    if (pInfos->At(version)==NULL) {
	      TStreamerInfo* pClone=(TStreamerInfo*)pSchema->Clone();
	      if (pClone) {
		pClone->SetClass(pClass);
		pClone->BuildOld();
		pInfos->AddAtAndExpand(pClone, version);
		AliDebug(0,Form("adding schema definition %d version %d to class %s", i, version, pSchema->GetName()));
	      } else {
		AliError(Form("skipping schema definition %d (%s), unable to create clone object", i, pSchema->GetName()));
	      }
	    } else {
	      TStreamerInfo* pInfo=dynamic_cast<TStreamerInfo*>(pInfos->At(version));
	      if (pInfo && pInfo->GetClassVersion()==version) {
		AliDebug(0,Form("schema definition %d version %d already available in class %s, skipping ...", i, version, pSchema->GetName()));
	      } else {
		AliError(Form("can not verify version for already existing schema definition %d (%s) version %d: version of existing definition is %d", i, pSchema->GetName(), version, pInfo?pInfo->GetClassVersion():-1));
	      }
	    }
	  } else {
	    AliError(Form("skipping schema definition %d (%s), unable to set version %d in info array of size %d", i, pSchema->GetName(), version, pInfos?pInfos->GetEntriesFast():-1));
	  }
	} else {
	  AliError(Form("skipping schema definition %d (%s), unable to find class", i, pSchema->GetName()));
	}
      } else {
	AliError(Form("skipping schema definition %d, not of TStreamerInfo", i));
      }
    }
  }

  return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2003 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <ctype.h>
#include <fstream>
#include <iostream>
#include <list>
#include <string>
#include <vector>

#include "base/misc.hh"
#include "base/trace.hh"
#include "base/str.hh"

using namespace std;

namespace Trace {
const string DefaultName("global");
FlagVec flags(NumFlags, false);

//
// This variable holds the output stream for debug information.  Other
// than setting up/redirecting this stream, do *NOT* reference this
// directly; use DebugOut() (see below) to access this stream for
// output.
//
ostream *dprintf_stream = &cerr;

int dprintf_ignore_size;
vector<string> dprintf_ignore;
vector<vector<string> > ignore_tokens;
vector<int> ignore_size;

bool
dprintf_ignore_name(const string &name)
{
    vector<string> name_tokens;
    tokenize(name_tokens, name, '.');
    int ntsize = name_tokens.size();

    for (int i = 0; i < dprintf_ignore_size; ++i) {
        bool match = true;
        int jstop = ignore_size[i];
        for (int j = 0; j < jstop; ++j) {
            if (j >= ntsize)
                break;

            const string &ignore = ignore_tokens[i][j];
            if (ignore != "*" && ignore != name_tokens[j]) {
                match = false;
                break;
            }
        }

        if (match == true)
            return true;
    }

    return false;
}

Log theLog;

Log::Log()
{
    size = 0;
    buffer = NULL;
}

void
Log::init(int _size)
{
    if (buffer != NULL) {
        fatal("Trace::Log::init called twice!");
    }

    size = _size;

    buffer = new (Record *)[size];

    for (int i = 0; i < size; ++i) {
        buffer[i] = NULL;
    }

    nextRecPtr = &buffer[0];
    wrapRecPtr = &buffer[size];
}

Log::~Log()
{
    for (int i = 0; i < size; ++i) {
        delete buffer[i];
    }

    delete [] buffer;
}

void
Log::append(Record *rec)
{
    // dump record to output stream if there's one open
    if (dprintf_stream != NULL) {
        rec->dump(*dprintf_stream);
    }

    // no buffering: justget rid of it now
    if (buffer == NULL) {
        delete rec;
        return;
    }

    Record *oldRec = *nextRecPtr;

    if (oldRec != NULL) {
        // log has wrapped: overwrite
        delete oldRec;
    }

    *nextRecPtr = rec;

    if (++nextRecPtr == wrapRecPtr) {
        nextRecPtr = &buffer[0];
    }
}

void
Log::dump(ostream &os)
{
    if (buffer == NULL) {
        return;
    }

    Record **bufPtr = nextRecPtr;

    if (*bufPtr == NULL) {
        // next record slot is empty: log must not be full yet.
        // start dumping from beginning of buffer
        bufPtr = buffer;
    }

    do {
        Record *rec = *bufPtr;

        rec->dump(os);

        if (++bufPtr == wrapRecPtr) {
            bufPtr = &buffer[0];
        }
    } while (bufPtr != nextRecPtr);
}

PrintfRecord::~PrintfRecord()
{
    delete &args;
}

void
PrintfRecord::dump(ostream &os)
{
    string fmt = "";

    if (!name.empty()) {
        fmt = "%s: " + fmt;
        args.prepend(name);
    }

    if (cycle != (Tick)-1) {
        fmt = "%7d: " + fmt;
        args.prepend(cycle);
    }

    fmt += format;

    args.dump(os, fmt);
    os.flush();
}

RawDataRecord::RawDataRecord(Tick _cycle, const void *_data, int _len)
    : Record(_cycle), len(_len)
{
    data = new uint8_t[len];
    memcpy(data, _data, len);
}

RawDataRecord::~RawDataRecord()
{
    delete [] data;
}

void
RawDataRecord::dump(ostream &os)
{
    int c, i, j;

    for (i = 0; i < len; i += 16) {
        ccprintf(os, "%08x  ", i);
        c = len - i;
        if (c > 16) c = 16;

        for (j = 0; j < c; j++) {
            ccprintf(os, "%02x ", data[i + j] & 0xff);
            if ((j & 0xf) == 7 && j > 0)
                ccprintf(os, " ");
        }

        for (; j < 16; j++)
            ccprintf(os, "   ");
        ccprintf(os, "  ");

        for (j = 0; j < c; j++) {
            int ch = data[i + j] & 0x7f;
            ccprintf(os,
                     "%c", (char)(isprint(ch) ? ch : ' '));
        }

        ccprintf(os, "\n");

        if (c < 16)
            break;
    }
}
} // namespace Trace

//
// Returns the current output stream for debug information.  As a
// wrapper around Trace::dprintf_stream, this handles cases where debug
// information is generated in the process of parsing .ini options,
// before we process the option that sets up the debug output stream
// itself.
//
std::ostream &
DebugOut()
{
    return *Trace::dprintf_stream;
}

/////////////////////////////////////////////
//
// C-linkage functions for invoking from gdb
//
/////////////////////////////////////////////

//
// Dump trace buffer to specified file (cout if NULL)
//
extern "C"
void
dumpTrace(const char *filename)
{
    if (filename != NULL) {
        ofstream out(filename);
        Trace::theLog.dump(out);
        out.close();
    }
    else {
        Trace::theLog.dump(cout);
    }
}

//
// Turn on/off trace output to cerr.  Typically used when trace output
// is only going to circular buffer, but you want to see what's being
// sent there as you step through some code in gdb.  This uses the
// same facility as the "trace to file" feature, and will print error
// messages rather than clobbering an existing ostream pointer.
//
extern "C"
void
echoTrace(bool on)
{
    if (on) {
        if (Trace::dprintf_stream != NULL) {
            cerr << "Already echoing trace to a file... go do a 'tail -f'"
                 << " on that file instead." << endl;
        } else {
            Trace::dprintf_stream = &cerr;
        }
    } else {
        if (Trace::dprintf_stream != &cerr) {
            cerr << "Not echoing trace to cerr." << endl;
        } else {
            Trace::dprintf_stream = NULL;
        }
    }
}
<commit_msg>more debugging support<commit_after>/*
 * Copyright (c) 2003 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <ctype.h>
#include <fstream>
#include <iostream>
#include <list>
#include <string>
#include <vector>

#include "base/misc.hh"
#include "base/trace.hh"
#include "base/str.hh"

using namespace std;

namespace Trace {
const string DefaultName("global");
FlagVec flags(NumFlags, false);

//
// This variable holds the output stream for debug information.  Other
// than setting up/redirecting this stream, do *NOT* reference this
// directly; use DebugOut() (see below) to access this stream for
// output.
//
ostream *dprintf_stream = &cerr;

int dprintf_ignore_size;
vector<string> dprintf_ignore;
vector<vector<string> > ignore_tokens;
vector<int> ignore_size;

bool
dprintf_ignore_name(const string &name)
{
    vector<string> name_tokens;
    tokenize(name_tokens, name, '.');
    int ntsize = name_tokens.size();

    for (int i = 0; i < dprintf_ignore_size; ++i) {
        bool match = true;
        int jstop = ignore_size[i];
        for (int j = 0; j < jstop; ++j) {
            if (j >= ntsize)
                break;

            const string &ignore = ignore_tokens[i][j];
            if (ignore != "*" && ignore != name_tokens[j]) {
                match = false;
                break;
            }
        }

        if (match == true)
            return true;
    }

    return false;
}

Log theLog;

Log::Log()
{
    size = 0;
    buffer = NULL;
}

void
Log::init(int _size)
{
    if (buffer != NULL) {
        fatal("Trace::Log::init called twice!");
    }

    size = _size;

    buffer = new (Record *)[size];

    for (int i = 0; i < size; ++i) {
        buffer[i] = NULL;
    }

    nextRecPtr = &buffer[0];
    wrapRecPtr = &buffer[size];
}

Log::~Log()
{
    for (int i = 0; i < size; ++i) {
        delete buffer[i];
    }

    delete [] buffer;
}

void
Log::append(Record *rec)
{
    // dump record to output stream if there's one open
    if (dprintf_stream != NULL) {
        rec->dump(*dprintf_stream);
    }

    // no buffering: justget rid of it now
    if (buffer == NULL) {
        delete rec;
        return;
    }

    Record *oldRec = *nextRecPtr;

    if (oldRec != NULL) {
        // log has wrapped: overwrite
        delete oldRec;
    }

    *nextRecPtr = rec;

    if (++nextRecPtr == wrapRecPtr) {
        nextRecPtr = &buffer[0];
    }
}

void
Log::dump(ostream &os)
{
    if (buffer == NULL) {
        return;
    }

    Record **bufPtr = nextRecPtr;

    if (*bufPtr == NULL) {
        // next record slot is empty: log must not be full yet.
        // start dumping from beginning of buffer
        bufPtr = buffer;
    }

    do {
        Record *rec = *bufPtr;

        rec->dump(os);

        if (++bufPtr == wrapRecPtr) {
            bufPtr = &buffer[0];
        }
    } while (bufPtr != nextRecPtr);
}

PrintfRecord::~PrintfRecord()
{
    delete &args;
}

void
PrintfRecord::dump(ostream &os)
{
    string fmt = "";

    if (!name.empty()) {
        fmt = "%s: " + fmt;
        args.prepend(name);
    }

    if (cycle != (Tick)-1) {
        fmt = "%7d: " + fmt;
        args.prepend(cycle);
    }

    fmt += format;

    args.dump(os, fmt);
    os.flush();
}

RawDataRecord::RawDataRecord(Tick _cycle, const void *_data, int _len)
    : Record(_cycle), len(_len)
{
    data = new uint8_t[len];
    memcpy(data, _data, len);
}

RawDataRecord::~RawDataRecord()
{
    delete [] data;
}

void
RawDataRecord::dump(ostream &os)
{
    int c, i, j;

    for (i = 0; i < len; i += 16) {
        ccprintf(os, "%08x  ", i);
        c = len - i;
        if (c > 16) c = 16;

        for (j = 0; j < c; j++) {
            ccprintf(os, "%02x ", data[i + j] & 0xff);
            if ((j & 0xf) == 7 && j > 0)
                ccprintf(os, " ");
        }

        for (; j < 16; j++)
            ccprintf(os, "   ");
        ccprintf(os, "  ");

        for (j = 0; j < c; j++) {
            int ch = data[i + j] & 0x7f;
            ccprintf(os,
                     "%c", (char)(isprint(ch) ? ch : ' '));
        }

        ccprintf(os, "\n");

        if (c < 16)
            break;
    }
}
} // namespace Trace

//
// Returns the current output stream for debug information.  As a
// wrapper around Trace::dprintf_stream, this handles cases where debug
// information is generated in the process of parsing .ini options,
// before we process the option that sets up the debug output stream
// itself.
//
std::ostream &
DebugOut()
{
    return *Trace::dprintf_stream;
}

/////////////////////////////////////////////
//
// C-linkage functions for invoking from gdb
//
/////////////////////////////////////////////

//
// Dump trace buffer to specified file (cout if NULL)
//
extern "C"
void
dumpTrace(const char *filename)
{
    if (filename != NULL) {
        ofstream out(filename);
        Trace::theLog.dump(out);
        out.close();
    }
    else {
        Trace::theLog.dump(cout);
    }
}

//
// Turn on/off trace output to cerr.  Typically used when trace output
// is only going to circular buffer, but you want to see what's being
// sent there as you step through some code in gdb.  This uses the
// same facility as the "trace to file" feature, and will print error
// messages rather than clobbering an existing ostream pointer.
//
extern "C"
void
echoTrace(bool on)
{
    if (on) {
        if (Trace::dprintf_stream != NULL) {
            cerr << "Already echoing trace to a file... go do a 'tail -f'"
                 << " on that file instead." << endl;
        } else {
            Trace::dprintf_stream = &cerr;
        }
    } else {
        if (Trace::dprintf_stream != &cerr) {
            cerr << "Not echoing trace to cerr." << endl;
        } else {
            Trace::dprintf_stream = NULL;
        }
    }
}

extern "C"
void
printTraceFlags()
{
    using namespace Trace;
    for (int i = 0; i < numFlagStrings; ++i)
        if (flags[i])
            cprintf("%s\n", flagStrings[i]);
}

void
tweakTraceFlag(const char *string, bool value)
{
    using namespace Trace;
    std::string str(string);

    for (int i = 0; i < numFlagStrings; ++i) {
        if (str != flagStrings[i])
            continue;

        int idx = i;

        if (idx < NumFlags) {
            flags[idx] = value;
        } else {
            idx -= NumFlags;
            if (idx >= NumCompoundFlags) {
                ccprintf(cerr, "Invalid compound flag");
                return;
            }

            const Flags *flagVec = compoundFlags[idx];

            for (int j = 0; flagVec[j] != -1; ++j) {
                if (flagVec[j] >= NumFlags) {
                    ccprintf(cerr, "Invalid compound flag");
                    return;
                }
                flags[flagVec[j]] = value;
            }
        }

        cprintf("flag %s was %s\n", string, value ? "set" : "cleared");
        return;
    }

    cprintf("could not find flag %s\n", string);
}

extern "C"
void
setTraceFlag(const char *string)
{
    tweakTraceFlag(string, true);
}

extern "C"
void
clearTraceFlag(const char *string)
{
    tweakTraceFlag(string, false);
}
<|endoftext|>