<commit_before>/**
 * Simple Image Processing Library
 * Copyright Erik Smistad 2012
 * See LICENSE file for information on use
 */
#include "Core.hpp"
#include "Visualization.hpp"
#include <limits>

namespace SIPL {
bool init = false;
GThread * gtkThread;
int windowCount;
GMutex * windowCountMutex;
void * initGTK(void * t) {
	gdk_threads_init ();
	gtk_init(0, (char ***) "");
	init = true;
    windowCountMutex = g_mutex_new();
	gdk_threads_enter ();
	gtk_main();
    gdk_threads_leave();
    return 0;
}

void Quit() {
    gtk_main_quit();
	g_thread_join(gtkThread);
    exit(0);
}

bool isInit() {
    return init;
}

void saveImage(BaseDataset * d, const char * filepath, const char * imageType) {
    Visualization * v = new Visualization(d);
    GdkPixbuf * pixBuf = v->render();
    delete v;
	gdk_pixbuf_save(pixBuf, filepath, imageType, NULL, NULL);
}

Visualization * displayVisualization(BaseDataset * d, float level, float window) {
    Visualization * v = new Visualization(d);
    v->setLevel(level);
    v->setWindow(window);
    v->display();
    return v;
}

Visualization * displayVolumeVisualization(BaseDataset * d, int slice, slice_plane direction, float level, float window) {
    Visualization * v = new Visualization(d);
    v->setLevel(level);
    v->setWindow(window);
    v->setSlice(slice);
    v->setDirection(direction);
    v->display();
    return v;
}

Visualization * displayMIPVisualization(BaseDataset * d, slice_plane direction, float level, float window) {
    Visualization * v = new Visualization(d);
    v->setType(MIP);
    v->setLevel(level);
    v->setWindow(window);
    v->setDirection(direction);
    v->display();
    return v;
}

int validateSlice(int slice, slice_plane direction, int3 size) {
    if(slice < 0)
        return 0;

    switch(direction) {
        case X:
            if(slice > size.x-1)
                return size.x-1;
            break;
        case Y:
            if(slice > size.y-1)
                return size.y-1;
            break;
        case Z:
            if(slice > size.z-1)
                return size.z-1;
            break;
    }
    return slice;
}
int getWindowCount() {
    g_mutex_lock(windowCountMutex);
    int wc = windowCount;
    g_mutex_unlock(windowCountMutex);
    return wc;
}
int increaseWindowCount() {
    g_mutex_lock(windowCountMutex);
    windowCount++;
    int wc = windowCount;
    g_mutex_unlock(windowCountMutex);
    return wc;
}
int decreaseWindowCount() {
    g_mutex_lock(windowCountMutex);
    windowCount--;
    int wc = windowCount;
    g_mutex_unlock(windowCountMutex);
    return wc;
}
bool endReached = false;
void quit(void) {
    endReached = true;
    if(getWindowCount() == 0)
        gtk_main_quit();
	g_thread_join(gtkThread);
}

void Init() {
    windowCount = 0;
	if (!init) {
		gtkThread = g_thread_new("main", initGTK, NULL);
	}
	while(!init); // wait for the thread to be created
    atexit(quit);
}

void destroyWindow(GtkWidget * widget, gpointer window) {
	if (decreaseWindowCount() == 0 && endReached) {
		gtk_main_quit();
	}
}

void quitProgram(GtkWidget * widget, gpointer window) {
    gtk_main_quit();
    exit(0);
}

void signalDestroyWindow(GtkWidget * widget, gpointer window) {
	if (decreaseWindowCount() == 0 && endReached) {
        gtk_main_quit();
	} else {
        gtk_widget_hide(GTK_WIDGET(window));
    }
}

void saveFileSignal(GtkWidget * widget, gpointer data) {
	// Get extension to determine image type
    std::string filepath(gtk_file_selection_get_filename (GTK_FILE_SELECTION (((_saveData *)data)->fs)));
	gdk_pixbuf_save(gtk_image_get_pixbuf(
			((_saveData *)data)->image),
			filepath.c_str(),
			filepath.substr(filepath.rfind('.')+1).c_str(),
			NULL, "quality", "100", NULL);

	gtk_widget_destroy(GTK_WIDGET(((_saveData *)data)->fs));
}

void refresh(GtkWidget * widget, gpointer data) {
    Visualization * v = (Visualization *)data;
    v->update();
}

char * floatToChar(float v) {
	char * str = new char[10];
	sprintf(str, "%f", v);
	return str;
}

void getMinAndMax(BaseDataset * image, float * min, float * max) {
    *min = std::numeric_limits<float>::max();
    *max = std::numeric_limits<float>::min();
    if(image->isVectorType) {
        float3 * floatData = image->getVectorFloatData();
        for(int i = 0; i < image->getTotalSize(); i++) {
            *min = std::min(*min, std::min(floatData[i].x, std::min(floatData[i].y, floatData[i].z)));
            *max = std::max(*max, std::max(floatData[i].x, std::max(floatData[i].y, floatData[i].z)));
        }

        delete[] floatData;
    } else {
        float * floatData = image->getFloatData();
        for(int i = 0; i < image->getTotalSize(); i++) {
            if(floatData[i] < *min)
                *min = floatData[i];
            if(floatData[i] > *max)
                *max = floatData[i];
        }
        delete[] floatData;
    }
}

class LevelWindowChange {
    public:
        LevelWindowChange(Visualization * v, BaseDataset * i, GtkWidget * w) {
            viz = v;
            image = i;
            otherWidget = w;
        };
        Visualization * viz;
        BaseDataset * image;
        GtkWidget * otherWidget;
};

void entryChangeLevel(GtkWidget * widget, gpointer data) {
    LevelWindowChange * c = (LevelWindowChange *)data;
    const gchar * value = gtk_entry_get_text(GTK_ENTRY(widget));
    gtk_range_set_value(GTK_RANGE(c->otherWidget), atof((char*)value));
    c->viz->setLevel(c->image,atof((char*)value));
    c->viz->update();
}

void scaleChangeLevel(GtkWidget * widget, gpointer data) {
    LevelWindowChange * c = (LevelWindowChange *)data;
    gdouble value = gtk_range_get_value(GTK_RANGE(widget));
    gtk_entry_set_text(GTK_ENTRY(c->otherWidget), floatToChar((float)value));
    c->viz->setLevel(c->image, (float)value);
    c->viz->update();
}

void entryChangeWindow(GtkWidget * widget, gpointer data) {
    LevelWindowChange * c = (LevelWindowChange *)data;
    const gchar * value = gtk_entry_get_text(GTK_ENTRY(widget));
    gtk_range_set_value(GTK_RANGE(c->otherWidget), atof((char*)value));
    c->viz->setWindow(c->image,atof((char*)value));
    c->viz->update();
}

void scaleChangeWindow(GtkWidget * widget, gpointer data) {
    LevelWindowChange * c = (LevelWindowChange *)data;
    gdouble value = gtk_range_get_value(GTK_RANGE(widget));
    gtk_entry_set_text(GTK_ENTRY(c->otherWidget), floatToChar((float)value));
    c->viz->setWindow(c->image, (float)value);
    c->viz->update();
}

void adjustLevelAndWindow(GtkWidget * widget, gpointer data) {
    Visualization * v = (Visualization *)data;
    // Create window and add sliders and text boxes to it, one for each image
    GtkWidget * window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "Adjust Level & Window");
	gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

    GtkWidget * vbox = gtk_vbox_new(FALSE, 1);
	gtk_container_add (GTK_CONTAINER (window), vbox);

	// TODO: retrieve min and max of image and the current level
	std::vector<BaseDataset *> images = v->getImages();

	for(int i = 0; i < images.size(); i++) {
        float currentLevel = v->getLevel(images[i]);
        float min,max;
        getMinAndMax(images[i], &min, &max);

        GtkWidget * levelLabel = gtk_label_new("Level: ");
        gtk_container_add(GTK_CONTAINER(vbox), levelLabel);
        GtkWidget * levelScale = gtk_hscale_new_with_range(min, max, (max-min)/255.0f);
        gtk_range_set_value(GTK_RANGE(levelScale), currentLevel);
        gtk_container_add(GTK_CONTAINER(vbox), levelScale);
        GtkWidget * levelEntry = gtk_entry_new();
        gtk_entry_set_text(GTK_ENTRY(levelEntry), floatToChar(currentLevel));
        g_signal_connect(
                levelScale, "value-changed",
                G_CALLBACK(scaleChangeLevel),
                new LevelWindowChange(v,images[i],levelEntry));
        g_signal_connect(
                levelEntry, "activate",
                G_CALLBACK(entryChangeLevel),
                new LevelWindowChange(v, images[i], levelScale));
        gtk_container_add(GTK_CONTAINER(vbox), levelEntry);

        float currentWindow = v->getWindow(images[i]);

        GtkWidget * windowLabel = gtk_label_new("Window: ");
        gtk_container_add(GTK_CONTAINER(vbox), windowLabel);
        GtkWidget * windowScale = gtk_hscale_new_with_range(0, max, (max)/255.0f);
        gtk_range_set_value(GTK_RANGE(windowScale), currentWindow);
        gtk_container_add(GTK_CONTAINER(vbox), windowScale);
        GtkWidget * windowEntry = gtk_entry_new();
        gtk_entry_set_text(GTK_ENTRY(windowEntry), floatToChar(currentWindow));
        g_signal_connect(
                windowScale, "value-changed",
                G_CALLBACK(scaleChangeLevel),
                new LevelWindowChange(v,images[i],windowEntry));
        g_signal_connect(
                windowEntry, "activate",
                G_CALLBACK(entryChangeLevel),
                new LevelWindowChange(v, images[i], windowScale));
        gtk_container_add(GTK_CONTAINER(vbox), windowEntry);
	}

    gtk_widget_show_all(window);
}

void saveDialog(GtkWidget * widget, gpointer image) {
	GtkWidget * fileSelection = gtk_file_selection_new("Save an image");

	_saveData * data = (_saveData *)malloc(sizeof(_saveData));
	data->fs = fileSelection;
	data->image = (GtkImage *)image;

	/* Connect the ok_button to file_ok_sel function */
	g_signal_connect (G_OBJECT (GTK_FILE_SELECTION (fileSelection)->ok_button),
			      "clicked", G_CALLBACK (saveFileSignal), data);

	/* Connect the cancel_button to destroy the widget */
	g_signal_connect_swapped (G_OBJECT (GTK_FILE_SELECTION (fileSelection)->cancel_button),
		                      "clicked", G_CALLBACK (gtk_widget_destroy),
				      G_OBJECT (fileSelection));

	gtk_widget_show(fileSelection);
}

uchar color2gray(uchar * p) {
   return 0.33*(p[0]+p[1]+p[2]);
}

void toT(bool * r, uchar * p) {
    *r = color2gray(p) > 128;
}
void toT(uchar * r, uchar * p) {
    *r = color2gray(p);
}
void toT(char * r, uchar * p) {
    *r = color2gray(p)-128;
}
void toT(ushort * r, uchar * p) {
    *r = ((float)color2gray(p)/255.0f)*65535;
}
void toT(short * r, uchar * p) {
    *r = (((float)color2gray(p)/255.0f)-0.5f)*65535;
}
void toT(uint * r, uchar * p) {
    *r = (((float)color2gray(p)/255.0f))*4294967295;
}
void toT(int * r, uchar * p) {
    *r = (((float)color2gray(p)/255.0f)-0.5f)*4294967295;
}
void toT(float * r, uchar * p) {
    *r = (float)color2gray(p)/255.0f;
}
void toT(color_uchar * c, uchar * p) {
    c->red = p[0];
    c->green = p[1];
    c->blue = p[2];
}
void toT(color_float * c, uchar * p) {
    c->red = (float)p[0]/255.0f;
    c->green = (float)p[1]/255.0f;
    c->blue = (float)p[2]/255.0f;
}
void toT(float2 * c, uchar * p) {
    c->x = (float)p[0]/255.0f;
    c->y = (float)p[1]/255.0f;
}
void toT(float3 * c, uchar * p) {
    c->x = (float)p[0]/255.0f;
    c->y = (float)p[1]/255.0f;
    c->z = (float)p[2]/255.0f;
}
template <>
void Dataset<color_uchar>::setDefaultLevelWindow() {
    this->defaultLevel = 255*0.5;
    this->defaultWindow = 255;
}
template <>
void Dataset<uchar>::setDefaultLevelWindow() {
    this->defaultLevel = 255*0.5;
    this->defaultWindow = 255;
}
template <>
void Dataset<char>::setDefaultLevelWindow() {
    this->defaultLevel = 0;
    this->defaultWindow = 255;
}
} // End namespace
<commit_msg>fixed a bug in adjust level window gui<commit_after>/**
 * Simple Image Processing Library
 * Copyright Erik Smistad 2012
 * See LICENSE file for information on use
 */
