<commit_before>/***************************************************************
 *
 * Copyright (C) 1990-2015, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.	You may
 * obtain a copy of the License at
 *
 *		http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

#include "condor_common.h"
#include "condor_attributes.h"
#include "condor_classad.h"
#include "condor_config.h"
#include "condor_constants.h"
#include "condor_uid.h"
#include "condor_md.h"
#include "directory_util.h"
#include "file_lock.h"
#include "filename_tools.h"
#include "stat_wrapper.h"
#include <sys/stat.h>
#include <stdlib.h>
#include <string>

#ifndef WIN32
	#include <unistd.h>
#endif

#ifdef HAVE_HTTP_PUBLIC_FILES

using namespace std;

namespace {	// Anonymous namespace to limit scope of names to this file

const int HASHNAMELEN = 17;

static string MakeHashName(const char* fileName, time_t fileModifiedTime) {

	unsigned char hashResult[HASHNAMELEN * 3]; // Allocate extra space for safety.

	// Convert the modified time to a string object
	std::string modifiedTimeStr = std::to_string((long long int) fileModifiedTime);

	// Create a new string which will be the source for our hash function.
	// This will append two strings:
	// 1. Full path to the file
	// 2. Modified time of the file
	unsigned char* hashSource = new unsigned char[strlen(fileName)
									+ strlen(modifiedTimeStr.c_str()) + 1];
	strcpy( (char*) hashSource, fileName );
	strcat( (char*) hashSource, modifiedTimeStr.c_str() );

	// Now calculate the hash
	memcpy(hashResult, Condor_MD_MAC::computeOnce(hashSource,
		strlen((const char*) hashSource)), HASHNAMELEN);
	char entryHashName[HASHNAMELEN * 2]; // 2 chars per hex byte
	entryHashName[0] = '\0';
	char letter[3];
	for (int i = 0; i < HASHNAMELEN - 1; ++i) {
		sprintf(letter, "%x", hashResult[i]);
		strcat(entryHashName, letter);
	}

	return entryHashName;
}

// WARNING!  This code changes priv state.  Be very careful if modifying it.
// Do not return in the block of code where the priv has been set to either
// condor or root.  -zmiller
static bool MakeLink(const char* srcFilePath, const string &newLink) {

	bool retVal = false;
	int srcFileInodeNum;
	int targetLinkInodeNum;
	struct stat srcFileStat;
	struct stat targetLinkStat;

	// Make sure the necessary parameters are set
	std::string webRootDir;
	param(webRootDir, "HTTP_PUBLIC_FILES_ROOT_DIR");
	if(webRootDir.empty()) {
		dprintf(D_ALWAYS, "mk_cache_links.cpp: HTTP_PUBLIC_FILES_ROOT_DIR "
						"not set! Falling back to regular file transfer\n");
		return (false);
	}
	std::string webRootOwner;
	param(webRootOwner, "HTTP_PUBLIC_FILES_ROOT_OWNER");
	if(webRootOwner.empty()) {
		dprintf(D_ALWAYS, "mk_cache_links.cpp: HTTP_PUBLIC_FILES_ROOT_OWNER "
						"not set! Falling back to regular file transfer\n");
		return (false);
	}
	char goodPath[PATH_MAX];
	if (realpath(webRootDir.c_str(), goodPath) == NULL) {
		dprintf(D_ALWAYS, "mk_cache_links.cpp: HTTP_PUBLIC_FILES_ROOT_DIR "
			"not a valid path: %s. Falling back to regular file transfer.\n",
			webRootDir.c_str());
		return (false);
	}

	// Determine the full path of the access file. Save it to a std::string and
	// deallocate the memory that dircat() returned.
	char* hardLinkFilePath = dircat(goodPath, newLink.c_str());
	std::string accessFilePath(hardLinkFilePath);
	accessFilePath += ".access";
	delete [] hardLinkFilePath;

	// STARTING HERE, DO NOT RETURN FROM THIS FUNCTION WITHOUT RESETTING
	// THE ORIGINAL PRIV STATE.

	// Check if an access file exists (which will be the case if someone has
	// already sent the source file).
	// If it does exist, lock it so that condor_preen cannot open it while
	// garbage collecting.
	// If it does not exist, carry on. We'll create it before exiting.

	priv_state original_priv = set_root_priv();
	FileLock *accessFileLock = NULL;

	if(access(accessFilePath.c_str(), F_OK) == 0) {
		accessFileLock = new FileLock(accessFilePath.c_str(), true, false);

		// Try to grab a lock on the access file. This should block until it
		// obtains the lock. If this fails for any reason, bail out.
		bool obtainedLock = accessFileLock->obtain(WRITE_LOCK);
		if(!obtainedLock) {
			dprintf(D_ALWAYS, "MakeLink: Failed to obtain lock on access file with"
				" error code %d (%s).\n", errno, strerror(errno));
			set_priv(original_priv);
			return (false);
		}
	}

	// Impersonate the user and open the file using safe_open(). This will allow
	// us to verify the user has privileges to access the file, and later to
	// verify the hard link points back to the same inode.
	set_user_priv();

	bool fileOK = false;
	FILE *srcFile = safe_fopen_wrapper(srcFilePath, "r");
	if (srcFile) {
		if(stat(srcFilePath, &srcFileStat) == 0) {
			srcFileInodeNum = srcFileStat.st_ino;
			fileOK = (srcFileStat.st_mode & S_IRUSR); // Verify readable by owner
		}
	}
	if (fileOK == false) {
		dprintf(D_ALWAYS, "MakeLink: Cannot transfer -- public input file not "
			"readable by user: %s\n", srcFilePath);
		set_priv(original_priv);
		return (false);
	}
	fclose(srcFile);

	// Create the hard link using root privileges; it will automatically get
	// owned by the same owner of the file. If the link already exists, don't do
	// anything at this point, we'll check later to make sure it points to the
	// correct inode.
	const char *const targetLinkPath = dircat(goodPath, newLink.c_str()); // needs to be freed

	// Switch to root privileges, so we can test if the link exists, and create
	// it if it does not
	set_root_priv();

	// Check if target link already exists
	FILE *targetLink = safe_fopen_wrapper(targetLinkPath, "r");
	if (targetLink) {
		// If link exists, update the .access file timestamp.
		retVal = true;
		fclose(targetLink);
	}
	else {
		// Link does not exist, so create it as root.
		if (link(srcFilePath, targetLinkPath) == 0) {
			// so far, so good!
			retVal = true;
		}
		else {
			dprintf(D_ALWAYS, "MakeLink: Could not link %s to %s, error: %s\n",
				targetLinkPath, srcFilePath, strerror(errno));
		}
	}

	// Now we need to make sure nothing devious has happened, that the hard link
	// points to the file we're expecting. First, make sure that the user
	// specified by HTTP_PUBLIC_FILES_ROOT_OWNER is a valid user.
	uid_t link_uid = -1;
	gid_t link_gid = -1;
	bool isValidUser = pcache()->get_user_ids(webRootOwner.c_str(), link_uid, link_gid);
	if (!isValidUser) {
		dprintf(D_ALWAYS, "Unable to look up HTTP_PUBLIC_FILES_ROOT_OWNER (%s)"
				" in /etc/passwd. Aborting.\n", webRootOwner.c_str());
		retVal = false;
	}

	if (link_uid == 0 || link_gid == 0) {
		dprintf(D_ALWAYS, "HTTP_PUBLIC_FILES_ROOT_OWNER (%s)"
			" in /etc/passwd has UID 0.  Aborting.\n", webRootOwner.c_str());
		retVal = false;
	}

	// Now that we've verified HTTP_PUBLIC_FILES_ROOT_OWNER is a valid user,
	// switch privileges to this user. Open the hard link. Verify that the
	// inode is the same as the file we opened earlier on.
	if (retVal == true) {
		if(setegid(link_gid) == -1) {
			dprintf(D_ALWAYS, "MakeLink: Error switching to group ID %d\n", link_gid);
			retVal = false;
		}
		if(seteuid(link_uid) == -1) {
			dprintf(D_ALWAYS, "MakeLink: Error switching to user ID %d\n", link_uid);
			retVal = false;
		}

		if (stat(targetLinkPath, &targetLinkStat) == 0) {
			targetLinkInodeNum = targetLinkStat.st_ino;
			if (srcFileInodeNum == targetLinkInodeNum) {
				retVal = true;
			}
			else {
				dprintf(D_ALWAYS, "Source file %s inode (%d) does not match "
					"hard link %s inode (%d), aborting.\n", srcFilePath,
					srcFileInodeNum, targetLinkPath, targetLinkInodeNum);
			}
		}
		else {
			retVal = false;
			dprintf(D_ALWAYS, "Cannot open hard link %s as user %s. Reverting to "
				"regular file transfer.\n", targetLinkPath, webRootOwner.c_str());
		}
	}

	// Touch the access file. This will create it if it doesn't exist, or update
	// the timestamp if it does.
	FILE* accessFile = fopen(accessFilePath.c_str(), "w");
	if (!accessFile) {
		dprintf(D_ALWAYS, "Failed to update access file %s.\n", accessFilePath.c_str());
	}
	fclose(accessFile);

	// Release the lock on the access file
	if(!accessFileLock->release()) {
		dprintf(D_ALWAYS, "MakeLink: Failed to release lock on access file with"
			" error code %d (%s).\n", errno, strerror(errno));
	}

	// Free the target link path
	delete [] targetLinkPath;

	// Reset priv state
	set_priv(original_priv);

	return retVal;
}

static string MakeAbsolutePath(const char* path, const char* initialWorkingDir) {
	if (is_relative_to_cwd(path)) {
		string fullPath = initialWorkingDir;
		fullPath += DIR_DELIM_CHAR;
		fullPath += path;
		return (fullPath);
	}
	return (path);
}

} // end namespace

void ProcessCachedInpFiles(ClassAd *const Ad, StringList *const InputFiles,
	StringList &PubInpFiles) {

	char *initialWorkingDir = NULL;
	const char *path;
	MyString remap;
	struct stat fileStat;
	time_t fileModifiedTime = time(NULL);

	if (PubInpFiles.isEmpty() == false) {
		const char *webServerAddress = param("HTTP_PUBLIC_FILES_ADDRESS");

		// If a web server address is not defined, exit quickly. The file
		// transfer will go on using the regular CEDAR protocol.
		if(!webServerAddress) {
			dprintf(D_FULLDEBUG, "mk_cache_links.cpp: HTTP_PUBLIC_FILES_ADDRESS "
							"not set! Falling back to regular file transfer\n");
			return;
		}

		// Build out the base URL for public files
		string url = "http://";
		url += webServerAddress;
		url += "/";

		PubInpFiles.rewind();

		if (Ad->LookupString(ATTR_JOB_IWD, &initialWorkingDir) != 1) {
			dprintf(D_FULLDEBUG, "mk_cache_links.cpp: Job ad did not have an "
				"initialWorkingDir! Falling back to regular file transfer\n");
			return;
		}
		while ((path = PubInpFiles.next()) != NULL) {
			// Determine the full path of the file to be transferred
			string fullPath = MakeAbsolutePath(path, initialWorkingDir);

			// Determine the time last modified of the file to be transferred
			if( stat( fullPath.c_str(), &fileStat ) == 0 ) {
				struct timespec fileTime = fileStat.st_mtim;
				fileModifiedTime = fileTime.tv_sec;
			}
			else {
				dprintf(D_FULLDEBUG, "mk_cache_links.cpp: Unable to access file "
					"%s. Falling back to regular file transfer\n", fullPath.c_str());
				free( initialWorkingDir );
				return;
			}

			string hashName = MakeHashName( fullPath.c_str(), fileModifiedTime );
			if (MakeLink(fullPath.c_str(), hashName)) {
				InputFiles->remove(path); // Remove plain file name from InputFiles
				remap += hashName;
				remap += "=";
				remap += basename(path);
				remap += ";";
				hashName = url + hashName;
				const char *const namePtr = hashName.c_str();
				if ( !InputFiles->contains(namePtr) ) {
					InputFiles->append(namePtr);
					dprintf(D_FULLDEBUG, "mk_cache_links.cpp: Adding url to "
												"InputFiles: %s\n", namePtr);
				}
				else dprintf(D_FULLDEBUG, "mk_cache_links.cpp: url already "
											"in InputFiles: %s\n", namePtr);
			}
			else {
				dprintf(D_FULLDEBUG, "mk_cache_links.cpp: Failed to generate "
									 "hash link for %s\n", fullPath.c_str());
			}
		}
		free( initialWorkingDir );
		if ( remap.Length() > 0 ) {
			MyString remapnew;
			char *buf = NULL;
			if (Ad->LookupString(ATTR_TRANSFER_INPUT_REMAPS, &buf) == 1) {
				remapnew = buf;
				free(buf);
				buf = NULL;
				remapnew += ";";
			}
			remapnew += remap;
			if (Ad->Assign(ATTR_TRANSFER_INPUT_REMAPS, remap.Value()) == false) {
				dprintf(D_ALWAYS, "mk_cache_links.cpp: Could not add to jobAd: "
													"%s\n", remap.c_str());
			}
		}
	}
	else
		dprintf(D_FULLDEBUG, "mk_cache_links.cpp: No public input files.\n");
}

#endif

<commit_msg>More Coverity fixes (#6452)<commit_after>/***************************************************************
 *
 * Copyright (C) 1990-2015, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.	You may
 * obtain a copy of the License at
 *
 *		http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

#include "condor_common.h"
#include "condor_attributes.h"
#include "condor_classad.h"
#include "condor_config.h"
#include "condor_constants.h"
#include "condor_uid.h"
#include "condor_md.h"
#include "directory_util.h"
#include "file_lock.h"
#include "filename_tools.h"
#include "stat_wrapper.h"
#include <sys/stat.h>
#include <stdlib.h>
#include <string>

#ifndef WIN32
	#include <unistd.h>
#endif

#ifdef HAVE_HTTP_PUBLIC_FILES

using namespace std;

namespace {	// Anonymous namespace to limit scope of names to this file

const int HASHNAMELEN = 17;

static string MakeHashName(const char* fileName, time_t fileModifiedTime) {

	unsigned char hashResult[HASHNAMELEN * 3]; // Allocate extra space for safety.

	// Convert the modified time to a string object
	std::string modifiedTimeStr = std::to_string((long long int) fileModifiedTime);

	// Create a new string which will be the source for our hash function.
	// This will append two strings:
	// 1. Full path to the file
	// 2. Modified time of the file
	unsigned char* hashSource = new unsigned char[strlen(fileName)
									+ strlen(modifiedTimeStr.c_str()) + 1];
	strcpy( (char*) hashSource, fileName );
	strcat( (char*) hashSource, modifiedTimeStr.c_str() );

	// Now calculate the hash
	memcpy(hashResult, Condor_MD_MAC::computeOnce(hashSource,
		strlen((const char*) hashSource)), HASHNAMELEN);
	char entryHashName[HASHNAMELEN * 2]; // 2 chars per hex byte
	entryHashName[0] = '\0';
	char letter[3];
	for (int i = 0; i < HASHNAMELEN - 1; ++i) {
		sprintf(letter, "%x", hashResult[i]);
		strcat(entryHashName, letter);
	}

	return entryHashName;
}

// WARNING!  This code changes priv state.  Be very careful if modifying it.
// Do not return in the block of code where the priv has been set to either
// condor or root.  -zmiller
static bool MakeLink(const char* srcFilePath, const string &newLink) {

	bool retVal = false;
	int srcFileInodeNum;
	int targetLinkInodeNum;
	struct stat srcFileStat;
	struct stat targetLinkStat;

	// Make sure the necessary parameters are set
	std::string webRootDir;
	param(webRootDir, "HTTP_PUBLIC_FILES_ROOT_DIR");
	if(webRootDir.empty()) {
		dprintf(D_ALWAYS, "mk_cache_links.cpp: HTTP_PUBLIC_FILES_ROOT_DIR "
						"not set! Falling back to regular file transfer\n");
		return (false);
	}
	std::string webRootOwner;
	param(webRootOwner, "HTTP_PUBLIC_FILES_ROOT_OWNER");
	if(webRootOwner.empty()) {
		dprintf(D_ALWAYS, "mk_cache_links.cpp: HTTP_PUBLIC_FILES_ROOT_OWNER "
						"not set! Falling back to regular file transfer\n");
		return (false);
	}
	char goodPath[PATH_MAX];
	if (realpath(webRootDir.c_str(), goodPath) == NULL) {
		dprintf(D_ALWAYS, "mk_cache_links.cpp: HTTP_PUBLIC_FILES_ROOT_DIR "
			"not a valid path: %s. Falling back to regular file transfer.\n",
			webRootDir.c_str());
		return (false);
	}

	// Determine the full path of the access file. Save it to a std::string and
	// deallocate the memory that dircat() returned.
	char* hardLinkFilePath = dircat(goodPath, newLink.c_str());
	std::string accessFilePath(hardLinkFilePath);
	accessFilePath += ".access";
	delete [] hardLinkFilePath;

	// STARTING HERE, DO NOT RETURN FROM THIS FUNCTION WITHOUT RESETTING
	// THE ORIGINAL PRIV STATE.

	// Check if an access file exists (which will be the case if someone has
	// already sent the source file).
	// If it does exist, lock it so that condor_preen cannot open it while
	// garbage collecting.
	// If it does not exist, carry on. We'll create it before exiting.

	priv_state original_priv = set_root_priv();
	FileLock *accessFileLock = NULL;

	if(access(accessFilePath.c_str(), F_OK) == 0) {
		accessFileLock = new FileLock(accessFilePath.c_str(), true, false);

		// Try to grab a lock on the access file. This should block until it
		// obtains the lock. If this fails for any reason, bail out.
		bool obtainedLock = accessFileLock->obtain(WRITE_LOCK);
		if(!obtainedLock) {
			dprintf(D_ALWAYS, "MakeLink: Failed to obtain lock on access file with"
				" error code %d (%s).\n", errno, strerror(errno));
			set_priv(original_priv);
			return (false);
		}
	}

	// Impersonate the user and open the file using safe_open(). This will allow
	// us to verify the user has privileges to access the file, and later to
	// verify the hard link points back to the same inode.
	set_user_priv();

	bool fileOK = false;
	FILE *srcFile = safe_fopen_wrapper(srcFilePath, "r");
	if (srcFile) {
		if(stat(srcFilePath, &srcFileStat) == 0) {
			srcFileInodeNum = srcFileStat.st_ino;
			fileOK = (srcFileStat.st_mode & S_IRUSR); // Verify readable by owner
		}
	}
	if (fileOK == false) {
		dprintf(D_ALWAYS, "MakeLink: Cannot transfer -- public input file not "
			"readable by user: %s\n", srcFilePath);
		set_priv(original_priv);
		return (false);
	}
	fclose(srcFile);

	// Create the hard link using root privileges; it will automatically get
	// owned by the same owner of the file. If the link already exists, don't do
	// anything at this point, we'll check later to make sure it points to the
	// correct inode.
	const char *const targetLinkPath = dircat(goodPath, newLink.c_str()); // needs to be freed

	// Switch to root privileges, so we can test if the link exists, and create
	// it if it does not
	set_root_priv();

	// Check if target link already exists
	FILE *targetLink = safe_fopen_wrapper(targetLinkPath, "r");
	if (targetLink) {
		// If link exists, update the .access file timestamp.
		retVal = true;
		delete [] targetLinkPath;
		fclose(targetLink);
	}
	else {
		// Link does not exist, so create it as root.
		if (link(srcFilePath, targetLinkPath) == 0) {
			// so far, so good!
			retVal = true;
		}
		else {
			dprintf(D_ALWAYS, "MakeLink: Could not link %s to %s, error: %s\n",
				targetLinkPath, srcFilePath, strerror(errno));
		}
	}

	// Now we need to make sure nothing devious has happened, that the hard link
	// points to the file we're expecting. First, make sure that the user
	// specified by HTTP_PUBLIC_FILES_ROOT_OWNER is a valid user.
	uid_t link_uid = -1;
	gid_t link_gid = -1;
	bool isValidUser = pcache()->get_user_ids(webRootOwner.c_str(), link_uid, link_gid);
	if (!isValidUser) {
		dprintf(D_ALWAYS, "Unable to look up HTTP_PUBLIC_FILES_ROOT_OWNER (%s)"
				" in /etc/passwd. Aborting.\n", webRootOwner.c_str());
		retVal = false;
	}

	if (link_uid == 0 || link_gid == 0) {
		dprintf(D_ALWAYS, "HTTP_PUBLIC_FILES_ROOT_OWNER (%s)"
			" in /etc/passwd has UID 0.  Aborting.\n", webRootOwner.c_str());
		retVal = false;
	}

	// Now that we've verified HTTP_PUBLIC_FILES_ROOT_OWNER is a valid user,
	// switch privileges to this user. Open the hard link. Verify that the
	// inode is the same as the file we opened earlier on.
	if (retVal == true) {
		if(setegid(link_gid) == -1) {
			dprintf(D_ALWAYS, "MakeLink: Error switching to group ID %d\n", link_gid);
			retVal = false;
		}
		if(seteuid(link_uid) == -1) {
			dprintf(D_ALWAYS, "MakeLink: Error switching to user ID %d\n", link_uid);
			retVal = false;
		}

		if (stat(targetLinkPath, &targetLinkStat) == 0) {
			targetLinkInodeNum = targetLinkStat.st_ino;
			if (srcFileInodeNum == targetLinkInodeNum) {
				retVal = true;
			}
			else {
				dprintf(D_ALWAYS, "Source file %s inode (%d) does not match "
					"hard link %s inode (%d), aborting.\n", srcFilePath,
					srcFileInodeNum, targetLinkPath, targetLinkInodeNum);
			}
		}
		else {
			retVal = false;
			dprintf(D_ALWAYS, "Cannot open hard link %s as user %s. Reverting to "
				"regular file transfer.\n", targetLinkPath, webRootOwner.c_str());
		}
	}

	// Touch the access file. This will create it if it doesn't exist, or update
	// the timestamp if it does.
	FILE* accessFile = fopen(accessFilePath.c_str(), "w");
	if (accessFile) {
		fclose(accessFile);
	}
	else {
		dprintf(D_ALWAYS, "Failed to update access file %s.\n", accessFilePath.c_str());
	}

	// Release the lock on the access file
	if(!accessFileLock->release()) {
		dprintf(D_ALWAYS, "MakeLink: Failed to release lock on access file with"
			" error code %d (%s).\n", errno, strerror(errno));
	}

	// Free the target link path
	delete [] targetLinkPath;

	// Reset priv state
	set_priv(original_priv);

	return retVal;
}

static string MakeAbsolutePath(const char* path, const char* initialWorkingDir) {
	if (is_relative_to_cwd(path)) {
		string fullPath = initialWorkingDir;
		fullPath += DIR_DELIM_CHAR;
		fullPath += path;
		return (fullPath);
	}
	return (path);
}

} // end namespace

void ProcessCachedInpFiles(ClassAd *const Ad, StringList *const InputFiles,
	StringList &PubInpFiles) {

	char *initialWorkingDir = NULL;
	const char *path;
	MyString remap;
	struct stat fileStat;
	time_t fileModifiedTime = time(NULL);

	if (PubInpFiles.isEmpty() == false) {
		const char *webServerAddress = param("HTTP_PUBLIC_FILES_ADDRESS");

		// If a web server address is not defined, exit quickly. The file
		// transfer will go on using the regular CEDAR protocol.
		if(!webServerAddress) {
			dprintf(D_FULLDEBUG, "mk_cache_links.cpp: HTTP_PUBLIC_FILES_ADDRESS "
							"not set! Falling back to regular file transfer\n");
			return;
		}

		// Build out the base URL for public files
		string url = "http://";
		url += webServerAddress;
		url += "/";

		PubInpFiles.rewind();

		if (Ad->LookupString(ATTR_JOB_IWD, &initialWorkingDir) != 1) {
			dprintf(D_FULLDEBUG, "mk_cache_links.cpp: Job ad did not have an "
				"initialWorkingDir! Falling back to regular file transfer\n");
			return;
		}
		while ((path = PubInpFiles.next()) != NULL) {
			// Determine the full path of the file to be transferred
			string fullPath = MakeAbsolutePath(path, initialWorkingDir);

			// Determine the time last modified of the file to be transferred
			if( stat( fullPath.c_str(), &fileStat ) == 0 ) {
				struct timespec fileTime = fileStat.st_mtim;
				fileModifiedTime = fileTime.tv_sec;
			}
			else {
				dprintf(D_FULLDEBUG, "mk_cache_links.cpp: Unable to access file "
					"%s. Falling back to regular file transfer\n", fullPath.c_str());
				free( initialWorkingDir );
				return;
			}

			string hashName = MakeHashName( fullPath.c_str(), fileModifiedTime );
			if (MakeLink(fullPath.c_str(), hashName)) {
				InputFiles->remove(path); // Remove plain file name from InputFiles
				remap += hashName;
				remap += "=";
				remap += basename(path);
				remap += ";";
				hashName = url + hashName;
				const char *const namePtr = hashName.c_str();
				if ( !InputFiles->contains(namePtr) ) {
					InputFiles->append(namePtr);
					dprintf(D_FULLDEBUG, "mk_cache_links.cpp: Adding url to "
												"InputFiles: %s\n", namePtr);
				}
				else dprintf(D_FULLDEBUG, "mk_cache_links.cpp: url already "
											"in InputFiles: %s\n", namePtr);
			}
			else {
				dprintf(D_FULLDEBUG, "mk_cache_links.cpp: Failed to generate "
									 "hash link for %s\n", fullPath.c_str());
			}
		}
		free( initialWorkingDir );
		if ( remap.Length() > 0 ) {
			MyString remapnew;
			char *buf = NULL;
			if (Ad->LookupString(ATTR_TRANSFER_INPUT_REMAPS, &buf) == 1) {
				remapnew = buf;
				free(buf);
				buf = NULL;
				remapnew += ";";
			}
			remapnew += remap;
			if (Ad->Assign(ATTR_TRANSFER_INPUT_REMAPS, remap.Value()) == false) {
				dprintf(D_ALWAYS, "mk_cache_links.cpp: Could not add to jobAd: "
													"%s\n", remap.c_str());
			}
		}
	}
	else
		dprintf(D_FULLDEBUG, "mk_cache_links.cpp: No public input files.\n");
}

#endif

<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * 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.                  *
 **************************************************************************/