#include "Core.hpp"
#include "Visualization.hpp"
#include <limits>

namespace SIPL {
bool init = false;
GThread * gtkThread;
int windowCount;
GMutex * windowCountMutex;
void * initGTK(void * t) {
	gdk_threads_init ();
	gtk_init(0, (char ***) "");
	init = true;
    windowCountMutex = g_mutex_new();
	gdk_threads_enter ();
	gtk_main();
    gdk_threads_leave();
    return 0;
}

void Quit() {
    gtk_main_quit();
	g_thread_join(gtkThread);
    exit(0);
}

bool isInit() {
    return init;
}

void saveImage(BaseDataset * d, const char * filepath, const char * imageType) {
    Visualization * v = new Visualization(d);
    GdkPixbuf * pixBuf = v->render();
    delete v;
	gdk_pixbuf_save(pixBuf, filepath, imageType, NULL, NULL);
}

Visualization * displayVisualization(BaseDataset * d, float level, float window) {
    Visualization * v = new Visualization(d);
    v->setLevel(level);
    v->setWindow(window);
    v->display();
    return v;
}

Visualization * displayVolumeVisualization(BaseDataset * d, int slice, slice_plane direction, float level, float window) {
    Visualization * v = new Visualization(d);
    v->setLevel(level);
    v->setWindow(window);
    v->setSlice(slice);
    v->setDirection(direction);
    v->display();
    return v;
}

Visualization * displayMIPVisualization(BaseDataset * d, slice_plane direction, float level, float window) {
    Visualization * v = new Visualization(d);
    v->setType(MIP);
    v->setLevel(level);
    v->setWindow(window);
    v->setDirection(direction);
    v->display();
    return v;
}

int validateSlice(int slice, slice_plane direction, int3 size) {
    if(slice < 0)
        return 0;

    switch(direction) {
        case X:
            if(slice > size.x-1)
                return size.x-1;
            break;
        case Y:
            if(slice > size.y-1)
                return size.y-1;
            break;
        case Z:
            if(slice > size.z-1)
                return size.z-1;
            break;
    }
    return slice;
}
int getWindowCount() {
    g_mutex_lock(windowCountMutex);
    int wc = windowCount;
    g_mutex_unlock(windowCountMutex);
    return wc;
}
int increaseWindowCount() {
    g_mutex_lock(windowCountMutex);
    windowCount++;
    int wc = windowCount;
    g_mutex_unlock(windowCountMutex);
    return wc;
}
int decreaseWindowCount() {
    g_mutex_lock(windowCountMutex);
    windowCount--;
    int wc = windowCount;
    g_mutex_unlock(windowCountMutex);
    return wc;
}
bool endReached = false;
void quit(void) {
    endReached = true;
    if(getWindowCount() == 0)
        gtk_main_quit();
	g_thread_join(gtkThread);
}

void Init() {
    windowCount = 0;
	if (!init) {
		gtkThread = g_thread_new("main", initGTK, NULL);
	}
	while(!init); // wait for the thread to be created
    atexit(quit);
}

void destroyWindow(GtkWidget * widget, gpointer window) {
	if (decreaseWindowCount() == 0 && endReached) {
		gtk_main_quit();
	}
}

void quitProgram(GtkWidget * widget, gpointer window) {
    gtk_main_quit();
    exit(0);
}

void signalDestroyWindow(GtkWidget * widget, gpointer window) {
	if (decreaseWindowCount() == 0 && endReached) {
        gtk_main_quit();
	} else {
        gtk_widget_hide(GTK_WIDGET(window));
    }
}

void saveFileSignal(GtkWidget * widget, gpointer data) {
	// Get extension to determine image type
    std::string filepath(gtk_file_selection_get_filename (GTK_FILE_SELECTION (((_saveData *)data)->fs)));
	gdk_pixbuf_save(gtk_image_get_pixbuf(
			((_saveData *)data)->image),
			filepath.c_str(),
			filepath.substr(filepath.rfind('.')+1).c_str(),
			NULL, "quality", "100", NULL);

	gtk_widget_destroy(GTK_WIDGET(((_saveData *)data)->fs));
}

void refresh(GtkWidget * widget, gpointer data) {
    Visualization * v = (Visualization *)data;
    v->update();
}

char * floatToChar(float v) {
	char * str = new char[10];
	sprintf(str, "%f", v);
	return str;
}

void getMinAndMax(BaseDataset * image, float * min, float * max) {
    *min = std::numeric_limits<float>::max();
    *max = std::numeric_limits<float>::min();
    if(image->isVectorType) {
        float3 * floatData = image->getVectorFloatData();
        for(int i = 0; i < image->getTotalSize(); i++) {
            *min = std::min(*min, std::min(floatData[i].x, std::min(floatData[i].y, floatData[i].z)));
            *max = std::max(*max, std::max(floatData[i].x, std::max(floatData[i].y, floatData[i].z)));
        }

        delete[] floatData;
    } else {
        float * floatData = image->getFloatData();
        for(int i = 0; i < image->getTotalSize(); i++) {
            if(floatData[i] < *min)
                *min = floatData[i];
            if(floatData[i] > *max)
                *max = floatData[i];
        }
        delete[] floatData;
    }
}

class LevelWindowChange {
    public:
        LevelWindowChange(Visualization * v, BaseDataset * i, GtkWidget * w) {
            viz = v;
            image = i;
            otherWidget = w;
        };
        Visualization * viz;
        BaseDataset * image;
        GtkWidget * otherWidget;
};

void entryChangeLevel(GtkWidget * widget, gpointer data) {
    LevelWindowChange * c = (LevelWindowChange *)data;
    const gchar * value = gtk_entry_get_text(GTK_ENTRY(widget));
    gtk_range_set_value(GTK_RANGE(c->otherWidget), atof((char*)value));
    c->viz->setLevel(c->image,atof((char*)value));
    c->viz->update();
}

void scaleChangeLevel(GtkWidget * widget, gpointer data) {
    LevelWindowChange * c = (LevelWindowChange *)data;
    gdouble value = gtk_range_get_value(GTK_RANGE(widget));
    gtk_entry_set_text(GTK_ENTRY(c->otherWidget), floatToChar((float)value));
    c->viz->setLevel(c->image, (float)value);
    c->viz->update();
}

void entryChangeWindow(GtkWidget * widget, gpointer data) {
    LevelWindowChange * c = (LevelWindowChange *)data;
    const gchar * value = gtk_entry_get_text(GTK_ENTRY(widget));
    gtk_range_set_value(GTK_RANGE(c->otherWidget), atof((char*)value));
    c->viz->setWindow(c->image,atof((char*)value));
    c->viz->update();
}

void scaleChangeWindow(GtkWidget * widget, gpointer data) {
    LevelWindowChange * c = (LevelWindowChange *)data;
    gdouble value = gtk_range_get_value(GTK_RANGE(widget));
    gtk_entry_set_text(GTK_ENTRY(c->otherWidget), floatToChar((float)value));
    c->viz->setWindow(c->image, (float)value);
    c->viz->update();
}

void adjustLevelAndWindow(GtkWidget * widget, gpointer data) {
    Visualization * v = (Visualization *)data;
    // Create window and add sliders and text boxes to it, one for each image
    GtkWidget * window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "Adjust Level & Window");
	gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

    GtkWidget * vbox = gtk_vbox_new(FALSE, 1);
	gtk_container_add (GTK_CONTAINER (window), vbox);

	// TODO: retrieve min and max of image and the current level
	std::vector<BaseDataset *> images = v->getImages();

	for(int i = 0; i < images.size(); i++) {
        float currentLevel = v->getLevel(images[i]);
        float min,max;
        getMinAndMax(images[i], &min, &max);

        GtkWidget * levelLabel = gtk_label_new("Level: ");
        gtk_container_add(GTK_CONTAINER(vbox), levelLabel);
        GtkWidget * levelScale = gtk_hscale_new_with_range(min, max, (max-min)/255.0f);
        gtk_range_set_value(GTK_RANGE(levelScale), currentLevel);
        gtk_container_add(GTK_CONTAINER(vbox), levelScale);
        GtkWidget * levelEntry = gtk_entry_new();
        gtk_entry_set_text(GTK_ENTRY(levelEntry), floatToChar(currentLevel));
        g_signal_connect(
                levelScale, "value-changed",
                G_CALLBACK(scaleChangeLevel),
                new LevelWindowChange(v,images[i],levelEntry));
        g_signal_connect(
                levelEntry, "activate",
                G_CALLBACK(entryChangeLevel),
                new LevelWindowChange(v, images[i], levelScale));
        gtk_container_add(GTK_CONTAINER(vbox), levelEntry);

        float currentWindow = v->getWindow(images[i]);

        GtkWidget * windowLabel = gtk_label_new("Window: ");
        gtk_container_add(GTK_CONTAINER(vbox), windowLabel);
        GtkWidget * windowScale = gtk_hscale_new_with_range(0, max, (max)/255.0f);
        gtk_range_set_value(GTK_RANGE(windowScale), currentWindow);
        gtk_container_add(GTK_CONTAINER(vbox), windowScale);
        GtkWidget * windowEntry = gtk_entry_new();
        gtk_entry_set_text(GTK_ENTRY(windowEntry), floatToChar(currentWindow));
        g_signal_connect(
                windowScale, "value-changed",
                G_CALLBACK(scaleChangeWindow),
                new LevelWindowChange(v,images[i],windowEntry));
        g_signal_connect(
                windowEntry, "activate",
                G_CALLBACK(entryChangeWindow),
                new LevelWindowChange(v, images[i], windowScale));
        gtk_container_add(GTK_CONTAINER(vbox), windowEntry);
	}

    gtk_widget_show_all(window);
}

void saveDialog(GtkWidget * widget, gpointer image) {
	GtkWidget * fileSelection = gtk_file_selection_new("Save an image");

	_saveData * data = (_saveData *)malloc(sizeof(_saveData));
	data->fs = fileSelection;
	data->image = (GtkImage *)image;

	/* Connect the ok_button to file_ok_sel function */
	g_signal_connect (G_OBJECT (GTK_FILE_SELECTION (fileSelection)->ok_button),
			      "clicked", G_CALLBACK (saveFileSignal), data);

	/* Connect the cancel_button to destroy the widget */
	g_signal_connect_swapped (G_OBJECT (GTK_FILE_SELECTION (fileSelection)->cancel_button),
		                      "clicked", G_CALLBACK (gtk_widget_destroy),
				      G_OBJECT (fileSelection));

	gtk_widget_show(fileSelection);
}

uchar color2gray(uchar * p) {
   return 0.33*(p[0]+p[1]+p[2]);
}

void toT(bool * r, uchar * p) {
    *r = color2gray(p) > 128;
}
void toT(uchar * r, uchar * p) {
    *r = color2gray(p);
}
void toT(char * r, uchar * p) {
    *r = color2gray(p)-128;
}
void toT(ushort * r, uchar * p) {
    *r = ((float)color2gray(p)/255.0f)*65535;
}
void toT(short * r, uchar * p) {
    *r = (((float)color2gray(p)/255.0f)-0.5f)*65535;
}
void toT(uint * r, uchar * p) {
    *r = (((float)color2gray(p)/255.0f))*4294967295;
}
void toT(int * r, uchar * p) {
    *r = (((float)color2gray(p)/255.0f)-0.5f)*4294967295;
}
void toT(float * r, uchar * p) {
    *r = (float)color2gray(p)/255.0f;
}
void toT(color_uchar * c, uchar * p) {
    c->red = p[0];
    c->green = p[1];
    c->blue = p[2];
}
void toT(color_float * c, uchar * p) {
    c->red = (float)p[0]/255.0f;
    c->green = (float)p[1]/255.0f;
    c->blue = (float)p[2]/255.0f;
}
void toT(float2 * c, uchar * p) {
    c->x = (float)p[0]/255.0f;
    c->y = (float)p[1]/255.0f;
}
void toT(float3 * c, uchar * p) {
    c->x = (float)p[0]/255.0f;
    c->y = (float)p[1]/255.0f;
    c->z = (float)p[2]/255.0f;
}
template <>
void Dataset<color_uchar>::setDefaultLevelWindow() {
    this->defaultLevel = 255*0.5;
    this->defaultWindow = 255;
}
template <>
void Dataset<uchar>::setDefaultLevelWindow() {
    this->defaultLevel = 255*0.5;
    this->defaultWindow = 255;
}
template <>
void Dataset<char>::setDefaultLevelWindow() {
    this->defaultLevel = 0;
    this->defaultWindow = 255;
}
} // End namespace
<|endoftext|>