/* $Id$ */

//---
//  Produces the data needed to calculate the quality assurance.
//  All data must be mergeable objects.
//  A. Mastroserio
//---

// --- ROOT system ---
#include <TClonesArray.h>
#include <TFile.h>
#include <TH1F.h>
#include <TH2F.h>
#include <TH1I.h>
#include <TDirectory.h>
#include <Riostream.h>
// --- Standard library ---

// --- AliRoot header files ---
#include "AliESDCaloCluster.h"
#include "AliESDEvent.h"
#include "AliLog.h"
#include "AliHMPIDDigit.h"
#include "AliHMPIDHit.h"
#include "AliHMPIDCluster.h"
#include "AliHMPIDQualAssDataMaker.h"

ClassImp(AliHMPIDQualAssDataMaker)

//____________________________________________________________________________
  AliHMPIDQualAssDataMaker::AliHMPIDQualAssDataMaker() :
  AliQualAssDataMaker(AliQualAss::GetDetName(AliQualAss::kHMPID), "HMPID Quality Assurance Data Maker"),
  fhHitQdc(0x0),
  fhSDigits(0x0),
  fhDigPcEvt(0x0),
  fhDigChEvt(0x0),
  fhDigQ(0x0),
  fhCluEvt(0x0),
  fhCluChi2(0x0),
  fhCluQ(0x0),
  fhCluFlg(0x0),
  fhCluSize(0x0),
  fhMipCluSize(0x0),
  fhCkovP(0x0),
  fhSigP(0x0),
  fhMipXY(0x0),
  fhDifXY(0x0)
{
  // ctor
  for(Int_t i=0; i<7; i++) fhHitMap[i]=0x0;
  for(Int_t j=0; j<5; j++) fhPid[j]=0x0;
  fDetectorDir = fOutput->GetDirectory(GetName()) ;
  if (!fDetectorDir)
    fDetectorDir = fOutput->mkdir(GetName()) ;
}