<commit_before>/** @file
	@ingroup 	jamoma2

	@brief 		Unit test for the Dcblocker class

	@author		Timothy Place, Nathan Wolek
	@copyright	Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org.
	@license	This project is released under the terms of the MIT License.

 */

#include "Jamoma.h"

namespace Jamoma {

	class SampleBundleTest {

		UnitTest<SampleBundleTest>*	mTest;

	public:
		SampleBundleTest(Jamoma::UnitTest<SampleBundleTest>* test)
		: mTest(test)
		{
			testBasic();
            testAutoCreatedSampleBundleGroup();
		}

		void testBasic()
		{
			Jamoma::Gain			my_gain;
			Jamoma::SampleBundle	in_samples(2, 8);

			my_gain.gain = 0.5;

			in_samples.fill(1.0);
			auto out_samples = my_gain(in_samples);

			my_gain.gain = 0.25;
			in_samples = out_samples;
			out_samples = my_gain(in_samples);

			auto bar = in_samples[0][0];
			mTest->TEST_ASSERT("in_sample casting operator", mTest->compare(bar, 0.5));

			in_samples[0][0] = 2.0;
			auto foo = in_samples[0][0];
			mTest->TEST_ASSERT("setting and getting", mTest->compare(foo, 2.0));
		}

        void testAutoCreatedSampleBundleGroup() {

            // NW: this behavoir was noticed while working on tests for Phasor
            // it appears that sample values in first auto created vector change
            // as each subseqent vector is processed

            Jamoma::Phasor my_phasor16;

            my_phasor16.channelCount = 1;
            my_phasor16.frameCount = 16;

            my_phasor16.sampleRate = 48000;
            my_phasor16.phase = 0.0;
            my_phasor16.frequency = 1.0;

            // process vector 1 and stash a value
            auto out_samples16_1 = my_phasor16();

            Jamoma::Sample stash_value1 = out_samples16_1[0][0][0];

            // process vector 2 and stash a value
            auto out_samples16_2 = my_phasor16();

            // grab same value from first vector, should be the same?
            Jamoma::Sample stash_value2 = out_samples16_1[0][0][0];

            // process vector 3 and stash a value
            auto out_samples16_3 = my_phasor16();

            // grab same value from first vector, should be the same?
            Jamoma::Sample stash_value3 = out_samples16_1[0][0][0];

            // process vector 4 and stash a value
            auto out_samples16_4 = my_phasor16();

            // grab same value from first vector, should be the same?
            Jamoma::Sample stash_value4 = out_samples16_1[0][0][0];

            // I would expect all these to be equal, but they are NOT
            // Maybe I misunderstand what auto does?
            // But it is also possible auto is creating wrong type (i.e. not ImmutableSampleBundleGroup)
            // Let's be sure.
            mTest->TEST_ASSERT("stashed value 1 = 2", mTest->compare(stash_value1, stash_value2));
            mTest->TEST_ASSERT("stashed value 1 = 3", mTest->compare(stash_value1, stash_value3));
            mTest->TEST_ASSERT("stashed value 1 = 4", mTest->compare(stash_value1, stash_value4));
            mTest->TEST_ASSERT("stashed value 2 = 3", mTest->compare(stash_value2, stash_value3));
            mTest->TEST_ASSERT("stashed value 2 = 4", mTest->compare(stash_value2, stash_value4));
            mTest->TEST_ASSERT("stashed value 3 = 4", mTest->compare(stash_value3, stash_value4));

        }
	};

} // namespace Jamoma

int main(int argc, const char * argv[])
{
	Jamoma::UnitTest<Jamoma::SampleBundleTest>	aUnitTestInstance;
	return aUnitTestInstance.failureCount();
}
<commit_msg>changing comments and expected results of this test based on issue #63 discussion w @tap<commit_after>/** @file
	@ingroup 	jamoma2

	@brief 		Unit test for the Dcblocker class

	@author		Timothy Place, Nathan Wolek
	@copyright	Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org.
	@license	This project is released under the terms of the MIT License.

 */

#include "Jamoma.h"

namespace Jamoma {

	class SampleBundleTest {

		UnitTest<SampleBundleTest>*	mTest;

	public:
		SampleBundleTest(Jamoma::UnitTest<SampleBundleTest>* test)
		: mTest(test)
		{
			testBasic();
            testAutoCreatedSampleBundleGroup();
		}

		void testBasic()
		{
			Jamoma::Gain			my_gain;
			Jamoma::SampleBundle	in_samples(2, 8);

			my_gain.gain = 0.5;

			in_samples.fill(1.0);
			auto out_samples = my_gain(in_samples);

			my_gain.gain = 0.25;
			in_samples = out_samples;
			out_samples = my_gain(in_samples);

			auto bar = in_samples[0][0];
			mTest->TEST_ASSERT("in_sample casting operator", mTest->compare(bar, 0.5));

			in_samples[0][0] = 2.0;
			auto foo = in_samples[0][0];
			mTest->TEST_ASSERT("setting and getting", mTest->compare(foo, 2.0));
		}

        void testAutoCreatedSampleBundleGroup() {

            /*  NW: this behavior was noticed while working on tests for Phasor & logged as issue #63.
                It is caused by the return type of SharedSampleBundleGroup from our AudioObject.
                The SharedSampleBundleGroup is a shared_ptr, meaning the thing that it points to can and does change.
                This test has been preserved to demonstrate the expected behavior for future reference.
                If a stable set of samples are desired, your local return variable
                should explicitly specify a type of SampleBundle instead of using auto.
            */

            Jamoma::Phasor my_phasor16;

            my_phasor16.channelCount = 1;
            my_phasor16.frameCount = 16;

            my_phasor16.sampleRate = 48000;
            my_phasor16.phase = 0.0;
            my_phasor16.frequency = 1.0;

            // process vector 1 and stash a value
            auto out_samples16_1 = my_phasor16();

            Jamoma::Sample stash_value1 = out_samples16_1[0][0][0];

            // process vector 2 and stash a value
            auto out_samples16_2 = my_phasor16();

            // grab same value from first vector, should be the same?
            Jamoma::Sample stash_value2 = out_samples16_1[0][0][0];

            // process vector 3 and stash a value
            auto out_samples16_3 = my_phasor16();

            // grab same value from first vector, should be the same?
            Jamoma::Sample stash_value3 = out_samples16_1[0][0][0];

            // process vector 4 and stash a value
            auto out_samples16_4 = my_phasor16();

            // grab same value from first vector, should be the same?
            Jamoma::Sample stash_value4 = out_samples16_1[0][0][0];

            // If you misunderstand what auto is doing, you may expect the following values to be equal.
            // However, because it is a shared pointer, the values are changing with each call to the operator.
            mTest->TEST_ASSERT("stashed value 1 = 2", mTest->compare(stash_value1, stash_value2, false));
            mTest->TEST_ASSERT("stashed value 1 = 3", mTest->compare(stash_value1, stash_value3, false));
            mTest->TEST_ASSERT("stashed value 1 = 4", mTest->compare(stash_value1, stash_value4, false));
            mTest->TEST_ASSERT("stashed value 2 = 3", mTest->compare(stash_value2, stash_value3, false));
            mTest->TEST_ASSERT("stashed value 2 = 4", mTest->compare(stash_value2, stash_value4, false));
            mTest->TEST_ASSERT("stashed value 3 = 4", mTest->compare(stash_value3, stash_value4, false));

        }
	};

} // namespace Jamoma

int main(int argc, const char * argv[])
{
	Jamoma::UnitTest<Jamoma::SampleBundleTest>	aUnitTestInstance;
	return aUnitTestInstance.failureCount();
}
<|endoftext|>


<commit_before>#include <tests/lib/test.h>

#include <tests/lib/glib-helpers/test-conn-helper.h>

#include <tests/lib/glib/simple-conn.h>
#include <tests/lib/glib/stream-tube-chan.h>

#include <TelepathyQt4/ClientHandlerInterface>
#include <TelepathyQt4/Connection>
#include <TelepathyQt4/IncomingStreamTubeChannel>
#include <TelepathyQt4/OutgoingStreamTubeChannel>
#include <TelepathyQt4/ReferencedHandles>
#include <TelepathyQt4/StreamTubeChannel>
#include <TelepathyQt4/StreamTubeClient>
#include <TelepathyQt4/StreamTubeServer>

#include <telepathy-glib/telepathy-glib.h>

#include <cstring>

#include <QTcpServer>

using namespace Tp;
using namespace Tp::Client;

namespace
{

void destroySocketControlList(gpointer data)
{
    g_array_free((GArray *) data, TRUE);
}

// TODO: turn into something which supports everything, or everything except port/credentials ACs
GHashTable *createSupportedSocketTypesHash(TpSocketAddressType addressType,
        TpSocketAccessControl accessControl)
{
    GHashTable *ret;
    GArray *tab;

    ret = g_hash_table_new_full(NULL, NULL, NULL, destroySocketControlList);

    tab = g_array_sized_new(FALSE, FALSE, sizeof(TpSocketAccessControl), 1);
    g_array_append_val(tab, accessControl);

    g_hash_table_insert(ret, GUINT_TO_POINTER(addressType), tab);

    return ret;
}

}

class TestStreamTubeHandlers : public Test
{
    Q_OBJECT

public:
    TestStreamTubeHandlers(QObject *parent = 0)
        : Test(parent), mChanService(0)
    { }

private Q_SLOTS:
    void initTestCase();
    void init();

    void testRegistration();

    void cleanup();
    void cleanupTestCase();

private:
    QMap<QString, ClientHandlerInterface *> ourHandlers();

    void createTubeChannel(bool requested, TpSocketAddressType addressType,
            TpSocketAccessControl accessControl, bool withContact);

    TestConnHelper *mConn;
    TpTestsStreamTubeChannel *mChanService;
    StreamTubeChannelPtr mChan;
};

// TODO: turn into creating one (of possibly many) channels, which support everything, or everything
// except Port and Creds ACs
void TestStreamTubeHandlers::createTubeChannel(bool requested,
        TpSocketAddressType addressType,
        TpSocketAccessControl accessControl,
        bool withContact)
{
    mLoop->processEvents();
    tp_clear_object(&mChanService);

    /* Create service-side tube channel object */
    QString chanPath = QString(QLatin1String("%1/Channel")).arg(mConn->objectPath());

    TpHandleRepoIface *contactRepo = tp_base_connection_get_handles(
            TP_BASE_CONNECTION(mConn->service()), TP_HANDLE_TYPE_CONTACT);
    TpHandleRepoIface *roomRepo = tp_base_connection_get_handles(
            TP_BASE_CONNECTION(mConn->service()), TP_HANDLE_TYPE_ROOM);
    TpHandle handle;
    GType type;
    if (withContact) {
        handle = tp_handle_ensure(contactRepo, "bob", NULL, NULL);
        type = TP_TESTS_TYPE_CONTACT_STREAM_TUBE_CHANNEL;
    } else {
        handle = tp_handle_ensure(roomRepo, "#test", NULL, NULL);
        type = TP_TESTS_TYPE_ROOM_STREAM_TUBE_CHANNEL;
    }

    TpHandle alfHandle = tp_handle_ensure(contactRepo, "alf", NULL, NULL);

    GHashTable *sockets = createSupportedSocketTypesHash(addressType, accessControl);

    mChanService = TP_TESTS_STREAM_TUBE_CHANNEL(g_object_new(
            type,
            "connection", mConn->service(),
            "handle", handle,
            "requested", requested,
            "object-path", chanPath.toLatin1().constData(),
            "supported-socket-types", sockets,
            "initiator-handle", alfHandle,
            NULL));

    /* Create client-side tube channel object */
    GHashTable *props;
    g_object_get(mChanService, "channel-properties", &props, NULL);

    g_hash_table_unref(props);
    g_hash_table_unref(sockets);

    if (withContact)
        tp_handle_unref(contactRepo, handle);
    else
        tp_handle_unref(roomRepo, handle);
}

QMap<QString, ClientHandlerInterface *> TestStreamTubeHandlers::ourHandlers()
{
    QStringList registeredNames =
        QDBusConnection::sessionBus().interface()->registeredServiceNames();
    QMap<QString, ClientHandlerInterface *> handlers;

    Q_FOREACH (QString name, registeredNames) {
        if (!name.startsWith(QLatin1String("org.freedesktop.Telepathy.Client."))) {
            continue;
        }

        if (QDBusConnection::sessionBus().interface()->serviceOwner(name).value() !=
                QDBusConnection::sessionBus().baseService()) {
            continue;
        }

        QString path = QLatin1Char('/') + name;
        path.replace(QLatin1Char('.'), QLatin1Char('/'));

        ClientInterface client(name, path);
        QStringList ifaces;
        if (!waitForProperty(client.requestPropertyInterfaces(), &ifaces)) {
            continue;
        }

        if (!ifaces.contains(TP_QT4_IFACE_CLIENT_HANDLER)) {
            continue;
        }

        handlers.insert(name.mid(std::strlen("org.freedesktop.Telepathy.Client.")),
                new ClientHandlerInterface(name, path, this));
    }

    return handlers;
}

void TestStreamTubeHandlers::initTestCase()
{
    initTestCaseImpl();

    g_type_init();
    g_set_prgname("stream-tube-handlers");
    tp_debug_set_flags("all");
    dbus_g_bus_get(DBUS_BUS_STARTER, 0);

    mConn = new TestConnHelper(this,
            TP_TESTS_TYPE_SIMPLE_CONNECTION,
            "account", "me@example.com",
            "protocol", "example",
            NULL);
    QCOMPARE(mConn->connect(), true);
}

void TestStreamTubeHandlers::init()
{
    initImpl();
}

void TestStreamTubeHandlers::testRegistration()
{
    StreamTubeServerPtr httpServer =
        StreamTubeServer::create(QStringList() << QLatin1String("http"), QStringList());
    StreamTubeServerPtr whiteboardServer =
        StreamTubeServer::create(QStringList() << QLatin1String("sketch"),
                QStringList() << QLatin1String("sketch"), QString(), true);
    StreamTubeServerPtr activatedServer =
        StreamTubeServer::create(QStringList() << QLatin1String("ftp"), QStringList(),
                QLatin1String("vsftpd"));

    StreamTubeClientPtr browser =
        StreamTubeClient::create(QStringList() << QLatin1String("http"), QStringList(),
                QLatin1String("Debian.Iceweasel"));
    StreamTubeClientPtr collaborationTool =
        StreamTubeClient::create(QStringList() << QLatin1String("sketch") << QLatin1String("ftp"),
                QStringList() << QLatin1String("sketch"));

    QCOMPARE(activatedServer->clientName(), QLatin1String("vsftpd"));
    QCOMPARE(browser->clientName(), QLatin1String("Debian.Iceweasel"));

    class CookieGenerator : public StreamTubeServer::ParametersGenerator
    {
    public:
        CookieGenerator() : serial(0) {}

        QVariantMap nextParameters(const AccountPtr &account, const OutgoingStreamTubeChannelPtr &tube,
                const ChannelRequestHints &hints) const
        {
            QVariantMap params;
            params.insert(QLatin1String("cookie-y"),
                    QString(QLatin1String("e982mrh2mr2h+%1")).arg(serial++));
            return params;
        }

    private:
        mutable uint serial; // mmm. I wonder if we should make nextParameters() non-const? that'd require giving a non const pointer when exporting too.
    } httpGenerator;

    QVariantMap whiteboardParams;
    whiteboardParams.insert(QLatin1String("password"),
            QString::fromLatin1("s3kr1t"));

    QTcpServer server;
    server.listen();

    httpServer->exportTcpSocket(QHostAddress::LocalHost, 80, &httpGenerator);
    whiteboardServer->exportTcpSocket(QHostAddress::LocalHost, 31552, whiteboardParams);
    activatedServer->exportTcpSocket(&server);

    browser->setToAcceptAsTcp();
    collaborationTool->setToAcceptAsUnix(true);

    QVERIFY(httpServer->isRegistered());
    QVERIFY(whiteboardServer->isRegistered());
    QVERIFY(activatedServer->isRegistered());
    QVERIFY(browser->isRegistered());
    QVERIFY(collaborationTool->isRegistered());

    QMap<QString, ClientHandlerInterface *> handlers = ourHandlers();

    QVERIFY(!handlers.isEmpty());
    QCOMPARE(handlers.size(), 5);

    QVERIFY(handlers.contains(httpServer->clientName()));
    QVERIFY(handlers.contains(whiteboardServer->clientName()));
    QVERIFY(handlers.contains(QLatin1String("vsftpd")));
    QVERIFY(handlers.contains(QLatin1String("Debian.Iceweasel")));
    QVERIFY(handlers.contains(collaborationTool->clientName()));
}

void TestStreamTubeHandlers::cleanup()
{
    cleanupImpl();

    if (mChan && mChan->isValid()) {
        qDebug() << "waiting for the channel to become invalidated";

        QVERIFY(connect(mChan.data(),
                SIGNAL(invalidated(Tp::DBusProxy*,QString,QString)),
                mLoop,
                SLOT(quit())));
        tp_base_channel_close(TP_BASE_CHANNEL(mChanService));
        QCOMPARE(mLoop->exec(), 0);
    }

    mChan.reset();

    if (mChanService != 0) {
        g_object_unref(mChanService);
        mChanService = 0;
    }

    mLoop->processEvents();
}

void TestStreamTubeHandlers::cleanupTestCase()
{
    QCOMPARE(mConn->disconnect(), true);
    delete mConn;

    cleanupTestCaseImpl();
}

QTEST_MAIN(TestStreamTubeHandlers)
#include "_gen/stream-tube-handlers.cpp.moc.hpp"
<commit_msg>Test basic StreamTubeServer export/handle operation<commit_after>#include <tests/lib/test.h>

#include <tests/lib/glib-helpers/test-conn-helper.h>

#include <tests/lib/glib/simple-conn.h>
#include <tests/lib/glib/stream-tube-chan.h>

#include <TelepathyQt4/Account>
#include <TelepathyQt4/AccountManager>
#include <TelepathyQt4/ChannelClassSpec>
#include <TelepathyQt4/ClientHandlerInterface>
#include <TelepathyQt4/ClientRegistrar>
#include <TelepathyQt4/Connection>
#include <TelepathyQt4/IncomingStreamTubeChannel>
#include <TelepathyQt4/OutgoingStreamTubeChannel>
#include <TelepathyQt4/PendingAccount>
#include <TelepathyQt4/PendingReady>
#include <TelepathyQt4/ReferencedHandles>
#include <TelepathyQt4/StreamTubeChannel>
#include <TelepathyQt4/StreamTubeClient>
#include <TelepathyQt4/StreamTubeServer>

#include <telepathy-glib/telepathy-glib.h>

#include <cstring>

#include <QTcpServer>

using namespace Tp;
using namespace Tp::Client;

namespace
{

class ChannelRequestAdaptor : public QDBusAbstractAdaptor
{
    Q_OBJECT
    Q_CLASSINFO("D-Bus Interface", "org.freedesktop.Telepathy.ChannelRequest")
    Q_CLASSINFO("D-Bus Introspection", ""
"  <interface name=\"org.freedesktop.Telepathy.ChannelRequest\" >\n"
"    <property name=\"Account\" type=\"o\" access=\"read\" />\n"
"    <property name=\"UserActionTime\" type=\"x\" access=\"read\" />\n"
"    <property name=\"PreferredHandler\" type=\"s\" access=\"read\" />\n"
"    <property name=\"Requests\" type=\"aa{sv}\" access=\"read\" />\n"
"    <property name=\"Interfaces\" type=\"as\" access=\"read\" />\n"
"    <property name=\"Hints\" type=\"a{sv}\" access=\"read\" />\n"
"    <method name=\"Proceed\" />\n"
"    <method name=\"Cancel\" />\n"
"    <signal name=\"Failed\" >\n"
"      <arg name=\"Error\" type=\"s\" />\n"
"      <arg name=\"Message\" type=\"s\" />\n"
"    </signal>\n"
"    <signal name=\"Succeeded\" />\n"
"    <signal name=\"SucceededWithChannel\" >\n"
"      <arg name=\"Connection\" type=\"o\" />\n"
"      <arg name=\"ConnectionProperties\" type=\"a{sv}\" />\n"
"      <arg name=\"Channel\" type=\"o\" />\n"
"      <arg name=\"ChannelProperties\" type=\"a{sv}\" />\n"
"    </signal>\n"
"  </interface>\n"
        "")

    Q_PROPERTY(QDBusObjectPath Account READ Account)
    Q_PROPERTY(qulonglong UserActionTime READ UserActionTime)
    Q_PROPERTY(QString PreferredHandler READ PreferredHandler)
    Q_PROPERTY(QualifiedPropertyValueMapList Requests READ Requests)
    Q_PROPERTY(QStringList Interfaces READ Interfaces)
    Q_PROPERTY(QVariantMap Hints READ Hints)

public:
    ChannelRequestAdaptor(QDBusObjectPath account,
            qulonglong userActionTime,
            QString preferredHandler,
            QualifiedPropertyValueMapList requests,
            QStringList interfaces,
            bool shouldFail,
            bool proceedNoop,
            QVariantMap hints,
            QObject *parent)
        : QDBusAbstractAdaptor(parent),
          mAccount(account), mUserActionTime(userActionTime),
          mPreferredHandler(preferredHandler), mRequests(requests),
          mInterfaces(interfaces), mShouldFail(shouldFail),
          mProceedNoop(proceedNoop), mHints(hints)
    {
    }

    virtual ~ChannelRequestAdaptor()
    {
    }

    void setChan(const QString &connPath, const QVariantMap &connProps,
            const QString &chanPath, const QVariantMap &chanProps)
    {
        mConnPath = connPath;
        mConnProps = connProps;
        mChanPath = chanPath;
        mChanProps = chanProps;
    }

public: // Properties
    inline QDBusObjectPath Account() const
    {
        return mAccount;
    }

    inline qulonglong UserActionTime() const
    {
        return mUserActionTime;
    }

    inline QString PreferredHandler() const
    {
        return mPreferredHandler;
    }

    inline QualifiedPropertyValueMapList Requests() const
    {
        return mRequests;
    }

    inline QStringList Interfaces() const
    {
        return mInterfaces;
    }

    inline QVariantMap Hints() const
    {
        return mHints;
    }

public Q_SLOTS: // Methods
    void Proceed()
    {
        if (mProceedNoop) {
            return;
        }

        if (mShouldFail) {
            QTimer::singleShot(0, this, SLOT(fail()));
        } else {
            QTimer::singleShot(0, this, SLOT(succeed()));
        }
    }

    void Cancel()
    {
        Q_EMIT Failed(QLatin1String(TELEPATHY_ERROR_CANCELLED), QLatin1String("Cancelled"));
    }

Q_SIGNALS: // Signals
    void Failed(const QString &error, const QString &message);
    void Succeeded();
    void SucceededWithChannel(const QDBusObjectPath &connPath, const QVariantMap &connProps,
            const QDBusObjectPath &chanPath, const QVariantMap &chanProps);

private Q_SLOTS:
    void fail()
    {
        Q_EMIT Failed(QLatin1String(TELEPATHY_ERROR_NOT_AVAILABLE), QLatin1String("Not available"));
    }

    void succeed()
    {
        if (!mConnPath.isEmpty() && !mChanPath.isEmpty()) {
            Q_EMIT SucceededWithChannel(QDBusObjectPath(mConnPath), mConnProps,
                    QDBusObjectPath(mChanPath), mChanProps);
        }

        Q_EMIT Succeeded();
    }

private:
    QDBusObjectPath mAccount;
    qulonglong mUserActionTime;
    QString mPreferredHandler;
    QualifiedPropertyValueMapList mRequests;
    QStringList mInterfaces;
    bool mShouldFail;
    bool mProceedNoop;
    QVariantMap mHints;
    QString mConnPath, mChanPath;
    QVariantMap mConnProps, mChanProps;
};

void destroySocketControlList(gpointer data)
{
    g_array_free(reinterpret_cast<GArray *>(data), TRUE);
}

GHashTable *createSupportedSocketTypesHash(bool supportMonitoring)
{
    GHashTable *ret;
    GArray *tab;
    TpSocketAccessControl ac;

    ret = g_hash_table_new_full(NULL, NULL, NULL, destroySocketControlList);

    // IPv4
    tab = g_array_sized_new(FALSE, FALSE, sizeof(TpSocketAccessControl), 1);
    ac = TP_SOCKET_ACCESS_CONTROL_LOCALHOST;
    g_array_append_val(tab, ac);

    if (supportMonitoring) {
        ac = TP_SOCKET_ACCESS_CONTROL_PORT;
        g_array_append_val(tab, ac);
    }

    g_hash_table_insert(ret, GUINT_TO_POINTER(TP_SOCKET_ADDRESS_TYPE_IPV4), tab);

    // IPv6
    tab = g_array_sized_new(FALSE, FALSE, sizeof(TpSocketAccessControl), 1);
    ac = TP_SOCKET_ACCESS_CONTROL_LOCALHOST;
    g_array_append_val(tab, ac);

    if (supportMonitoring) {
        ac = TP_SOCKET_ACCESS_CONTROL_PORT;
        g_array_append_val(tab, ac);
    }

    g_hash_table_insert(ret, GUINT_TO_POINTER(TP_SOCKET_ADDRESS_TYPE_IPV6), tab);

    // Named UNIX
    tab = g_array_sized_new(FALSE, FALSE, sizeof(TpSocketAccessControl), 1);
    ac = TP_SOCKET_ACCESS_CONTROL_LOCALHOST;
    g_array_append_val(tab, ac);

    if (supportMonitoring) {
        ac = TP_SOCKET_ACCESS_CONTROL_CREDENTIALS;
        g_array_append_val(tab, ac);
    }

    g_hash_table_insert(ret, GUINT_TO_POINTER(TP_SOCKET_ADDRESS_TYPE_UNIX), tab);

    // Abstract UNIX
    tab = g_array_sized_new(FALSE, FALSE, sizeof(TpSocketAccessControl), 1);
    ac = TP_SOCKET_ACCESS_CONTROL_LOCALHOST;
    g_array_append_val(tab, ac);

    if (supportMonitoring) {
        ac = TP_SOCKET_ACCESS_CONTROL_CREDENTIALS;
        g_array_append_val(tab, ac);
    }

    g_hash_table_insert(ret, GUINT_TO_POINTER(TP_SOCKET_ADDRESS_TYPE_ABSTRACT_UNIX), tab);

    return ret;
}

}