//____________________________________________________________________________
AliHMPIDQualAssDataMaker::AliHMPIDQualAssDataMaker(const AliHMPIDQualAssDataMaker& qadm) :
  AliQualAssDataMaker(),
  fhHitQdc(qadm.fhHitQdc),
  fhSDigits(qadm.fhSDigits),
  fhDigPcEvt(qadm.fhDigPcEvt),
  fhDigChEvt(qadm.fhDigChEvt),
  fhDigQ(qadm.fhDigQ),
  fhCluEvt(qadm.fhCluEvt),
  fhCluChi2(qadm.fhCluChi2),
  fhCluQ(qadm.fhCluQ),
  fhCluFlg(qadm.fhCluFlg),
  fhCluSize(qadm.fhCluSize),
  fhMipCluSize(qadm.fhMipCluSize),
  fhCkovP(qadm.fhCkovP),
  fhSigP(qadm.fhSigP),
  fhMipXY(qadm.fhMipXY),
  fhDifXY(qadm.fhDifXY)
{
  //copy ctor
  for(Int_t i=0; i<7; i++) fhHitMap[i]=qadm.fhHitMap[i];
  for(Int_t j=0; j<5; j++) fhPid[j]=qadm.fhPid[j];

  SetName((const char*)qadm.GetName()) ;
  SetTitle((const char*)qadm.GetTitle());
}

//__________________________________________________________________
AliHMPIDQualAssDataMaker& AliHMPIDQualAssDataMaker::operator = (const AliHMPIDQualAssDataMaker& qadm )
{
  // Equal operator.
  this->~AliHMPIDQualAssDataMaker();
  new(this) AliHMPIDQualAssDataMaker(qadm);
  return *this;
}

//____________________________________________________________________________
void AliHMPIDQualAssDataMaker::InitHits()
{
  // create Hits histograms in Hits subdir
     fhHitQdc=new TH1F("HitQdc","HMPID Hit Qdc all chamber;QDC",500,0,4000);
     for(Int_t iCh=0;iCh<7;iCh++) fhHitMap[iCh]=new TH2F(Form("HMPID HitMap%i",iCh),Form("Ch%i;x_{Hit};y_{Hit}",iCh),162,-1,161,146,-1,145);
}

//____________________________________________________________________________
void AliHMPIDQualAssDataMaker::InitDigits()
{
  // create Digits histograms in Digits subdir
      fhDigPcEvt=new TH1F("hDigPcEvt","PC occupancy",156,-1,77);
      fhDigChEvt=new TH1F("hDigChEvt","Chamber occupancy",32,-1,7);
      fhDigQ  =new TH1F("Q        "," digit charge               ",3000,0,3000);
}

//____________________________________________________________________________
void AliHMPIDQualAssDataMaker::InitSDigits()
{
  // create SDigits histograms in SDigits subdir
      fhSDigits     = new TH1F("hHmpidSDigits",    "SDigits Q  distribution in HMPID",  500, 0., 5000.) ;
}

//____________________________________________________________________________

void AliHMPIDQualAssDataMaker::InitRecPoints()
{
  // create cluster histograms in RecPoint subdir
      fhCluEvt=new TH1F("CluPerEvt","# clusters per chamber",16,-1,7);
      fhCluChi2  =new TH1F("CluChi2"  ,"Chi2 "               ,1000,0,100);
      fhCluQ   =new TH1F("CluQ"   ,"Cluster charge"        ,3000,0,3000);
      fhCluFlg   =new TH1F("CluFlg"   ,"Cluster flag"        ,14,-1.5,12.5);
      fhCluSize  =new TH1F("CluSize"  ,"Raw cluster size    ",100,0,100);
      fhMipCluSize =new TH1F("MipCluSize"  ,"Mip cluster size    ",100,0,100);
}
//____________________________________________________________________________
void AliHMPIDQualAssDataMaker::InitESDs()
{
  //create ESDs histograms in ESDs subdir
     fhCkovP  = new TH2F("CkovP" , "#theta_{c}, [rad];P, [GeV]"   , 150,   0,  7  ,100, 0, 1)   ;
     fhSigP   = new TH2F("SigP"  ,"#sigma_{#theta_c} [mrad];[GeV]", 150,   0,  7  ,100, 0, 1)   ;
     fhMipXY  = new TH2F("MipXY" ,"mip position"                  , 260,   0,130  ,252, 0,126)  ;
     fhDifXY  = new TH2F("DifXY" ,"diff"                          , 200, -10, 10  ,200,-10,10)  ;
     fhPid[0] = new TH1F("PidE" ,"PID: e yellow #mu magenta"  ,100,0,1)                         ;
     fhPid[1] = new TH1F("PidMu","pid of #mu"                 ,100,0,1)                         ;
     fhPid[2] = new TH1F("PidPi","PID: #pi red K green p blue",100,0,1)                         ;
     fhPid[3] = new TH1F("PidK" ,"pid of K"                   ,100,0,1)                         ;
     fhPid[4] = new TH1F("PidP" ,"pid of p"                   ,100,0,1)                         ;
}

//____________________________________________________________________________
void AliHMPIDQualAssDataMaker::MakeHits(TObject * data)
{
  //fills QA histos for Hits
  TClonesArray * hits = dynamic_cast<TClonesArray *>(data) ;
  if (!hits){
    AliError("Wrong type of hits container") ;
  } else {
    TIter next(hits);
    AliHMPIDHit * hit ;
    while ( (hit = dynamic_cast<AliHMPIDHit *>(next())) ) {
      if(hit->Pid()<500000) fhHitQdc->Fill(hit->Q()) ;
      if(hit->Pid()<500000) fhHitMap[hit->Ch()]->Fill(hit->LorsX(),hit->LorsY());
    }
  }
}

//____________________________________________________________________________
void AliHMPIDQualAssDataMaker::MakeDigits( TObject * data)
{
  //fills QA histos for Digits
  TObjArray *chambers = dynamic_cast<TObjArray*>(data);
  if ( !chambers) {
    AliError("Wrong type of digits container") ;
  } else {
    for(Int_t i =0; i< chambers->GetEntries(); i++)
      {
	TClonesArray * digits = dynamic_cast<TClonesArray*>(chambers->At(i));
	fhDigChEvt->Fill(i,digits->GetEntriesFast()/(48.*80.*6.));
	TIter next(digits);
	AliHMPIDDigit * digit;
	while ( (digit = dynamic_cast<AliHMPIDDigit *>(next())) ) {
	  fhDigPcEvt->Fill(10.*i+digit->Pc(),1./(48.*80.));
	  fhDigQ->Fill(digit->Q());
	}
      }
  }
}

//____________________________________________________________________________
void AliHMPIDQualAssDataMaker::MakeSDigits( TObject * data)
{
  //fills QA histos for SDigits
  TClonesArray * sdigits = dynamic_cast<TClonesArray *>(data) ;
  if (!sdigits) {
    AliError("Wrong type of sdigits container") ;
  } else {
    AliHMPIDDigit *ref = (AliHMPIDDigit *)sdigits->At(0);
    Float_t zero = ref->GetTrack(0);
    TIter next(sdigits) ;
    AliHMPIDDigit * sdigit ;
    while ( (sdigit = dynamic_cast<AliHMPIDDigit *>(next())) ) {
      fhSDigits->Fill(sdigit->Q()) ;
      if(zero == sdigit->GetTrack(0)) continue;
      else zero = sdigit->GetTrack(0);
    }
  }
}

//____________________________________________________________________________
void AliHMPIDQualAssDataMaker::MakeRecPoints(TTree * clustersTree)
{
  //fills QA histos for clusters

  TClonesArray *clusters = new TClonesArray("AliHMPIDCluster");
  for(int i=AliHMPIDParam::kMinCh;i<=AliHMPIDParam::kMaxCh;i++){
    TBranch *branch = clustersTree->GetBranch(Form("HMPID%d",i));
    branch->SetAddress(&clusters);
    branch->GetEntry(0);

    fhCluEvt->Fill(i,clusters->GetEntries());
    TIter next(clusters);
    AliHMPIDCluster *clu;
    while ( (clu = dynamic_cast<AliHMPIDCluster *>(next())) ) {;
      fhCluFlg->Fill(clu->Status());  fhCluChi2->Fill(clu->Chi2());  fhCluSize->Fill(clu->Size());
      fhCluQ->Fill(clu->Q());
      Int_t qCut=100;
      if(clu->Q()>qCut) {
	fhMipCluSize->SetTitle(Form("Mip cluster size at a Qcut = %i ADC",qCut));
	fhMipCluSize->Fill(clu->Size());
      }
    }
  }

  clusters->Delete();
  delete clusters;
}

//____________________________________________________________________________
void AliHMPIDQualAssDataMaker::MakeESDs(AliESDEvent * esd)
{
  //fills QA histos for ESD
  for(Int_t iTrk = 0 ; iTrk < esd->GetNumberOfTracks() ; iTrk++){
    AliESDtrack *pTrk = esd->GetTrack(iTrk) ;
    fhCkovP->Fill(pTrk->GetP(),pTrk->GetHMPIDsignal());
    fhSigP->Fill( pTrk->GetP(),TMath::Sqrt(pTrk->GetHMPIDchi2()));
    Float_t xm,ym; Int_t q,np;
    pTrk->GetHMPIDmip(xm,ym,q,np);                       //mip info
    fhMipXY->Fill(xm,ym);
    Float_t xRad,yRad,th,ph;
    pTrk->GetHMPIDtrk(xRad,yRad,th,ph);              //track info at the middle of the radiator
    Float_t xPc = xRad+9.25*TMath::Tan(th)*TMath::Cos(ph); // temporar: linear extrapol (B=0!)
    Float_t yPc = yRad+9.25*TMath::Tan(th)*TMath::Sin(ph); // temporar:          "
    fhDifXY->Fill(xm-xPc,ym-yPc); //track info
    Double_t pid[5] ;      pTrk->GetHMPIDpid(pid) ;
    for(Int_t i = 0 ; i < 5 ; i++) fhPid[i]->Fill(pid[i]) ;
  }
}

<commit_msg>Commenting out some obsolete code. The code will revised after the Yves' presentation at the offline week<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * 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.                  *
 **************************************************************************/

/* $Id$ */

//---
//  Produces the data needed to calculate the quality assurance.
//  All data must be mergeable objects.
//  A. Mastroserio
//---

// --- ROOT system ---
#include <TClonesArray.h>
#include <TFile.h>
#include <TH1F.h>
#include <TH2F.h>
#include <TH1I.h>
#include <TDirectory.h>
#include <Riostream.h>
// --- Standard library ---

// --- AliRoot header files ---
#include "AliESDCaloCluster.h"
#include "AliESDEvent.h"
#include "AliLog.h"
#include "AliHMPIDDigit.h"
#include "AliHMPIDHit.h"
#include "AliHMPIDCluster.h"
#include "AliHMPIDQualAssDataMaker.h"

ClassImp(AliHMPIDQualAssDataMaker)

//____________________________________________________________________________
  AliHMPIDQualAssDataMaker::AliHMPIDQualAssDataMaker() :
  AliQualAssDataMaker(AliQualAss::GetDetName(AliQualAss::kHMPID), "HMPID Quality Assurance Data Maker"),
  fhHitQdc(0x0),
  fhSDigits(0x0),
  fhDigPcEvt(0x0),
  fhDigChEvt(0x0),
  fhDigQ(0x0),
  fhCluEvt(0x0),
  fhCluChi2(0x0),
  fhCluQ(0x0),
  fhCluFlg(0x0),
  fhCluSize(0x0),
  fhMipCluSize(0x0),
  fhCkovP(0x0),
  fhSigP(0x0),
  fhMipXY(0x0),
  fhDifXY(0x0)
{
  // ctor
  for(Int_t i=0; i<7; i++) fhHitMap[i]=0x0;
  for(Int_t j=0; j<5; j++) fhPid[j]=0x0;
//   fDetectorDir = fOutput->GetDirectory(GetName()) ;
//   if (!fDetectorDir)
//     fDetectorDir = fOutput->mkdir(GetName()) ;
}

//____________________________________________________________________________
AliHMPIDQualAssDataMaker::AliHMPIDQualAssDataMaker(const AliHMPIDQualAssDataMaker& qadm) :
  AliQualAssDataMaker(),
  fhHitQdc(qadm.fhHitQdc),
  fhSDigits(qadm.fhSDigits),
  fhDigPcEvt(qadm.fhDigPcEvt),
  fhDigChEvt(qadm.fhDigChEvt),
  fhDigQ(qadm.fhDigQ),
  fhCluEvt(qadm.fhCluEvt),
  fhCluChi2(qadm.fhCluChi2),
  fhCluQ(qadm.fhCluQ),
  fhCluFlg(qadm.fhCluFlg),
  fhCluSize(qadm.fhCluSize),
  fhMipCluSize(qadm.fhMipCluSize),
  fhCkovP(qadm.fhCkovP),
  fhSigP(qadm.fhSigP),
  fhMipXY(qadm.fhMipXY),
  fhDifXY(qadm.fhDifXY)
{
  //copy ctor
  for(Int_t i=0; i<7; i++) fhHitMap[i]=qadm.fhHitMap[i];
  for(Int_t j=0; j<5; j++) fhPid[j]=qadm.fhPid[j];

  SetName((const char*)qadm.GetName()) ;
  SetTitle((const char*)qadm.GetTitle());
}

//__________________________________________________________________
AliHMPIDQualAssDataMaker& AliHMPIDQualAssDataMaker::operator = (const AliHMPIDQualAssDataMaker& qadm )
{
  // Equal operator.
  this->~AliHMPIDQualAssDataMaker();
  new(this) AliHMPIDQualAssDataMaker(qadm);
  return *this;
}

//____________________________________________________________________________
void AliHMPIDQualAssDataMaker::InitHits()
{
  // create Hits histograms in Hits subdir
     fhHitQdc=new TH1F("HitQdc","HMPID Hit Qdc all chamber;QDC",500,0,4000);
     for(Int_t iCh=0;iCh<7;iCh++) fhHitMap[iCh]=new TH2F(Form("HMPID HitMap%i",iCh),Form("Ch%i;x_{Hit};y_{Hit}",iCh),162,-1,161,146,-1,145);
}