class TestStreamTubeHandlers : public Test
{
    Q_OBJECT

public:
    TestStreamTubeHandlers(QObject *parent = 0)
        : Test(parent), mChanService(0)
    { }

protected Q_SLOTS:
    void onTubeRequested(const Tp::AccountPtr &, const Tp::OutgoingStreamTubeChannelPtr &,
            const QDateTime &, const Tp::ChannelRequestHints &);

private Q_SLOTS:
    void initTestCase();
    void init();

    void testRegistration();
    void testBasicTcpExport();

    void cleanup();
    void cleanupTestCase();

private:
    QMap<QString, ClientHandlerInterface *> ourHandlers();

    QPair<QString, QVariantMap> createTubeChannel(bool requested, HandleType type,
            bool supportMonitoring);

    AccountManagerPtr mAM;
    AccountPtr mAcc;
    TestConnHelper *mConn;
    TpTestsStreamTubeChannel *mChanService;

    OutgoingStreamTubeChannelPtr mRequestedTube;
    QDateTime mRequestTime;
    ChannelRequestHints mRequestHints;
};

// TODO: turn into creating one (of possibly many) channels
QPair<QString, QVariantMap> TestStreamTubeHandlers::createTubeChannel(bool requested,
        HandleType handleType,
        bool supportMonitoring)
{
    mLoop->processEvents();
    tp_clear_object(&mChanService);

    /* Create service-side tube channel object */
    QString chanPath = QString(QLatin1String("%1/Channel%2%3%4"))
        .arg(mConn->objectPath())
        .arg(requested)
        .arg(static_cast<uint>(handleType))
        .arg(supportMonitoring);
    QVariantMap chanProps;

    chanProps.insert(TP_QT4_IFACE_CHANNEL + QString::fromLatin1(".ChannelType"),
            TP_QT4_IFACE_CHANNEL_TYPE_STREAM_TUBE);
    chanProps.insert(TP_QT4_IFACE_CHANNEL + QString::fromLatin1(".Requested"), requested);
    chanProps.insert(TP_QT4_IFACE_CHANNEL + QString::fromLatin1(".TargetHandleType"),
            static_cast<uint>(handleType));

    TpHandleRepoIface *contactRepo = tp_base_connection_get_handles(
            TP_BASE_CONNECTION(mConn->service()), TP_HANDLE_TYPE_CONTACT);
    TpHandleRepoIface *roomRepo = tp_base_connection_get_handles(
            TP_BASE_CONNECTION(mConn->service()), TP_HANDLE_TYPE_ROOM);
    TpHandle handle;
    GType type;
    if (handleType == HandleTypeContact) {
        handle = tp_handle_ensure(contactRepo, "bob", NULL, NULL);
        type = TP_TESTS_TYPE_CONTACT_STREAM_TUBE_CHANNEL;
        chanProps.insert(TP_QT4_IFACE_CHANNEL + QString::fromLatin1(".TargetID"),
                QString::fromLatin1("bob"));
    } else {
        handle = tp_handle_ensure(roomRepo, "#test", NULL, NULL);
        type = TP_TESTS_TYPE_ROOM_STREAM_TUBE_CHANNEL;
        chanProps.insert(TP_QT4_IFACE_CHANNEL + QString::fromLatin1(".TargetID"),
                QString::fromLatin1("#test"));
    }

    chanProps.insert(TP_QT4_IFACE_CHANNEL + QString::fromLatin1(".TargetHandle"), handle);

    TpHandle alfHandle = tp_handle_ensure(contactRepo, "alf", NULL, NULL);

    GHashTable *sockets = createSupportedSocketTypesHash(supportMonitoring);

    mChanService = TP_TESTS_STREAM_TUBE_CHANNEL(g_object_new(
            type,
            "connection", mConn->service(),
            "handle", handle,
            "requested", requested,
            "object-path", chanPath.toLatin1().constData(),
            "supported-socket-types", sockets,
            "initiator-handle", alfHandle,
            NULL));

    if (handleType == HandleTypeContact)
        tp_handle_unref(contactRepo, handle);
    else
        tp_handle_unref(roomRepo, handle);

    return qMakePair(chanPath, chanProps);
}

QMap<QString, ClientHandlerInterface *> TestStreamTubeHandlers::ourHandlers()
{
    QStringList registeredNames =
        QDBusConnection::sessionBus().interface()->registeredServiceNames();
    QMap<QString, ClientHandlerInterface *> handlers;

    Q_FOREACH (QString name, registeredNames) {
        if (!name.startsWith(QLatin1String("org.freedesktop.Telepathy.Client."))) {
            continue;
        }

        if (QDBusConnection::sessionBus().interface()->serviceOwner(name).value() !=
                QDBusConnection::sessionBus().baseService()) {
            continue;
        }

        QString path = QLatin1Char('/') + name;
        path.replace(QLatin1Char('.'), QLatin1Char('/'));

        ClientInterface client(name, path);
        QStringList ifaces;
        if (!waitForProperty(client.requestPropertyInterfaces(), &ifaces)) {
            continue;
        }

        if (!ifaces.contains(TP_QT4_IFACE_CLIENT_HANDLER)) {
            continue;
        }

        handlers.insert(name.mid(std::strlen("org.freedesktop.Telepathy.Client.")),
                new ClientHandlerInterface(name, path, this));
    }

    return handlers;
}

void TestStreamTubeHandlers::onTubeRequested(
        const Tp::AccountPtr &acc,
        const Tp::OutgoingStreamTubeChannelPtr &tube,
        const QDateTime &userActionTime,
        const Tp::ChannelRequestHints &hints)
{
    qDebug() << "tube" << tube->objectPath() << "requested on account" << acc->objectPath();

    // We don't use a shared factory here so the proxies will be different, but the object path
    // should be the same
    if (acc->objectPath() != mAcc->objectPath()) {
        qWarning() << "account" << acc->objectPath() << "is not the expected" << mAcc->objectPath();
        mLoop->exit(1);
    }

    // We always set the user action time in the past, so if that's carried over correctly, it won't
    // be any more recent than the current time

    if (mRequestTime >= QDateTime::currentDateTime()) {
        qWarning() << "user action time later than expected";
        mLoop->exit(2);
    }

    mRequestedTube = tube;
    mRequestTime = userActionTime;
    mRequestHints = hints;

    mLoop->exit(0);
}

void TestStreamTubeHandlers::initTestCase()
{
    initTestCaseImpl();

    g_type_init();
    g_set_prgname("stream-tube-handlers");
    tp_debug_set_flags("all");
    dbus_g_bus_get(DBUS_BUS_STARTER, 0);

    mAM = AccountManager::create();
    QVERIFY(connect(mAM->becomeReady(),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);
    QCOMPARE(mAM->isReady(), true);

    QVariantMap parameters;
    parameters[QLatin1String("account")] = QLatin1String("foobar");
    PendingAccount *pacc = mAM->createAccount(QLatin1String("foo"),
            QLatin1String("bar"), QLatin1String("foobar"), parameters);
    QVERIFY(connect(pacc,
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);
    QVERIFY(pacc->account());
    mAcc= pacc->account();

    mConn = new TestConnHelper(this,
            TP_TESTS_TYPE_SIMPLE_CONNECTION,
            "account", "me@example.com",
            "protocol", "example",
            NULL);
    QCOMPARE(mConn->connect(), true);
}

void TestStreamTubeHandlers::init()
{
    initImpl();
}

void TestStreamTubeHandlers::testRegistration()
{
    StreamTubeServerPtr httpServer =
        StreamTubeServer::create(QStringList() << QLatin1String("http"), QStringList());
    StreamTubeServerPtr whiteboardServer =
        StreamTubeServer::create(QStringList() << QLatin1String("sketch"),
                QStringList() << QLatin1String("sketch"), QString(), true);
    StreamTubeServerPtr activatedServer =
        StreamTubeServer::create(QStringList() << QLatin1String("ftp"), QStringList(),
                QLatin1String("vsftpd"));

    StreamTubeClientPtr browser =
        StreamTubeClient::create(QStringList() << QLatin1String("http"), QStringList(),
                QLatin1String("Debian.Iceweasel"));
    StreamTubeClientPtr collaborationTool =
        StreamTubeClient::create(QStringList() << QLatin1String("sketch") << QLatin1String("ftp"),
                QStringList() << QLatin1String("sketch"));

    QCOMPARE(activatedServer->clientName(), QLatin1String("vsftpd"));
    QCOMPARE(browser->clientName(), QLatin1String("Debian.Iceweasel"));

    class CookieGenerator : public StreamTubeServer::ParametersGenerator
    {
    public:
        CookieGenerator() : serial(0) {}

        QVariantMap nextParameters(const AccountPtr &account, const OutgoingStreamTubeChannelPtr &tube,
                const ChannelRequestHints &hints) const
        {
            QVariantMap params;
            params.insert(QLatin1String("cookie-y"),
                    QString(QLatin1String("e982mrh2mr2h+%1")).arg(serial++));
            return params;
        }

    private:
        mutable uint serial; // mmm. I wonder if we should make nextParameters() non-const? that'd require giving a non const pointer when exporting too.
    } httpGenerator;

    QVariantMap whiteboardParams;
    whiteboardParams.insert(QLatin1String("password"),
            QString::fromLatin1("s3kr1t"));

    QTcpServer server;
    server.listen();

    httpServer->exportTcpSocket(QHostAddress::LocalHost, 80, &httpGenerator);
    whiteboardServer->exportTcpSocket(QHostAddress::LocalHost, 31552, whiteboardParams);
    activatedServer->exportTcpSocket(&server);

    browser->setToAcceptAsTcp();
    collaborationTool->setToAcceptAsUnix(true);

    QVERIFY(httpServer->isRegistered());
    QVERIFY(whiteboardServer->isRegistered());
    QVERIFY(activatedServer->isRegistered());
    QVERIFY(browser->isRegistered());
    QVERIFY(collaborationTool->isRegistered());

    QMap<QString, ClientHandlerInterface *> handlers = ourHandlers();

    QVERIFY(!handlers.isEmpty());
    QCOMPARE(handlers.size(), 5);

    QVERIFY(handlers.contains(httpServer->clientName()));
    QVERIFY(handlers.contains(whiteboardServer->clientName()));
    QVERIFY(handlers.contains(QLatin1String("vsftpd")));
    QVERIFY(handlers.contains(QLatin1String("Debian.Iceweasel")));
    QVERIFY(handlers.contains(collaborationTool->clientName()));
}

void TestStreamTubeHandlers::testBasicTcpExport()
{
    StreamTubeServerPtr server =
        StreamTubeServer::create(QStringList() << QLatin1String("ftp"), QStringList(),
                QLatin1String("vsftpd"));
    server->exportTcpSocket(QHostAddress::LocalHost, 22);
    QVERIFY(server->isRegistered());

    QMap<QString, ClientHandlerInterface *> handlers = ourHandlers();

    QVERIFY(!handlers.isEmpty());
    ClientHandlerInterface *handler = handlers.value(server->clientName());
    QVERIFY(handler != 0);

    ChannelClassList filter;
    QVERIFY(waitForProperty(handler->requestPropertyHandlerChannelFilter(), &filter));

    QCOMPARE(filter.size(), 1);
    QVERIFY(ChannelClassSpec(filter.first())
            == ChannelClassSpec::outgoingStreamTube(QLatin1String("ftp")));

    QPair<QString, QVariantMap> chan = createTubeChannel(true, HandleTypeContact, false);

    QVERIFY(connect(server.data(),
                SIGNAL(tubeRequested(Tp::AccountPtr,Tp::OutgoingStreamTubeChannelPtr,QDateTime,Tp::ChannelRequestHints)),
                SLOT(onTubeRequested(Tp::AccountPtr,Tp::OutgoingStreamTubeChannelPtr,QDateTime,Tp::ChannelRequestHints))));

    QDateTime userActionTime = QDateTime::currentDateTime().addDays(-1);
    userActionTime = userActionTime.addMSecs(-userActionTime.time().msec());
    qDebug() << userActionTime;

    QVariantMap hints;
    hints.insert(QLatin1String("tp-qt4-test-request-hint-herring-color-rgba"), uint(0xff000000));

    QObject *request = new QObject(this);
    QString requestPath = QLatin1String("/org/freedesktop/Telepathy/ChannelRequest/Request1");

    QDBusConnection bus = server->registrar()->dbusConnection();
    new ChannelRequestAdaptor(QDBusObjectPath(mAcc->objectPath()),
            userActionTime.toTime_t(),
            QString(),
            QualifiedPropertyValueMapList(),
            QStringList(),
            false,
            false,
            hints,
            request);
    QVERIFY(bus.registerService(TP_QT4_CHANNEL_DISPATCHER_BUS_NAME));
    QVERIFY(bus.registerObject(requestPath, request));

    ChannelDetails details = { QDBusObjectPath(chan.first), chan.second };
    handler->HandleChannels(
            QDBusObjectPath(mAcc->objectPath()),
            QDBusObjectPath(mConn->objectPath()),
            ChannelDetailsList() << details,
            ObjectPathList() << QDBusObjectPath(requestPath),
            userActionTime.toTime_t(),
            QVariantMap());

    QCOMPARE(mLoop->exec(), 0);

    QCOMPARE(mRequestedTube->objectPath(), chan.first);
    QCOMPARE(mRequestTime, userActionTime);
    QCOMPARE(mRequestHints.allHints(), hints);
}

void TestStreamTubeHandlers::cleanup()
{
    cleanupImpl();

    mRequestHints = ChannelRequestHints();

    if (mRequestedTube && mRequestedTube->isValid()) {
        qDebug() << "waiting for the channel to become invalidated";

        QVERIFY(connect(mRequestedTube.data(),
                SIGNAL(invalidated(Tp::DBusProxy*,QString,QString)),
                mLoop,
                SLOT(quit())));
        tp_base_channel_close(TP_BASE_CHANNEL(mChanService));
        QCOMPARE(mLoop->exec(), 0);
    }

    mRequestedTube.reset();

    if (mChanService != 0) {
        g_object_unref(mChanService);
        mChanService = 0;
    }

    mLoop->processEvents();
}

void TestStreamTubeHandlers::cleanupTestCase()
{
    mAM.reset();
    mAcc.reset();

    QCOMPARE(mConn->disconnect(), true);
    delete mConn;

    cleanupTestCaseImpl();
}

QTEST_MAIN(TestStreamTubeHandlers)
#include "_gen/stream-tube-handlers.cpp.moc.hpp"
<|endoftext|>


<commit_before>//
//  main.cpp
//  SparseMatrix
//
//  Created by Gabriele Carrettoni on 02/02/15.
//  Copyright (c) 2015 Gabriele Carrettoni. All rights reserved.
//

#include <iostream>
#include <cstdio>
#include <exception>
#include <stdexcept>

/**
 SparseMatrix
 Implementation of a SparseMatrix
 @param T the type to store in the matrix.
 */
template <typename T>
class SparseMatrix {

public:
    /**
     Struct to hold the elements with their respective coordinates.
     @param j the row coordinate
     @param k the coloumn cooridnate
     @param elem the element stored
     */
    struct Element {
        const int j, k;
        T elem;

        Element(int r, int c, const T e): j(r), k(c), elem(e) {}
    };

    class const_iterator;

    class iterator {
        //
    public:
        typedef std::forward_iterator_tag iterator_category;
        typedef Element                   value_type;
        typedef ptrdiff_t                 difference_type;
        typedef value_type*               pointer;
        typedef value_type*&              reference;

        /**
         Copy constructor
         @param other reference to the iterator to copy.
         */
        iterator(const iterator &other) {
            data = other.data;
        }

        /**
         Assignment
         @param other reference to the iterator to copy.
         */
        iterator& operator=(const iterator &other) {
            data = other.data;
            return *this;
        }

        /**
         Dereference pointer
         */
        reference operator*() const {
            return *data;
        }

        /**
         Return pointer
         @returns pointer to the current element.
         */
        pointer operator->() const {
            return *data;
        }

        /**
         Post-increment operator;
         @returns iterator not incremented;
         */
        iterator operator++(int) {
            return iterator(data++);
        }

        /**
         Pre-increment operator;
         @returns iterator incremented;
         */
        iterator& operator++() {
            ++data;
            return *this;
        }

        /**
         Equality operator, check if the two iterators point to the same element
         @param other reference to the other iterator
         */
        bool operator==(const iterator &other) const {
            return data == other.data;
        }

        /**
         Inequality operator, check iif the two iterators
         don't point to the same element
         @param other reference to the other iterator
         */
        bool operator!=(const iterator &other) const {
            return data != other.data;
        }

        friend class const_iterator;

        /**
         Equality operator, check if the two iterators point to the same element.
         @param other reference to the other const_iterator
          */
        bool operator==(const const_iterator &other) const {
            return data == other.data;
        }

        /**
         Inequality operator, check if the two iterators
         don't point to the same element.
         @param other reference to the other const_iterator
         */
        bool operator!=(const const_iterator &other) const {
            return data != other.data;
        }

    private:
        Element** data;

        friend class SparseMatrix;

        explicit iterator(Element** data_): data(data_) {}
    };

    class const_iterator {
        //
    public:
        typedef std::forward_iterator_tag iterator_category;
        typedef const Element             value_type;
        typedef ptrdiff_t                 difference_type;
        typedef value_type*               pointer;
        typedef value_type&               reference;

        /**
         Copy constructor
         @param other reference to the iterator to copy.
         */
        const_iterator(const iterator &other) {
            data = other.data;
        }

        /**
         Assignment
         @param other reference to the iterator to copy.
         */
        const_iterator& operator=(const iterator &other) {
            data = other.data;
            return *this;
        }

        /**
         Dereference pointer
         */
        reference operator*() const {
            return **data;
        }

        /**
         Return pointer
         @returns pointer to the current element.
         */
        pointer operator->() const {
            return *data;
        }

        /**
         Post-increment operator;
         @returns iterator not incremented;
         */
        const_iterator operator++(int) {
            return iterator(data++);
        }

        /**
         Pre-increment operator;
         @returns iterator incremented;
         */
        const_iterator& operator++() {
            ++data;
            return *this;
        }

        /**
         Equality operator, check if the two iterators point to the same element
         @param other reference to the other iterator
         */
        bool operator==(const const_iterator &other) const {
            return data == other.data;
        }

        /**
         Inequality operator, check iif the two iterators
         don't point to the same element
         @param other reference to the other iterator
         */
        bool operator!=(const const_iterator &other) const {
            return data != other.data;
        }

        friend class const_iterator;

    private:
        Element** data;

        friend class SparseMatrix;

        const_iterator(Element** data_): data(data_) {}
    };

    /**
     Constructor
     @param r the number of rows
     @param c the number of coloumns
     @param d the default element to return when the user tries to retrieve an
     element not existent in the matrix.
     */
    explicit SparseMatrix(int r, int c, T d): rows(r), cols(c), def(d), size(0), m(NULL) {}

    /**
     Copy constructor
     @param sm the matrix to copy from
     */
    SparseMatrix(const SparseMatrix& sm) {
        rows = sm.rows;
        cols = sm.cols;

        def  = sm.def;
        size = sm.size;

        m = new Element*[size]();

        for (int i=0; i < size; i++) {
            m[i] = new Element(sm.m[i]->j, sm.m[i]->k, sm.m[i]->elem);
        }
    }

    /**
     Copy constructor from Matrix with different type trying to cast the type.
     @param sm the other matrix
     */
    template <typename Q>
    SparseMatrix(const SparseMatrix<Q>& sm) {
        rows = sm.get_rows();
        cols = sm.get_cols();

        def  = sm.get_def();
        size = sm.get_size();

        m = new Element*[size]();

        for (int i=0; i < size; i++) {
            m[i] = new Element(sm.get_m()[i]->j,
                               sm.get_m()[i]->k,
                               sm.get_m()[i]->elem);
        }
    }

    /**
     Destructor
     */
    ~SparseMatrix() {
        for (int i=0; i < size; i++)
            delete m[i];

        delete[] m;
        m = NULL;
    }

    iterator begin() {
        return iterator(m);
    }

    iterator end() {
        return iterator(m+size);
    }

    const_iterator begin() const {
        return iterator(m);
    }

    const_iterator end() const {
        return iterator(m+size);
    }

    /**
     Add an element of type T to the matrix.
     @param j the nth-row
     @param k the nth-col
     @param elem the element to add to the matrix
     */
    void add(int j, int k, const T elem) {
        //assert(j < rows && k < cols);

        Element** temp = new Element*[++size]();

        if (m) {
            for (int i=0; i < size; i++) {
                if (i == size-1) {
                    temp[i] = new Element(j, k, elem);
                    break;
                }

                if ((j < m[i]->j) || (j == m[i]->j && k < m[i]->k)) {
                    temp[i] = new Element(j, k, elem);

                    for (int x=i+1; x < size; x++) {
                        temp[x] = m[i++];
                    }

                    break;
                }

                if (j == m[i]->j && k == m[i]->k) {
                    m[i]->elem = elem;

                    delete[] temp;
                    temp = NULL;

                    --size;
                    break;
                }

                temp[i] = m[i];
            }

        }
        else
            temp[0] = new Element(j, k, elem);

        if (temp) m = temp;
    }

    /**
     Query operator, useful to retrieve elements aded to the matrix, returns
     the default element passed at class intialization if queried for an element
     not in the matrix.
     @param j the nth-row
     @param k the nth-col
     @returns the element
     */
    T operator()(int j, int k) {
        for (int i=0; i < size; i++) {
            if (m[i]->j == j && m[i]->k == k)
                return m[i]->elem;
        }

        return def;
    }

    /**
     Returns the default parameter passed at class instantiation
     @returns default value
     */
    const T get_def() const {
        return def;
    }

    const int get_rows() const {
        return rows;
    }

    const int get_cols() const {
        return cols;
    }

    const size_t get_size() const {
        return size;
    }

    Element** get_m() const  {
        return m;
    }

private:
    int rows;
    int cols;
    T def;

    Element** m;
    size_t size;
};

template <typename T, typename P>
int evaluate(SparseMatrix<T>& sm, P p) {
    int sum = 0;
    for (const typename SparseMatrix<T>::Element* e: sm) {
        if (p(e->elem)) sum++;
    }

    if (p(sm.get_def())) sum++;

    return sum;
}

bool t(int m) { return m > 1; }

int main(int argc, const char * argv[]) {
    SparseMatrix<float> m(10, 10, 0);
    m.add(0, 1, 1.2);
    m.add(9, 9, 0);
    m.add(3, 2, 9);
    m.add(3, 2, 5.3);

    SparseMatrix<int> m2(m);

    for (auto itr=m.begin(); itr != m.end(); itr++) {
        std::cout << itr->elem << std::endl;
    }

    std::cout << evaluate(m, t);

    return 0;
}
<commit_msg>doc get_rows()<commit_after>//
//  main.cpp
//  SparseMatrix
//
//  Created by Gabriele Carrettoni on 02/02/15.
//  Copyright (c) 2015 Gabriele Carrettoni. All rights reserved.
//

#include <iostream>
#include <cstdio>
#include <exception>
#include <stdexcept>

/**
 SparseMatrix
 Implementation of a SparseMatrix
 @param T the type to store in the matrix.
 */
template <typename T>
class SparseMatrix {

public:
    /**
     Struct to hold the elements with their respective coordinates.
     @param j the row coordinate
     @param k the coloumn cooridnate
     @param elem the element stored
     */
    struct Element {
        const int j, k;
        T elem;

        Element(int r, int c, const T e): j(r), k(c), elem(e) {}
    };

    class const_iterator;

    class iterator {
        //
    public:
        typedef std::forward_iterator_tag iterator_category;
        typedef Element                   value_type;
        typedef ptrdiff_t                 difference_type;
        typedef value_type*               pointer;
        typedef value_type*&              reference;

        /**
         Copy constructor
         @param other reference to the iterator to copy.
         */
        iterator(const iterator &other) {
            data = other.data;
        }

        /**
         Assignment
         @param other reference to the iterator to copy.
         */
        iterator& operator=(const iterator &other) {
            data = other.data;
            return *this;
        }

        /**
         Dereference pointer
         */
        reference operator*() const {
            return *data;
        }

        /**
         Return pointer
         @returns pointer to the current element.
         */
        pointer operator->() const {
            return *data;
        }

        /**
         Post-increment operator;
         @returns iterator not incremented;
         */
        iterator operator++(int) {
            return iterator(data++);
        }

        /**
         Pre-increment operator;
         @returns iterator incremented;
         */
        iterator& operator++() {
            ++data;
            return *this;
        }

        /**
         Equality operator, check if the two iterators point to the same element
         @param other reference to the other iterator
         */
        bool operator==(const iterator &other) const {
            return data == other.data;
        }

        /**
         Inequality operator, check iif the two iterators
         don't point to the same element
         @param other reference to the other iterator
         */
        bool operator!=(const iterator &other) const {
            return data != other.data;
        }

        friend class const_iterator;

        /**
         Equality operator, check if the two iterators point to the same element.
         @param other reference to the other const_iterator
          */
        bool operator==(const const_iterator &other) const {
            return data == other.data;
        }

        /**
         Inequality operator, check if the two iterators
         don't point to the same element.
         @param other reference to the other const_iterator
         */
        bool operator!=(const const_iterator &other) const {
            return data != other.data;
        }

    private:
        Element** data;

        friend class SparseMatrix;

        explicit iterator(Element** data_): data(data_) {}
    };

    class const_iterator {
        //
    public:
        typedef std::forward_iterator_tag iterator_category;
        typedef const Element             value_type;
        typedef ptrdiff_t                 difference_type;
        typedef value_type*               pointer;
        typedef value_type&               reference;

        /**
         Copy constructor
         @param other reference to the iterator to copy.
         */
        const_iterator(const iterator &other) {
            data = other.data;
        }

        /**
         Assignment
         @param other reference to the iterator to copy.
         */
        const_iterator& operator=(const iterator &other) {
            data = other.data;
            return *this;
        }

        /**
         Dereference pointer
         */
        reference operator*() const {
            return **data;
        }

        /**
         Return pointer
         @returns pointer to the current element.
         */
        pointer operator->() const {
            return *data;
        }

        /**
         Post-increment operator;
         @returns iterator not incremented;
         */
        const_iterator operator++(int) {
            return iterator(data++);
        }

        /**
         Pre-increment operator;
         @returns iterator incremented;
         */
        const_iterator& operator++() {
            ++data;
            return *this;
        }

        /**
         Equality operator, check if the two iterators point to the same element
         @param other reference to the other iterator
         */
        bool operator==(const const_iterator &other) const {
            return data == other.data;
        }

        /**
         Inequality operator, check iif the two iterators
         don't point to the same element
         @param other reference to the other iterator
         */
        bool operator!=(const const_iterator &other) const {
            return data != other.data;
        }

        friend class const_iterator;

    private:
        Element** data;

        friend class SparseMatrix;

        const_iterator(Element** data_): data(data_) {}
    };

    /**
     Constructor
     @param r the number of rows
     @param c the number of coloumns
     @param d the default element to return when the user tries to retrieve an
     element not existent in the matrix.
     */
    explicit SparseMatrix(int r, int c, T d): rows(r), cols(c), def(d), size(0), m(NULL) {}

    /**
     Copy constructor
     @param sm the matrix to copy from
     */
    SparseMatrix(const SparseMatrix& sm) {
        rows = sm.rows;
        cols = sm.cols;

        def  = sm.def;
        size = sm.size;

        m = new Element*[size]();

        for (int i=0; i < size; i++) {
            m[i] = new Element(sm.m[i]->j, sm.m[i]->k, sm.m[i]->elem);
        }
    }

    /**
     Copy constructor from Matrix with different type trying to cast the type.
     @param sm the other matrix
     */
    template <typename Q>
    SparseMatrix(const SparseMatrix<Q>& sm) {
        rows = sm.get_rows();
        cols = sm.get_cols();

        def  = sm.get_def();
        size = sm.get_size();

        m = new Element*[size]();

        for (int i=0; i < size; i++) {
            m[i] = new Element(sm.get_m()[i]->j,
                               sm.get_m()[i]->k,
                               sm.get_m()[i]->elem);
        }
    }

    /**
     Destructor
     */
    ~SparseMatrix() {
        for (int i=0; i < size; i++)
            delete m[i];

        delete[] m;
        m = NULL;
    }

    iterator begin() {
        return iterator(m);
    }

    iterator end() {
        return iterator(m+size);
    }

    const_iterator begin() const {
        return iterator(m);
    }

    const_iterator end() const {
        return iterator(m+size);
    }

    /**
     Add an element of type T to the matrix.
     @param j the nth-row
     @param k the nth-col
     @param elem the element to add to the matrix
     */
    void add(int j, int k, const T elem) {
        //assert(j < rows && k < cols);

        Element** temp = new Element*[++size]();

        if (m) {
            for (int i=0; i < size; i++) {
                if (i == size-1) {
                    temp[i] = new Element(j, k, elem);
                    break;
                }

                if ((j < m[i]->j) || (j == m[i]->j && k < m[i]->k)) {
                    temp[i] = new Element(j, k, elem);

                    for (int x=i+1; x < size; x++) {
                        temp[x] = m[i++];
                    }

                    break;
                }

                if (j == m[i]->j && k == m[i]->k) {
                    m[i]->elem = elem;

                    delete[] temp;
                    temp = NULL;

                    --size;
                    break;
                }

                temp[i] = m[i];
            }

        }
        else
            temp[0] = new Element(j, k, elem);

        if (temp) m = temp;
    }

    /**
     Query operator, useful to retrieve elements aded to the matrix, returns
     the default element passed at class intialization if queried for an element
     not in the matrix.
     @param j the nth-row
     @param k the nth-col
     @returns the element
     */
    T operator()(int j, int k) {
        for (int i=0; i < size; i++) {
            if (m[i]->j == j && m[i]->k == k)
                return m[i]->elem;
        }

        return def;
    }

    /**
     Returns the default parameter passed at class instantiation
     @returns default value
     */
    const T get_def() const {
        return def;
    }

    /**
     Returns the number of rows.
     @returns number of rows
     */
    const int get_rows() const {
        return rows;
    }

    const int get_cols() const {
        return cols;
    }

    const size_t get_size() const {
        return size;
    }

    Element** get_m() const  {
        return m;
    }

private:
    int rows;
    int cols;
    T def;

    Element** m;
    size_t size;
};

template <typename T, typename P>
int evaluate(SparseMatrix<T>& sm, P p) {
    int sum = 0;
    for (const typename SparseMatrix<T>::Element* e: sm) {
        if (p(e->elem)) sum++;
    }

    if (p(sm.get_def())) sum++;

    return sum;
}

bool t(int m) { return m > 1; }

int main(int argc, const char * argv[]) {
    SparseMatrix<float> m(10, 10, 0);
    m.add(0, 1, 1.2);
    m.add(9, 9, 0);
    m.add(3, 2, 9);
    m.add(3, 2, 5.3);

    SparseMatrix<int> m2(m);

    for (auto itr=m.begin(); itr != m.end(); itr++) {
        std::cout << itr->elem << std::endl;
    }

    std::cout << evaluate(m, t);

    return 0;
}
<|endoftext|>


<commit_before>/***********************************************************************************************************
 *                                                                                *
 * Helper class for TRD PID efficiency calculation Calculation of the hadron efficiency depenedent on      *
 * momentum and of the errors implemented in function CalculatePionEff. The pion efficiency is based on a  *
 * predefined electron efficiency. The default is 90%. To change the, one has to call the function         *
 * SetElectronEfficiency.                                                                                *
 * Other Helper functions decide based on 90% electron efficiency whether a certain track is accepted      *
 * as Electron Track. The reference data is stored in the TRD OCDB.                                        *
 *                                                                                *
 ***********************************************************************************************************/
#include "TObject.h"
#include "TObjArray.h"
#include "TMath.h"
#include "TF1.h"
#include "TH1F.h"
#include "TGraph.h"
#include "TGraphErrors.h"
#include "TPDGCode.h"

#include "AliLog.h"
#include "Cal/AliTRDCalPID.h"
#include "AliCDBManager.h"
#include "AliCDBEntry.h"
#include "AliESDtrack.h"
#include "AliPID.h"
#include "AliTRDpidUtil.h"

ClassImp(AliTRDpidUtil)

Float_t AliTRDpidUtil::fgEleEffi = 0.9;

//________________________________________________________________________
AliTRDpidUtil::AliTRDpidUtil()
  : TObject()
  ,fCalcEleEffi(0.)
  ,fPionEffi(-1.)
  ,fError(-1.)
  ,fThreshold(-1.)
{
  //
  // Default constructor
  //
}

//________________________________________________________________________
Bool_t  AliTRDpidUtil::CalculatePionEffi(TH1* histo1, TH1* histo2)
// Double_t  AliTRDpidUtil::GetError()
{
  //
  // Calculates the pion efficiency
  //

  histo1 -> SetLineColor(kRed);
  histo2 -> SetLineColor(kBlue);
  if(!histo1 -> GetEntries() || !histo2 -> GetEntries()){
    AliWarning("Histo with no entries !");
    return kFALSE;
  }
  histo1 -> Scale(1./histo1->GetEntries());
  histo2 -> Scale(1./histo2->GetEntries());

  Int_t abinE, bbinE, cbinE = -1;
  Double_t aBinSumE, bBinSumE;                  // content of a single bin
  Bool_t bFirst = 1;                            // checks if threshold is crossed for the first time
  Double_t sumElecE[kBins+2], sumPionsE[kBins+2];  // array of the integrated sum in each bin
  memset(sumElecE, 0, (kBins+2)*sizeof(Double_t));
  memset(sumPionsE, 0, (kBins+2)*sizeof(Double_t));

  // calculate electron efficiency of each bin
  for (abinE = (histo1 -> GetNbinsX()); abinE >= 0; abinE--){
   aBinSumE = 0;
    aBinSumE = histo1 -> GetBinContent(abinE);

    sumElecE[abinE] = sumElecE[abinE+1] + aBinSumE;

    if((sumElecE[abinE] >= fgEleEffi) && (bFirst == 1)){
      bFirst = 0;
      cbinE = abinE;
      fCalcEleEffi = (sumElecE[cbinE]);
    }
  }

  fThreshold = histo1 -> GetBinCenter(cbinE);

  // calculate pion efficiency of each bin
  for (bbinE = (histo2 -> GetNbinsX()); bbinE >= abinE; bbinE--){
    bBinSumE = 0;
    bBinSumE = histo2 -> GetBinContent(bbinE);

    sumPionsE[bbinE] = sumPionsE[bbinE+1] + bBinSumE;
    if(bbinE == cbinE){
      fPionEffi = (sumPionsE[cbinE]);
    }
  }

  // pion efficiency vs electron efficiency
  TGraph gEffis(kBins, sumElecE, sumPionsE);

  // use fit function to get derivate of the TGraph for error calculation
  TF1 f1("f1","[0]*x*x+[1]*x+[2]", fgEleEffi-.05, fgEleEffi+.05);
  gEffis.Fit(&f1, "Q", "", fgEleEffi-.05, fgEleEffi+.05);

  // return the error of the pion efficiency
  if(((1.-fPionEffi) < 0) || ((1.-fCalcEleEffi) < 0)){
    AliWarning(" EleEffi or PioEffi > 1. Error can not be calculated. Please increase statistics or check your simulation!");
    return kFALSE;
  }
  fError = sqrt(((1/histo2 -> GetEntries())*fPionEffi*(1-fPionEffi))+((f1.Derivative(fgEleEffi))*(f1.Derivative(fgEleEffi))*(1/histo1 -> GetEntries())*fCalcEleEffi*(1-fCalcEleEffi)));

//   AliInfo(Form("Pion Effi at [%f] : [%f +/- %f], Threshold[%f]", fCalcEleEffi, fPionEffi, fError, fThreshold));
//   AliInfo(Form("Derivative at %4.2f : %f\n", fgEleEffi, f1.Derivative(fgEleEffi)));
  return kTRUE;
}

//__________________________________________________________________________
Int_t AliTRDpidUtil::GetMomentumBin(Double_t p)
{
  //
  // returns the momentum bin for a given momentum
  //

  Int_t pBin1 = -1;                                    // check bin1
  Int_t pBin2 = -1;                                    // check bin2

  if(p < 0) return -1;                                 // return -1 if momentum < 0
  if(p < AliTRDCalPID::GetMomentum(0)) return 0;                                      // smallest momentum bin
  if(p >= AliTRDCalPID::GetMomentum(AliTRDCalPID::kNMom-1)) return AliTRDCalPID::kNMom-1; // largest momentum bin

  // calculate momentum bin for non extremal momenta
  for(Int_t iMomBin = 1; iMomBin < AliTRDCalPID::kNMom; iMomBin++){
    if(p < AliTRDCalPID::GetMomentum(iMomBin)){
      pBin1 = iMomBin - 1;
      pBin2 = iMomBin;
    }
    else
      continue;

    if(p - AliTRDCalPID::GetMomentum(pBin1) >= AliTRDCalPID::GetMomentum(pBin2) - p){
       return pBin2;
    }
    else{
      return pBin1;
    }
  }

  return -1;
}

//__________________________________________________________________________
Bool_t AliTRDpidUtil::IsElectron(const AliESDtrack *track, ETRDPIDMethod method){
  //
  // Do PID decision for the TRD based on 90% Electron efficiency threshold
  //
  // Author: Markus Fasel (M.Fasel@gsi.de)
  //
  if(method == kESD) method = kNN;
  TString histname[2] = {"fHistThreshLQ", "fHistThreshNN"};
  AliCDBManager *cdb = AliCDBManager::Instance();
  AliCDBEntry *cdbThresholds = cdb->Get("TRD/Calib/PIDThresholds");
  TObjArray *histos = dynamic_cast<TObjArray *>(cdbThresholds->GetObject());
  TH1 * thresholdHist = dynamic_cast<TH1F *>(histos->FindObject(histname[method].Data()));
  Double_t threshold = thresholdHist->GetBinContent(GetMomentumBin(track->P()) + 1);

  // Do Decision
  Double_t pid_probs[5];
  track->GetTRDpid(pid_probs);
  if(pid_probs[AliPID::kElectron] >= threshold) return kTRUE;
  return kFALSE;
}

//__________________________________________________________________________
Double_t AliTRDpidUtil::GetSystematicError(const AliESDtrack *track, ETRDPIDMethod method){
  //
  // Returns the pion efficiency at 90% electron efficiency from the OCDB
  //
  // Author: Markus Fasel (M.Fasel@gsi.de)
  //
  if(method == kESD) method = kNN;
  TString histname[2] = {"fHistPionEffLQ", "fHistPionEffNN"};
  AliCDBManager *cdb = AliCDBManager::Instance();
  AliCDBEntry *cdbThresholds = cdb->Get("TRD/Calib/PIDThresholds");
  TObjArray *histos = dynamic_cast<TObjArray *>(cdbThresholds->GetObject());
  TH1 * thresholdHist = dynamic_cast<TH1F *>(histos->FindObject(histname[method].Data()));
  return thresholdHist->GetBinContent(GetMomentumBin(track->P()) + 1);
}

//________________________________________________________________________
Int_t AliTRDpidUtil::Pdg2Pid(Int_t pdg){
  //
  // Private Helper function to get the paticle species (ALICE notation)
  // from the Pdg code
  //
  Int_t species;
  switch(TMath::Abs(pdg)){
  case kElectron:
    species = AliPID::kElectron;
    break;
  case kMuonMinus:
    species = AliPID::kMuon;
    break;
  case kPiPlus:
    species = AliPID::kPion;
    break;
  case kKPlus:
    species = AliPID::kKaon;
    break;
  case kProton:
    species = AliPID::kProton;
    break;
  default:
    species = -1;
  }
  return species;
}

<commit_msg>fix crash in PWG1 train (Andrei)<commit_after>/***********************************************************************************************************
 *                                                                                *
 * Helper class for TRD PID efficiency calculation Calculation of the hadron efficiency depenedent on      *
 * momentum and of the errors implemented in function CalculatePionEff. The pion efficiency is based on a  *
 * predefined electron efficiency. The default is 90%. To change the, one has to call the function         *
 * SetElectronEfficiency.                                                                                *
 * Other Helper functions decide based on 90% electron efficiency whether a certain track is accepted      *
 * as Electron Track. The reference data is stored in the TRD OCDB.                                        *
 *                                                                                *
 ***********************************************************************************************************/
#include "TObject.h"
#include "TObjArray.h"
#include "TMath.h"
#include "TF1.h"
#include "TH1F.h"
#include "TGraph.h"
#include "TGraphErrors.h"
#include "TPDGCode.h"

#include "AliLog.h"
#include "Cal/AliTRDCalPID.h"
#include "AliCDBManager.h"
#include "AliCDBEntry.h"
#include "AliESDtrack.h"
#include "AliPID.h"
#include "AliTRDpidUtil.h"

ClassImp(AliTRDpidUtil)

Float_t AliTRDpidUtil::fgEleEffi = 0.9;

//________________________________________________________________________
AliTRDpidUtil::AliTRDpidUtil()
  : TObject()
  ,fCalcEleEffi(0.)
  ,fPionEffi(-1.)
  ,fError(-1.)
  ,fThreshold(-1.)
{
  //
  // Default constructor
  //
}

//________________________________________________________________________
Bool_t  AliTRDpidUtil::CalculatePionEffi(TH1* histo1, TH1* histo2)
// Double_t  AliTRDpidUtil::GetError()
{
  //
  // Calculates the pion efficiency
  //

  histo1 -> SetLineColor(kRed);
  histo2 -> SetLineColor(kBlue);
  if(!histo1 -> GetEntries() || !histo2 -> GetEntries()){
    AliWarning("Histo with no entries !");
    return kFALSE;
  }
  histo1 -> Scale(1./histo1->GetEntries());
  histo2 -> Scale(1./histo2->GetEntries());

  Int_t abinE, bbinE, cbinE = -1;
  Double_t aBinSumE, bBinSumE;                  // content of a single bin
  Bool_t bFirst = 1;                            // checks if threshold is crossed for the first time
  Double_t sumElecE[kBins+2], sumPionsE[kBins+2];  // array of the integrated sum in each bin
  memset(sumElecE, 0, (kBins+2)*sizeof(Double_t));
  memset(sumPionsE, 0, (kBins+2)*sizeof(Double_t));

  // calculate electron efficiency of each bin
  for (abinE = (histo1 -> GetNbinsX()); abinE >= 0; abinE--){
   aBinSumE = 0;
    aBinSumE = histo1 -> GetBinContent(abinE);

    sumElecE[abinE] = sumElecE[abinE+1] + aBinSumE;

    if((sumElecE[abinE] >= fgEleEffi) && (bFirst == 1)){
      bFirst = 0;
      cbinE = abinE;
      fCalcEleEffi = (sumElecE[cbinE]);
    }
  }

  fThreshold = histo1 -> GetBinCenter(cbinE);

  // calculate pion efficiency of each bin
  for (bbinE = (histo2 -> GetNbinsX()); bbinE > abinE; bbinE--){
    bBinSumE = 0;
    bBinSumE = histo2 -> GetBinContent(bbinE);

    sumPionsE[bbinE] = sumPionsE[bbinE+1] + bBinSumE;
    if(bbinE == cbinE){
      fPionEffi = (sumPionsE[cbinE]);
    }
  }

  // pion efficiency vs electron efficiency
  TGraph gEffis(kBins, sumElecE, sumPionsE);

  // use fit function to get derivate of the TGraph for error calculation
  TF1 f1("f1","[0]*x*x+[1]*x+[2]", fgEleEffi-.05, fgEleEffi+.05);
  gEffis.Fit(&f1, "Q", "", fgEleEffi-.05, fgEleEffi+.05);

  // return the error of the pion efficiency
  if(((1.-fPionEffi) < 0) || ((1.-fCalcEleEffi) < 0)){
    AliWarning(" EleEffi or PioEffi > 1. Error can not be calculated. Please increase statistics or check your simulation!");
    return kFALSE;
  }
  fError = sqrt(((1/histo2 -> GetEntries())*fPionEffi*(1-fPionEffi))+((f1.Derivative(fgEleEffi))*(f1.Derivative(fgEleEffi))*(1/histo1 -> GetEntries())*fCalcEleEffi*(1-fCalcEleEffi)));

//   AliInfo(Form("Pion Effi at [%f] : [%f +/- %f], Threshold[%f]", fCalcEleEffi, fPionEffi, fError, fThreshold));
//   AliInfo(Form("Derivative at %4.2f : %f\n", fgEleEffi, f1.Derivative(fgEleEffi)));
  return kTRUE;
}

//__________________________________________________________________________
Int_t AliTRDpidUtil::GetMomentumBin(Double_t p)
{
  //
  // returns the momentum bin for a given momentum
  //

  Int_t pBin1 = -1;                                    // check bin1
  Int_t pBin2 = -1;                                    // check bin2

  if(p < 0) return -1;                                 // return -1 if momentum < 0
  if(p < AliTRDCalPID::GetMomentum(0)) return 0;                                      // smallest momentum bin
  if(p >= AliTRDCalPID::GetMomentum(AliTRDCalPID::kNMom-1)) return AliTRDCalPID::kNMom-1; // largest momentum bin

  // calculate momentum bin for non extremal momenta
  for(Int_t iMomBin = 1; iMomBin < AliTRDCalPID::kNMom; iMomBin++){
    if(p < AliTRDCalPID::GetMomentum(iMomBin)){
      pBin1 = iMomBin - 1;
      pBin2 = iMomBin;
    }
    else
      continue;

    if(p - AliTRDCalPID::GetMomentum(pBin1) >= AliTRDCalPID::GetMomentum(pBin2) - p){
       return pBin2;
    }
    else{
      return pBin1;
    }
  }

  return -1;
}

//__________________________________________________________________________
Bool_t AliTRDpidUtil::IsElectron(const AliESDtrack *track, ETRDPIDMethod method){
  //
  // Do PID decision for the TRD based on 90% Electron efficiency threshold
  //
  // Author: Markus Fasel (M.Fasel@gsi.de)
  //
  if(method == kESD) method = kNN;
  TString histname[2] = {"fHistThreshLQ", "fHistThreshNN"};
  AliCDBManager *cdb = AliCDBManager::Instance();
  AliCDBEntry *cdbThresholds = cdb->Get("TRD/Calib/PIDThresholds");
  TObjArray *histos = dynamic_cast<TObjArray *>(cdbThresholds->GetObject());
  TH1 * thresholdHist = dynamic_cast<TH1F *>(histos->FindObject(histname[method].Data()));
  Double_t threshold = thresholdHist->GetBinContent(GetMomentumBin(track->P()) + 1);

  // Do Decision
  Double_t pid_probs[5];
  track->GetTRDpid(pid_probs);
  if(pid_probs[AliPID::kElectron] >= threshold) return kTRUE;
  return kFALSE;
}

//__________________________________________________________________________
Double_t AliTRDpidUtil::GetSystematicError(const AliESDtrack *track, ETRDPIDMethod method){
  //
  // Returns the pion efficiency at 90% electron efficiency from the OCDB
  //
  // Author: Markus Fasel (M.Fasel@gsi.de)
  //
  if(method == kESD) method = kNN;
  TString histname[2] = {"fHistPionEffLQ", "fHistPionEffNN"};
  AliCDBManager *cdb = AliCDBManager::Instance();
  AliCDBEntry *cdbThresholds = cdb->Get("TRD/Calib/PIDThresholds");
  TObjArray *histos = dynamic_cast<TObjArray *>(cdbThresholds->GetObject());
  TH1 * thresholdHist = dynamic_cast<TH1F *>(histos->FindObject(histname[method].Data()));
  return thresholdHist->GetBinContent(GetMomentumBin(track->P()) + 1);
}

//________________________________________________________________________
Int_t AliTRDpidUtil::Pdg2Pid(Int_t pdg){
  //
  // Private Helper function to get the paticle species (ALICE notation)
  // from the Pdg code
  //
  Int_t species;
  switch(TMath::Abs(pdg)){
  case kElectron:
    species = AliPID::kElectron;
    break;
  case kMuonMinus:
    species = AliPID::kMuon;
    break;
  case kPiPlus:
    species = AliPID::kPion;
    break;
  case kKPlus:
    species = AliPID::kKaon;
    break;
  case kProton:
    species = AliPID::kProton;
    break;
  default:
    species = -1;
  }
  return species;
}

<|endoftext|>