//____________________________________________________________________________
void AliHMPIDQualAssDataMaker::InitDigits()
{
  // create Digits histograms in Digits subdir
      fhDigPcEvt=new TH1F("hDigPcEvt","PC occupancy",156,-1,77);
      fhDigChEvt=new TH1F("hDigChEvt","Chamber occupancy",32,-1,7);
      fhDigQ  =new TH1F("Q        "," digit charge               ",3000,0,3000);
}

//____________________________________________________________________________
void AliHMPIDQualAssDataMaker::InitSDigits()
{
  // create SDigits histograms in SDigits subdir
      fhSDigits     = new TH1F("hHmpidSDigits",    "SDigits Q  distribution in HMPID",  500, 0., 5000.) ;
}

//____________________________________________________________________________

void AliHMPIDQualAssDataMaker::InitRecPoints()
{
  // create cluster histograms in RecPoint subdir
      fhCluEvt=new TH1F("CluPerEvt","# clusters per chamber",16,-1,7);
      fhCluChi2  =new TH1F("CluChi2"  ,"Chi2 "               ,1000,0,100);
      fhCluQ   =new TH1F("CluQ"   ,"Cluster charge"        ,3000,0,3000);
      fhCluFlg   =new TH1F("CluFlg"   ,"Cluster flag"        ,14,-1.5,12.5);
      fhCluSize  =new TH1F("CluSize"  ,"Raw cluster size    ",100,0,100);
      fhMipCluSize =new TH1F("MipCluSize"  ,"Mip cluster size    ",100,0,100);
}
//____________________________________________________________________________
void AliHMPIDQualAssDataMaker::InitESDs()
{
  //create ESDs histograms in ESDs subdir
     fhCkovP  = new TH2F("CkovP" , "#theta_{c}, [rad];P, [GeV]"   , 150,   0,  7  ,100, 0, 1)   ;
     fhSigP   = new TH2F("SigP"  ,"#sigma_{#theta_c} [mrad];[GeV]", 150,   0,  7  ,100, 0, 1)   ;
     fhMipXY  = new TH2F("MipXY" ,"mip position"                  , 260,   0,130  ,252, 0,126)  ;
     fhDifXY  = new TH2F("DifXY" ,"diff"                          , 200, -10, 10  ,200,-10,10)  ;
     fhPid[0] = new TH1F("PidE" ,"PID: e yellow #mu magenta"  ,100,0,1)                         ;
     fhPid[1] = new TH1F("PidMu","pid of #mu"                 ,100,0,1)                         ;
     fhPid[2] = new TH1F("PidPi","PID: #pi red K green p blue",100,0,1)                         ;
     fhPid[3] = new TH1F("PidK" ,"pid of K"                   ,100,0,1)                         ;
     fhPid[4] = new TH1F("PidP" ,"pid of p"                   ,100,0,1)                         ;
}

//____________________________________________________________________________
void AliHMPIDQualAssDataMaker::MakeHits(TObject * data)
{
  //fills QA histos for Hits
  TClonesArray * hits = dynamic_cast<TClonesArray *>(data) ;
  if (!hits){
    AliError("Wrong type of hits container") ;
  } else {
    TIter next(hits);
    AliHMPIDHit * hit ;
    while ( (hit = dynamic_cast<AliHMPIDHit *>(next())) ) {
      if(hit->Pid()<500000) fhHitQdc->Fill(hit->Q()) ;
      if(hit->Pid()<500000) fhHitMap[hit->Ch()]->Fill(hit->LorsX(),hit->LorsY());
    }
  }
}

//____________________________________________________________________________
void AliHMPIDQualAssDataMaker::MakeDigits( TObject * data)
{
  //fills QA histos for Digits
  TObjArray *chambers = dynamic_cast<TObjArray*>(data);
  if ( !chambers) {
    AliError("Wrong type of digits container") ;
  } else {
    for(Int_t i =0; i< chambers->GetEntries(); i++)
      {
	TClonesArray * digits = dynamic_cast<TClonesArray*>(chambers->At(i));
	fhDigChEvt->Fill(i,digits->GetEntriesFast()/(48.*80.*6.));
	TIter next(digits);
	AliHMPIDDigit * digit;
	while ( (digit = dynamic_cast<AliHMPIDDigit *>(next())) ) {
	  fhDigPcEvt->Fill(10.*i+digit->Pc(),1./(48.*80.));
	  fhDigQ->Fill(digit->Q());
	}
      }
  }
}

//____________________________________________________________________________
void AliHMPIDQualAssDataMaker::MakeSDigits( TObject * data)
{
  //fills QA histos for SDigits
  TClonesArray * sdigits = dynamic_cast<TClonesArray *>(data) ;
  if (!sdigits) {
    AliError("Wrong type of sdigits container") ;
  } else {
    AliHMPIDDigit *ref = (AliHMPIDDigit *)sdigits->At(0);
    Float_t zero = ref->GetTrack(0);
    TIter next(sdigits) ;
    AliHMPIDDigit * sdigit ;
    while ( (sdigit = dynamic_cast<AliHMPIDDigit *>(next())) ) {
      fhSDigits->Fill(sdigit->Q()) ;
      if(zero == sdigit->GetTrack(0)) continue;
      else zero = sdigit->GetTrack(0);
    }
  }
}

//____________________________________________________________________________
void AliHMPIDQualAssDataMaker::MakeRecPoints(TTree * clustersTree)
{
  //fills QA histos for clusters

  TClonesArray *clusters = new TClonesArray("AliHMPIDCluster");
  for(int i=AliHMPIDParam::kMinCh;i<=AliHMPIDParam::kMaxCh;i++){
    TBranch *branch = clustersTree->GetBranch(Form("HMPID%d",i));
    branch->SetAddress(&clusters);
    branch->GetEntry(0);

    fhCluEvt->Fill(i,clusters->GetEntries());
    TIter next(clusters);
    AliHMPIDCluster *clu;
    while ( (clu = dynamic_cast<AliHMPIDCluster *>(next())) ) {;
      fhCluFlg->Fill(clu->Status());  fhCluChi2->Fill(clu->Chi2());  fhCluSize->Fill(clu->Size());
      fhCluQ->Fill(clu->Q());
      Int_t qCut=100;
      if(clu->Q()>qCut) {
	fhMipCluSize->SetTitle(Form("Mip cluster size at a Qcut = %i ADC",qCut));
	fhMipCluSize->Fill(clu->Size());
      }
    }
  }

  clusters->Delete();
  delete clusters;
}

//____________________________________________________________________________
void AliHMPIDQualAssDataMaker::MakeESDs(AliESDEvent * esd)
{
  //fills QA histos for ESD
  for(Int_t iTrk = 0 ; iTrk < esd->GetNumberOfTracks() ; iTrk++){
    AliESDtrack *pTrk = esd->GetTrack(iTrk) ;
    fhCkovP->Fill(pTrk->GetP(),pTrk->GetHMPIDsignal());
    fhSigP->Fill( pTrk->GetP(),TMath::Sqrt(pTrk->GetHMPIDchi2()));
    Float_t xm,ym; Int_t q,np;
    pTrk->GetHMPIDmip(xm,ym,q,np);                       //mip info
    fhMipXY->Fill(xm,ym);
    Float_t xRad,yRad,th,ph;
    pTrk->GetHMPIDtrk(xRad,yRad,th,ph);              //track info at the middle of the radiator
    Float_t xPc = xRad+9.25*TMath::Tan(th)*TMath::Cos(ph); // temporar: linear extrapol (B=0!)
    Float_t yPc = yRad+9.25*TMath::Tan(th)*TMath::Sin(ph); // temporar:          "
    fhDifXY->Fill(xm-xPc,ym-yPc); //track info
    Double_t pid[5] ;      pTrk->GetHMPIDpid(pid) ;
    for(Int_t i = 0 ; i < 5 ; i++) fhPid[i]->Fill(pid[i]) ;
  }
}

<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include "tp_PointGeometry.hxx"
#include "TabPages.hrc"
#include "res_BarGeometry.hxx"
#include "ResId.hxx"

#include "chartview/ChartSfxItemIds.hxx"

#include <svl/intitem.hxx>
#include <svx/svx3ditems.hxx>

namespace chart
{

SchLayoutTabPage::SchLayoutTabPage(Window* pWindow,const SfxItemSet& rInAttrs)
                 : SfxTabPage(pWindow, "tp_ChartType", "modules/schart/ui/tp_ChartType.ui", rInAttrs)
                 , m_pGeometryResources(0)
{
    m_pGeometryResources = new BarGeometryResources( this );
}

SchLayoutTabPage::~SchLayoutTabPage()
{
    delete m_pGeometryResources;
}

SfxTabPage* SchLayoutTabPage::Create(Window* pWindow,
                                        const SfxItemSet* rOutAttrs)
{
    return new SchLayoutTabPage(pWindow, *rOutAttrs);
}

bool SchLayoutTabPage::FillItemSet(SfxItemSet* rOutAttrs)
{

    if(m_pGeometryResources && m_pGeometryResources->GetSelectEntryCount())
    {
        long nSegs=32;

        long nShape = m_pGeometryResources->GetSelectEntryPos();
        if(nShape==CHART_SHAPE3D_PYRAMID)
            nSegs=4;

        rOutAttrs->Put(SfxInt32Item(SCHATTR_STYLE_SHAPE,nShape));
        rOutAttrs->Put(Svx3DHorizontalSegmentsItem(nSegs));
    }
    return true;
}

void SchLayoutTabPage::Reset(const SfxItemSet* rInAttrs)
{
    const SfxPoolItem *pPoolItem = NULL;

    if (rInAttrs->GetItemState(SCHATTR_STYLE_SHAPE,true, &pPoolItem) == SFX_ITEM_SET)
    {
        long nVal=((const SfxInt32Item*)pPoolItem)->GetValue();
        if(m_pGeometryResources)
        {
            m_pGeometryResources->SelectEntryPos(static_cast<sal_uInt16>(nVal));
            m_pGeometryResources->Show( true );
        }
    }
}

} //namespace chart

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>SchLayoutTabPage: that ctor wants a pointer<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include "tp_PointGeometry.hxx"
#include "TabPages.hrc"
#include "res_BarGeometry.hxx"
#include "ResId.hxx"

#include "chartview/ChartSfxItemIds.hxx"

#include <svl/intitem.hxx>
#include <svx/svx3ditems.hxx>

namespace chart
{

SchLayoutTabPage::SchLayoutTabPage(Window* pWindow,const SfxItemSet& rInAttrs)
     : SfxTabPage(pWindow, "tp_ChartType", "modules/schart/ui/tp_ChartType.ui", &rInAttrs)
     , m_pGeometryResources(0)
{
    m_pGeometryResources = new BarGeometryResources( this );
}

SchLayoutTabPage::~SchLayoutTabPage()
{
    delete m_pGeometryResources;
}

SfxTabPage* SchLayoutTabPage::Create(Window* pWindow,
                                        const SfxItemSet* rOutAttrs)
{
    return new SchLayoutTabPage(pWindow, *rOutAttrs);
}

bool SchLayoutTabPage::FillItemSet(SfxItemSet* rOutAttrs)
{

    if(m_pGeometryResources && m_pGeometryResources->GetSelectEntryCount())
    {
        long nSegs=32;

        long nShape = m_pGeometryResources->GetSelectEntryPos();
        if(nShape==CHART_SHAPE3D_PYRAMID)
            nSegs=4;

        rOutAttrs->Put(SfxInt32Item(SCHATTR_STYLE_SHAPE,nShape));
        rOutAttrs->Put(Svx3DHorizontalSegmentsItem(nSegs));
    }
    return true;
}

void SchLayoutTabPage::Reset(const SfxItemSet* rInAttrs)
{
    const SfxPoolItem *pPoolItem = NULL;

    if (rInAttrs->GetItemState(SCHATTR_STYLE_SHAPE,true, &pPoolItem) == SFX_ITEM_SET)
    {
        long nVal=((const SfxInt32Item*)pPoolItem)->GetValue();
        if(m_pGeometryResources)
        {
            m_pGeometryResources->SelectEntryPos(static_cast<sal_uInt16>(nVal));
            m_pGeometryResources->Show( true );
        }
    }
}

} //namespace chart

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>#include <sstream>
#include <iomanip>

#include "Bar.h"
#include "ChartUtil.h"

namespace CppChart
{
	BarChart::BarChart(const std::vector<DataElement>& d, bool al, bool dv) :
		m_gap(10), m_guides(true), m_displayGuides(false), m_displayValues(dv),
		m_data(d), m_width(0), m_vSize(0.0f)
	{
		LogFnStart();

		m_max = (*max_element(m_data.begin(), m_data.end())).value;
		m_legend.m_exists = al;

		if (m_legend.m_exists)
		{
			std::vector<DataFormat> temp;
			for (auto& element : d)
			{
				temp.push_back({ element.name, element.color });
			}
			m_legend.AddData(temp);
		}

		LogFnEnd();
	}

	void BarChart::Render()
	{
		LogFnStart();

		float x = m_chartOffsets.x / 2.0f + m_gap, y = m_chartOffsets.y / 2.0f;
		float ratio = (m_chartHeight - 2.0f * m_chartOffsets.y - m_vSize) / m_max;
		float item;

		sf::Text text, values;
		sf::RectangleShape guideLines;

		m_width = (m_chartWidth - 2.0f * m_chartOffsets.x - m_gap * static_cast<float>(m_data.size())) / static_cast<float>(m_data.size());
		m_vSize = m_width / static_cast<float>(CountDigit(m_max) + 3u);

		if (!m_legend.m_exists)
		{
			text.setFont(m_axes.labels.font);
			text.setColor(m_axes.labels.fontColor);
			text.setCharacterSize(m_axes.labels.fontSize);
		}

		if (m_displayValues)
		{
			values.setFont(m_axes.labels.font);
			values.setCharacterSize(m_vSize);
		}

		if (m_guides)
		{
			// TODO: Fix code
		}

		for (auto& d : m_data)
		{
			item = d.value;
			item *= ratio;

			m_bar.setPosition(x, m_chartHeight - y - item + m_vSize);
			m_bar.setSize(sf::Vector2f(m_width, item - m_axes.labels.fontSize - m_vSize));
			m_bar.setFillColor(d.color);

			m_chartTexture.draw(m_bar);

			if (!m_legend.m_exists)
			{
				text.setString(d.name);
				SetTextAtCenter(text, x, m_chartHeight - y - 1.2f * m_axes.labels.fontSize, m_width + m_gap, m_axes.labels.fontSize);
				text.move(sf::Vector2f(-m_gap / 2.0f, 0.0f));
				m_chartTexture.draw(text);
			}

			if (m_displayValues)
			{
				values.setColor(d.color);
				values.setString([&]()
				{
					std::ostringstream oss;
					oss << std::setprecision(2) << d.value;
					return oss.str();
				}());
				SetTextAtCenter(values, x, m_chartHeight - y - item - m_vSize / 2.0f, m_width + m_gap, m_vSize);
				values.move(sf::Vector2f(-m_gap / 2.0f, 0.0f));
				m_chartTexture.draw(values);
			}

			x += m_width + m_gap;
		}

		DrawAxes();

		LogFnEnd();
	}
}
<commit_msg>Implement MultiBarChart's constructor<commit_after>#include <sstream>
#include <iomanip>

#include "Bar.h"
#include "ChartUtil.h"
#include <cassert>

namespace CppChart
{
	BarChart::BarChart(const std::vector<DataElement>& d, bool al, bool dv) :
		m_gap(10), m_guides(true), m_displayGuides(false), m_displayValues(dv),
		m_data(d), m_width(0), m_vSize(0.0f)
	{
		LogFnStart();

		m_max = (*max_element(m_data.begin(), m_data.end())).value;
		m_legend.m_exists = al;

		if (m_legend.m_exists)
		{
			std::vector<DataFormat> temp;
			for (auto& element : d)
			{
				temp.push_back({ element.name, element.color });
			}
			m_legend.AddData(temp);
		}

		LogFnEnd();
	}

	void BarChart::Render()
	{
		LogFnStart();

		float x = m_chartOffsets.x / 2.0f + m_gap, y = m_chartOffsets.y / 2.0f;
		float ratio = (m_chartHeight - 2.0f * m_chartOffsets.y - m_vSize) / m_max;
		float item;

		sf::Text text, values;
		sf::RectangleShape guideLines;

		m_width = (m_chartWidth - 2.0f * m_chartOffsets.x - m_gap * static_cast<float>(m_data.size())) / static_cast<float>(m_data.size());
		m_vSize = m_width / static_cast<float>(CountDigit(m_max) + 3u);

		if (!m_legend.m_exists)
		{
			text.setFont(m_axes.labels.font);
			text.setColor(m_axes.labels.fontColor);
			text.setCharacterSize(m_axes.labels.fontSize);
		}

		if (m_displayValues)
		{
			values.setFont(m_axes.labels.font);
			values.setCharacterSize(m_vSize);
		}

		if (m_guides)
		{
			// TODO: Fix code
		}

		for (auto& d : m_data)
		{
			item = d.value;
			item *= ratio;

			m_bar.setPosition(x, m_chartHeight - y - item + m_vSize);
			m_bar.setSize(sf::Vector2f(m_width, item - m_axes.labels.fontSize - m_vSize));
			m_bar.setFillColor(d.color);

			m_chartTexture.draw(m_bar);

			if (!m_legend.m_exists)
			{
				text.setString(d.name);
				SetTextAtCenter(text, x, m_chartHeight - y - 1.2f * m_axes.labels.fontSize, m_width + m_gap, m_axes.labels.fontSize);
				text.move(sf::Vector2f(-m_gap / 2.0f, 0.0f));
				m_chartTexture.draw(text);
			}

			if (m_displayValues)
			{
				values.setColor(d.color);
				values.setString([&]()
				{
					std::ostringstream oss;
					oss << std::setprecision(2) << d.value;
					return oss.str();
				}());
				SetTextAtCenter(values, x, m_chartHeight - y - item - m_vSize / 2.0f, m_width + m_gap, m_vSize);
				values.move(sf::Vector2f(-m_gap / 2.0f, 0.0f));
				m_chartTexture.draw(values);
			}

			x += m_width + m_gap;
		}

		DrawAxes();

		LogFnEnd();
	}

	MultiBarChart::MultiBarChart(const std::vector<std::vector<float>>& md, const std::vector<std::string>& al, const std::vector<sf::Color>& bc)
		: m_gap(0.0f), m_guides(0), m_displayGuides(false), m_displayValues(true), m_multiData(md), m_axesLabels(al), m_barColors(bc), m_width(0.0f), m_vSize(0.0f)
	{
		LogFnStart();

		assert(md.size() == al.size());
		assert(md[0].size() == bc.size());

		float temp = 0.0f;
		m_max = *(max_element(md[0].begin(), md[0].end()));

		for (int i = 1; i < al.size(); ++i)
		{
			if (temp > m_max)
			{
				m_max = temp;
			}
		}

		LogFnEnd();
	}
}
<|endoftext|>


<commit_before><commit_msg>Use bool<commit_after><|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2009, Willow Garage, Inc.
 *  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 Willow Garage, Inc. 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.
 *
 * $Id$
 *
 */

#include "pcl/point_types.h"
#include "pcl/impl/instantiate.hpp"
#include "pcl/features/pfh.h"
#include "pcl/features/impl/pfh.hpp"

//////////////////////////////////////////////////////////////////////////////////////////////
bool
pcl::computePairFeatures (const Eigen::Vector4f &p1, const Eigen::Vector4f &n1,
                          const Eigen::Vector4f &p2, const Eigen::Vector4f &n2,
                          float &f1, float &f2, float &f3, float &f4)
{
  Eigen::Vector4f dp2p1 = p2 - p1;
  dp2p1[3] = 0.0f;
  f4 = dp2p1.norm ();

  if (f4 == 0)
  {
    PCL_ERROR ("Euclidean distance between points is 0!\n");
    f1 = f2 = f3 = f4 = 0;
    return (false);
  }

  Eigen::Vector4f n1_copy = n1,
      n2_copy = n2;
  n1_copy[3] = n2_copy[3] = 0.0f;
  float angle1 = n1_copy.dot (dp2p1) / f4,
      angle2 = -n2_copy.dot (dp2p1) / f4;

/* commented this to pass the unit tests
 * if (acos (angle1) > acos(angle2))
  {
    // switch p1 and p2
    n1_copy = n2;
    n2_copy = n1;
    n1_copy[3] = n2_copy[3] = 0.0f;
    dp2p1 *= (-1);
    f3 = angle2;
  }
  else*/
  f3 = angle1;

  // Create a Darboux frame coordinate system u-v-w
  // u = n1; v = (p_idx - q_idx) x u / || (p_idx - q_idx) x u ||; w = u x v
  Eigen::Vector4f v = dp2p1.cross3 (n1_copy);
  v[3] = 0.0f;
  float v_norm = v.norm ();
  if (v_norm == 0)
  {
    PCL_ERROR ("Norm of Delta x U is 0!\n");
    f1 = f2 = f3 = f4 = 0;
    return (false);
  }
  // Normalize v
  v /= v_norm;

  Eigen::Vector4f w = n1_copy.cross3 (v);
  // Do not have to normalize w - it is a unit vector by construction

  v[3] = 0.0f;
  f2 = v.dot (n2_copy);
  w[3] = 0.0f;
  // Compute f1 = arctan (w * n2, u * n2) i.e. angle of n2 in the x=u, y=w coordinate system
  f1 = atan2f (w.dot (n2_copy), u.dot (n2_copy)); // @todo optimize this

  return (true);
}

// Instantiations of specific point types
PCL_INSTANTIATE_PRODUCT(PFHEstimation, (PCL_XYZ_POINT_TYPES)(PCL_NORMAL_POINT_TYPES)((pcl::PFHSignature125)));

<commit_msg>too many undos in the editor - build now works :-)<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2009, Willow Garage, Inc.
 *  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 Willow Garage, Inc. 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.
 *
 * $Id$
 *
 */

#include "pcl/point_types.h"
#include "pcl/impl/instantiate.hpp"
#include "pcl/features/pfh.h"
#include "pcl/features/impl/pfh.hpp"

//////////////////////////////////////////////////////////////////////////////////////////////
bool
pcl::computePairFeatures (const Eigen::Vector4f &p1, const Eigen::Vector4f &n1,
                          const Eigen::Vector4f &p2, const Eigen::Vector4f &n2,
                          float &f1, float &f2, float &f3, float &f4)
{
  Eigen::Vector4f dp2p1 = p2 - p1;
  dp2p1[3] = 0.0f;
  f4 = dp2p1.norm ();

  if (f4 == 0.0f)
  {
    PCL_ERROR ("Euclidean distance between points is 0!\n");
    f1 = f2 = f3 = f4 = 0.0f;
    return (false);
  }

  Eigen::Vector4f n1_copy = n1,
      n2_copy = n2;
  n1_copy[3] = n2_copy[3] = 0.0f;
  float angle1 = n1_copy.dot (dp2p1) / f4,
      angle2 = -n2_copy.dot (dp2p1) / f4;

/* commented this to pass the unit tests
 * if (acos (angle1) > acos(angle2))
  {
    // switch p1 and p2
    n1_copy = n2;
    n2_copy = n1;
    n1_copy[3] = n2_copy[3] = 0.0f;
    dp2p1 *= (-1);
    f3 = angle2;
  }
  else*/
  f3 = angle1;

  // Create a Darboux frame coordinate system u-v-w
  // u = n1; v = (p_idx - q_idx) x u / || (p_idx - q_idx) x u ||; w = u x v
  Eigen::Vector4f v = dp2p1.cross3 (n1_copy);
  v[3] = 0.0f;
  float v_norm = v.norm ();
  if (v_norm == 0.0f)
  {
    PCL_ERROR ("Norm of Delta x U is 0!\n");
    f1 = f2 = f3 = f4 = 0.0f;
    return (false);
  }
  // Normalize v
  v /= v_norm;

  Eigen::Vector4f w = n1_copy.cross3 (v);
  // Do not have to normalize w - it is a unit vector by construction

  v[3] = 0.0f;
  f2 = v.dot (n2_copy);
  w[3] = 0.0f;
  // Compute f1 = arctan (w * n2, u * n2) i.e. angle of n2 in the x=u, y=w coordinate system
  f1 = atan2f (w.dot (n2_copy), n1_copy.dot (n2_copy)); // @todo optimize this

  return (true);
}

// Instantiations of specific point types
PCL_INSTANTIATE_PRODUCT(PFHEstimation, (PCL_XYZ_POINT_TYPES)(PCL_NORMAL_POINT_TYPES)((pcl::PFHSignature125)));

<|endoftext|>


<commit_before>
#include <list>
#include <sstream>

#include "flame/base.h"

#include "pyflame.h"

#define NO_IMPORT_ARRAY
#define PY_ARRAY_UNIQUE_SYMBOL FLAME_PyArray_API
#include <numpy/ndarrayobject.h>

/** Translate python list of tuples to Config
 *
 *  [(K,V)]   -> Config
 *    float   -> double
 *    str     -> string
 *    [[()]]    -> vector<Config>  (recurse)
 *    ndarray -> vector<double>
 *    TODO: [0.0]   -> vector<double>
 */
void List2Config(Config& ret, PyObject *list, unsigned depth)
{
    if(depth>3)
        throw std::runtime_error("too deep for Dict2Config");

    PyRef<> iter(PyObject_GetIter(list));
    while(true) {
        PyObject *item = PyIter_Next(iter.py());
        if(!item) break;
        PyRef<> itemref(item);
        const char *kname;
        PyObject *value;
        if(!PyArg_ParseTuple(item, "sO", &kname, &value))
            throw std::runtime_error("list item is not a tuple?");

        if(PyArray_Check(value)) { // array as vector<double>
            PyRef<> arr(PyArray_ContiguousFromAny(value, NPY_DOUBLE, 0, 2));
            double *buf = (double*)PyArray_DATA(arr.py());
            std::vector<double> temp(PyArray_SIZE(arr.py()));
            std::copy(buf, buf+temp.size(), temp.begin());

            ret.swap<std::vector<double> >(kname, temp);

        } else if(PyNumber_Check(value)) { // scalar as double
            PyRef<> dval(PyNumber_Float(value));
            double val = PyFloat_AsDouble(dval.py());
            ret.set<double>(kname, val);

        } else if(PyUnicode_Check(value) || (PY_MAJOR_VERSION < 3 && PyBytes_Check(value))) { // string
            PyRef<> valref(value, borrow());
            PyCString sval(valref);
            const char *val = sval.c_str();

            ret.set<std::string>(kname, val);

        } else if(PySequence_Check(value)) { // list of dict
            Py_ssize_t N = PySequence_Size(value);

            Config::vector_t output;
            output.reserve(N);

            for(Py_ssize_t i=0; i<N; i++) {
                PyRef<> elem(PySequence_GetItem(value, i));

                if(PyDict_Check(elem.py())) {
                    elem.reset(PyMapping_Items(elem.py()));
                }
                if(!PyList_Check(elem.py())) {
                    PyTypeObject *valuetype = (PyTypeObject*)PyObject_Type(elem.py());
                    throw std::invalid_argument(SB()<<"lists must contain only dict or list of tuples, not "<<valuetype->tp_name);
                }

                output.push_back(ret.new_scope());

                List2Config(output.back(), elem.py(), depth+1); // inheirt parent scope
            }

            ret.set<Config::vector_t>(kname, output);

        } else {
            PyTypeObject *valuetype = (PyTypeObject*)PyObject_Type(value);
            throw std::invalid_argument(SB()<<"Must be a dict, not "<<valuetype->tp_name);
        }
    }
}

namespace {

PyObject* pydirname(PyObject *obj)
{
    if(!obj) return NULL;

    PyRef<> ospath(PyImport_ImportModule("os.path"));
    return PyObject_CallMethod(ospath.py(), "dirname", "O", obj);
}

struct confval : public boost::static_visitor<PyRef<> >
{
    PyRef<> operator()(double v) const
    {
        return PyRef<>(PyFloat_FromDouble(v));
    }

    PyRef<> operator()(const std::string& v) const
    {
        return PyRef<>(PyString_FromString(v.c_str()));
    }

    PyRef<> operator()(const std::vector<double>& v) const
    {
        npy_intp dims[]  = {(npy_intp)v.size()};
        PyRef<> obj(PyArray_SimpleNew(1, dims, NPY_DOUBLE));
        std::copy(v.begin(), v.end(), (double*)PyArray_DATA(obj.py()));
        return obj;
    }

    PyRef<> operator()(const Config::vector_t& v) const
    {
        PyRef<> L(PyList_New(v.size()));

        for(size_t i=0, N=v.size(); i<N; i++)
        {
            PyList_SetItem(L.py(), i, conf2dict(&v[i]));
        }
        return L;
    }
};

} // namespace

PyObject* conf2dict(const Config *conf)
{
    PyRef<> list(PyList_New(0));

    for(Config::const_iterator it=conf->begin(), end=conf->end();
        it!=end; ++it)
    {
        PyRef<> val(boost::apply_visitor(confval(), it->second));
        PyRef<> tup(Py_BuildValue("sO", it->first.c_str(), val.py()));
        if(PyList_Append(list.py(), tup.py()))
            throw std::runtime_error("Failed to insert into dictionary from conf2dict");
    }

    return list.releasePy();
}

Config* list2conf(PyObject *dict)
{
    if(!PyList_Check(dict))
        throw std::invalid_argument("Not a list");
    std::auto_ptr<Config> conf(new Config);
    List2Config(*conf, dict);
    return conf.release();
}

PyObject* PyGLPSPrint(PyObject *, PyObject *args)
{
    try {
        PyObject *inp;
        if(!PyArg_ParseTuple(args, "O", &inp))
            return NULL;

        PyRef<> list;
        if(PyDict_Check(inp)) {
            list.reset(PyMapping_Items(inp));
            inp = list.py();
        }
        if(!PyList_Check(inp))
            return PyErr_Format(PyExc_ValueError, "argument must be dict or list of tuples");

        Config conf;
        List2Config(conf, inp);
        std::ostringstream strm;
        GLPSPrint(strm, conf);
        return PyString_FromString(strm.str().c_str());
    }CATCH()
}

#ifndef PY_SSIZE_T_CLEAN
#error the following assumes ssize_t is used
#endif

Config* PyGLPSParse2Config(PyObject *, PyObject *args, PyObject *kws)
{
    PyObject *conf = NULL, *extra_defs = Py_None;
    const char *path = NULL;
    const char *pnames[] = {"config", "path", "extra", NULL};
    if(!PyArg_ParseTupleAndKeywords(args, kws, "O|zO", (char**)pnames, &conf, &path, &extra_defs))
        return NULL;

    GLPSParser parser;

    if(extra_defs==Py_None) {
        // no-op
    } else if(PyDict_Check(extra_defs)) {
        PyObject *key, *value;
        Py_ssize_t pos = 0;

        while(PyDict_Next(extra_defs, &pos, &key, &value)) {
            PyRef<> keyx(key, borrow());
            PyCString keystr(keyx);

            Config::value_t curval;

            if(PyNumber_Check(value)) {
                PyRef<> pyf(PyNumber_Float(value));
                curval = PyFloat_AsDouble(pyf.py());

            } else if(PyString_Check(value)) {
                PyRef<> valuex(value, borrow());
                PyCString valstr(valuex);

                curval = valstr.c_str();

            } else {
                PyErr_SetString(PyExc_ValueError, "extra {} can contain only numbers or strings");
                return NULL;
            }

            parser.setVar(keystr.c_str(), curval);
        }
    } else {
        PyErr_SetString(PyExc_ValueError, "'extra' must be a dict");
        return NULL;
    }

    PyGetBuf buf;
    std::auto_ptr<Config> C;

    PyRef<> listref;

    if(PyObject_HasAttrString(conf, "read")) { // file-like
        PyCString pyname;

        if(!path && PyObject_HasAttrString(conf, "name")) {
            path = pyname.c_str(pydirname(PyObject_GetAttrString(conf, "name")));
        }

        PyRef<> pybytes(PyObject_CallMethod(conf, "read", ""));
        if(!buf.get(pybytes.py())) {
            PyErr_SetString(PyExc_TypeError, "read() must return a buffer");
            return NULL;
        }
        C.reset(parser.parse_byte((const char*)buf.data(), buf.size(), path));

    } else if(buf.get(conf)) {
        C.reset(parser.parse_byte((const char*)buf.data(), buf.size(), path));

#if PY_MAJOR_VERSION >= 3
    } else if(PyUnicode_Check(conf)) { // py3 str (aka unicode) doesn't implement buffer iface
        PyCString buf;
        const char *cbuf = buf.c_str(conf);

        C.reset(parser.parse_byte(cbuf, strlen(cbuf), path));
#endif

    } else {
        if(PyDict_Check(conf)) {
            listref.reset(PyMapping_Items(conf));
            conf = listref.py();
        }
        if(PyList_Check(conf)) {
            C.reset(list2conf(conf));

        } else {
            throw std::invalid_argument("'config' must be dict, list of tuples, or byte buffer");
        }
    }

    return C.release();
}

PyObject* PyGLPSParse(PyObject *unused, PyObject *args, PyObject *kws)
{
    try{
        return conf2dict(PyGLPSParse2Config(unused, args, kws));
    }CATCH()
}
<commit_msg>python: propagate errors through conf2dict()<commit_after>
#include <list>
#include <sstream>

#include "flame/base.h"

#include "pyflame.h"

#define NO_IMPORT_ARRAY
#define PY_ARRAY_UNIQUE_SYMBOL FLAME_PyArray_API
#include <numpy/ndarrayobject.h>

/** Translate python list of tuples to Config
 *
 *  [(K,V)]   -> Config
 *    float   -> double
 *    str     -> string
 *    [[()]]    -> vector<Config>  (recurse)
 *    ndarray -> vector<double>
 *    TODO: [0.0]   -> vector<double>
 */
void List2Config(Config& ret, PyObject *list, unsigned depth)
{
    if(depth>3)
        throw std::runtime_error("too deep for Dict2Config");

    PyRef<> iter(PyObject_GetIter(list));
    while(true) {
        PyObject *item = PyIter_Next(iter.py());
        if(!item) break;
        PyRef<> itemref(item);
        const char *kname;
        PyObject *value;
        if(!PyArg_ParseTuple(item, "sO", &kname, &value))
            throw std::runtime_error("list item is not a tuple?");

        if(PyArray_Check(value)) { // array as vector<double>
            PyRef<> arr(PyArray_ContiguousFromAny(value, NPY_DOUBLE, 0, 2));
            double *buf = (double*)PyArray_DATA(arr.py());
            std::vector<double> temp(PyArray_SIZE(arr.py()));
            std::copy(buf, buf+temp.size(), temp.begin());

            ret.swap<std::vector<double> >(kname, temp);

        } else if(PyNumber_Check(value)) { // scalar as double
            PyRef<> dval(PyNumber_Float(value));
            double val = PyFloat_AsDouble(dval.py());
            ret.set<double>(kname, val);

        } else if(PyUnicode_Check(value) || (PY_MAJOR_VERSION < 3 && PyBytes_Check(value))) { // string
            PyRef<> valref(value, borrow());
            PyCString sval(valref);
            const char *val = sval.c_str();

            ret.set<std::string>(kname, val);

        } else if(PySequence_Check(value)) { // list of dict
            Py_ssize_t N = PySequence_Size(value);

            Config::vector_t output;
            output.reserve(N);

            for(Py_ssize_t i=0; i<N; i++) {
                PyRef<> elem(PySequence_GetItem(value, i));

                if(PyDict_Check(elem.py())) {
                    elem.reset(PyMapping_Items(elem.py()));
                }
                if(!PyList_Check(elem.py())) {
                    PyTypeObject *valuetype = (PyTypeObject*)PyObject_Type(elem.py());
                    throw std::invalid_argument(SB()<<"lists must contain only dict or list of tuples, not "<<valuetype->tp_name);
                }

                output.push_back(ret.new_scope());

                List2Config(output.back(), elem.py(), depth+1); // inheirt parent scope
            }

            ret.set<Config::vector_t>(kname, output);

        } else {
            PyTypeObject *valuetype = (PyTypeObject*)PyObject_Type(value);
            throw std::invalid_argument(SB()<<"Must be a dict, not "<<valuetype->tp_name);
        }
    }
}

namespace {

PyObject* pydirname(PyObject *obj)
{
    if(!obj) return NULL;

    PyRef<> ospath(PyImport_ImportModule("os.path"));
    return PyObject_CallMethod(ospath.py(), "dirname", "O", obj);
}

struct confval : public boost::static_visitor<PyRef<> >
{
    PyRef<> operator()(double v) const
    {
        return PyRef<>(PyFloat_FromDouble(v));
    }

    PyRef<> operator()(const std::string& v) const
    {
        return PyRef<>(PyString_FromString(v.c_str()));
    }

    PyRef<> operator()(const std::vector<double>& v) const
    {
        npy_intp dims[]  = {(npy_intp)v.size()};
        PyRef<> obj(PyArray_SimpleNew(1, dims, NPY_DOUBLE));
        std::copy(v.begin(), v.end(), (double*)PyArray_DATA(obj.py()));
        return obj;
    }

    PyRef<> operator()(const Config::vector_t& v) const
    {
        PyRef<> L(PyList_New(v.size()));

        for(size_t i=0, N=v.size(); i<N; i++)
        {
            PyList_SetItem(L.py(), i, conf2dict(&v[i]));
        }
        return L;
    }
};

} // namespace

PyObject* conf2dict(const Config *conf)
{
    if(!conf)
        return NULL;
    PyRef<> list(PyList_New(0));

    for(Config::const_iterator it=conf->begin(), end=conf->end();
        it!=end; ++it)
    {
        PyRef<> val(boost::apply_visitor(confval(), it->second));
        PyRef<> tup(Py_BuildValue("sO", it->first.c_str(), val.py()));
        if(PyList_Append(list.py(), tup.py()))
            throw std::runtime_error("Failed to insert into dictionary from conf2dict");
    }

    return list.releasePy();
}

Config* list2conf(PyObject *dict)
{
    if(!PyList_Check(dict))
        throw std::invalid_argument("Not a list");
    std::auto_ptr<Config> conf(new Config);
    List2Config(*conf, dict);
    return conf.release();
}

PyObject* PyGLPSPrint(PyObject *, PyObject *args)
{
    try {
        PyObject *inp;
        if(!PyArg_ParseTuple(args, "O", &inp))
            return NULL;

        PyRef<> list;
        if(PyDict_Check(inp)) {
            list.reset(PyMapping_Items(inp));
            inp = list.py();
        }
        if(!PyList_Check(inp))
            return PyErr_Format(PyExc_ValueError, "argument must be dict or list of tuples");

        Config conf;
        List2Config(conf, inp);
        std::ostringstream strm;
        GLPSPrint(strm, conf);
        return PyString_FromString(strm.str().c_str());
    }CATCH()
}

#ifndef PY_SSIZE_T_CLEAN
#error the following assumes ssize_t is used
#endif

Config* PyGLPSParse2Config(PyObject *, PyObject *args, PyObject *kws)
{
    PyObject *conf = NULL, *extra_defs = Py_None;
    const char *path = NULL;
    const char *pnames[] = {"config", "path", "extra", NULL};
    if(!PyArg_ParseTupleAndKeywords(args, kws, "O|zO", (char**)pnames, &conf, &path, &extra_defs))
        return NULL;

    GLPSParser parser;

    if(extra_defs==Py_None) {
        // no-op
    } else if(PyDict_Check(extra_defs)) {
        PyObject *key, *value;
        Py_ssize_t pos = 0;

        while(PyDict_Next(extra_defs, &pos, &key, &value)) {
            PyRef<> keyx(key, borrow());
            PyCString keystr(keyx);

            Config::value_t curval;

            if(PyNumber_Check(value)) {
                PyRef<> pyf(PyNumber_Float(value));
                curval = PyFloat_AsDouble(pyf.py());

            } else if(PyString_Check(value)) {
                PyRef<> valuex(value, borrow());
                PyCString valstr(valuex);

                curval = valstr.c_str();

            } else {
                PyErr_SetString(PyExc_ValueError, "extra {} can contain only numbers or strings");
                return NULL;
            }

            parser.setVar(keystr.c_str(), curval);
        }
    } else {
        PyErr_SetString(PyExc_ValueError, "'extra' must be a dict");
        return NULL;
    }

    PyGetBuf buf;
    std::auto_ptr<Config> C;

    PyRef<> listref;

    if(PyObject_HasAttrString(conf, "read")) { // file-like
        PyCString pyname;

        if(!path && PyObject_HasAttrString(conf, "name")) {
            path = pyname.c_str(pydirname(PyObject_GetAttrString(conf, "name")));
        }

        PyRef<> pybytes(PyObject_CallMethod(conf, "read", ""));
        if(!buf.get(pybytes.py())) {
            PyErr_SetString(PyExc_TypeError, "read() must return a buffer");
            return NULL;
        }
        C.reset(parser.parse_byte((const char*)buf.data(), buf.size(), path));

    } else if(buf.get(conf)) {
        C.reset(parser.parse_byte((const char*)buf.data(), buf.size(), path));

#if PY_MAJOR_VERSION >= 3
    } else if(PyUnicode_Check(conf)) { // py3 str (aka unicode) doesn't implement buffer iface
        PyCString buf;
        const char *cbuf = buf.c_str(conf);

        C.reset(parser.parse_byte(cbuf, strlen(cbuf), path));
#endif

    } else {
        if(PyDict_Check(conf)) {
            listref.reset(PyMapping_Items(conf));
            conf = listref.py();
        }
        if(PyList_Check(conf)) {
            C.reset(list2conf(conf));

        } else {
            throw std::invalid_argument("'config' must be dict, list of tuples, or byte buffer");
        }
    }

    return C.release();
}

PyObject* PyGLPSParse(PyObject *unused, PyObject *args, PyObject *kws)
{
    try{
        return conf2dict(PyGLPSParse2Config(unused, args, kws));
    }CATCH()
}
<|endoftext|>