<commit_before>// The "Square Detector" program.
// It loads several images sequentially and tries to find squares in
// each image

#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"

#include <iostream>
#include <math.h>
#include <string.h>

using namespace cv;

int thresh = 50, N = 11;
const char* wndname = "Square Detection Demo";

// helper function:
// finds a cosine of angle between vectors
// from pt0->pt1 and from pt0->pt2
static double angle( Point pt1, Point pt2, Point pt0 )
{
    double dx1 = pt1.x - pt0.x;
    double dy1 = pt1.y - pt0.y;
    double dx2 = pt2.x - pt0.x;
    double dy2 = pt2.y - pt0.y;
    return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}

// returns sequence of squares detected on the image.
// the sequence is stored in the specified memory storage
static void findSquares( const Mat& image, vector<vector<Point> >& squares )
{
    squares.clear();

    Mat pyr, timg, gray0(image.size(), CV_8U), gray;

    // down-scale and upscale the image to filter out the noise
    pyrDown(image, pyr, Size(image.cols/2, image.rows/2));
    pyrUp(pyr, timg, image.size());
    vector<vector<Point> > contours;

    // find squares in every color plane of the image
    for( int c = 0; c < 3; c++ )
    {
        int ch[] = {c, 0};
        mixChannels(&timg, 1, &gray0, 1, ch, 1);

        // try several threshold levels
        for( int l = 0; l < N; l++ )
        {
            // hack: use Canny instead of zero threshold level.
            // Canny helps to catch squares with gradient shading
            if( l == 0 )
            {
                // apply Canny. Take the upper threshold from slider
                // and set the lower to 0 (which forces edges merging)
                Canny(gray0, gray, 0, thresh, 5);
                // dilate canny output to remove potential
                // holes between edge segments
                dilate(gray, gray, Mat(), Point(-1,-1));
            }
            else
            {
                // apply threshold if l!=0:
                //     tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0
                gray = gray0 >= (l+1)*255/N;
            }

            // find contours and store them all as a list
            findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);

            vector<Point> approx;

            // test each contour
            for( size_t i = 0; i < contours.size(); i++ )
            {
                // approximate contour with accuracy proportional
                // to the contour perimeter
                approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);

                // square contours should have 4 vertices after approximation
                // relatively large area (to filter out noisy contours)
                // and be convex.
                // Note: absolute value of an area is used because
                // area may be positive or negative - in accordance with the
                // contour orientation
                if( approx.size() == 4 &&
                    fabs(contourArea(Mat(approx))) > 1000 &&
                    isContourConvex(Mat(approx)) )
                {
                    double maxCosine = 0;

                    for( int j = 2; j < 5; j++ )
                    {
                        // find the maximum cosine of the angle between joint edges
                        double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));
                        maxCosine = MAX(maxCosine, cosine);
                    }

                    // if cosines of all angles are small
                    // (all angles are ~90 degree) then write quandrange
                    // vertices to resultant sequence
                    if( maxCosine < 0.3 )
                        squares.push_back(approx);
                }
            }
        }
    }
}

// the function draws all the squares in the image
static void drawSquares( Mat& image, const vector<vector<Point> >& squares )
{
    for( size_t i = 0; i < squares.size(); i++ )
    {
        const Point* p = &squares[i][0];
        int n = (int)squares[i].size();
        polylines(image, &p, &n, 1, true, Scalar(0,255,0), 3, CV_AA);
    }

    imshow(wndname, image);
}

int main(int /*argc*/, char** /*argv*/) {
    // Instantiate VideoCapture object. See here for details:
    // http://opencv.willowgarage.com/documentation/cpp/reading_and_writing_images_and_video.html
    VideoCapture cap(1);

    // Configure video. Our camera NEEDS the frame width to be set to 720
    // pixels.
    cap.set(CV_CAP_PROP_FRAME_WIDTH, 720);
    cap.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
    //cap.set(CV_CAP_PROP_FPS, 20);

    // Instantiate a Mat in which to store each video frame.
    Mat origFrame;
    Mat resizedFrame;

    namedWindow(wndname, 1);
    cvNamedWindow("control panel");
    cvCreateTrackbar("threshold", "control panel", &thresh, 300, NULL);
    vector<vector<Point> > squares;

    while (true) {
        // Capture image.
        cap >> origFrame;

        // Resize image to increase processing rate. See here for details:
        // http://opencv.willowgarage.com/documentation/cpp/geometric_image_transformations.html
        resize(origFrame, resizedFrame, Size(origFrame.cols/2, origFrame.rows/2), 0, 0, INTER_LINEAR);

        // Find and draw squares.
        findSquares(resizedFrame, squares);
        drawSquares(resizedFrame, squares);

        // Show the image, with the squares overlaid.
        imshow(wndname, resizedFrame);

        // Wait 5 milliseconds.
        waitKey(5);
    }

    return 0;
}
<commit_msg>Use pyrDown instead of resize.<commit_after>// The "Square Detector" program.
// It loads several images sequentially and tries to find squares in
// each image

#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"

#include <iostream>
#include <math.h>
#include <string.h>

using namespace cv;

int thresh = 50, N = 11;
const char* wndname = "Square Detection Demo";

// helper function:
// finds a cosine of angle between vectors
// from pt0->pt1 and from pt0->pt2
static double angle( Point pt1, Point pt2, Point pt0 )
{
    double dx1 = pt1.x - pt0.x;
    double dy1 = pt1.y - pt0.y;
    double dx2 = pt2.x - pt0.x;
    double dy2 = pt2.y - pt0.y;
    return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}

// returns sequence of squares detected on the image.
// the sequence is stored in the specified memory storage
static void findSquares( const Mat& image, vector<vector<Point> >& squares )
{
    squares.clear();

    Mat pyr, timg, gray0(image.size(), CV_8U), gray;

    // down-scale and upscale the image to filter out the noise
    pyrDown(image, pyr, Size(image.cols/2, image.rows/2));
    pyrUp(pyr, timg, image.size());
    vector<vector<Point> > contours;

    // find squares in every color plane of the image
    for( int c = 0; c < 3; c++ )
    {
        int ch[] = {c, 0};
        mixChannels(&timg, 1, &gray0, 1, ch, 1);

        // try several threshold levels
        for( int l = 0; l < N; l++ )
        {
            // hack: use Canny instead of zero threshold level.
            // Canny helps to catch squares with gradient shading
            if( l == 0 )
            {
                // apply Canny. Take the upper threshold from slider
                // and set the lower to 0 (which forces edges merging)
                Canny(gray0, gray, 0, thresh, 5);
                // dilate canny output to remove potential
                // holes between edge segments
                dilate(gray, gray, Mat(), Point(-1,-1));
            }
            else
            {
                // apply threshold if l!=0:
                //     tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0
                gray = gray0 >= (l+1)*255/N;
            }

            // find contours and store them all as a list
            findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);

            vector<Point> approx;

            // test each contour
            for( size_t i = 0; i < contours.size(); i++ )
            {
                // approximate contour with accuracy proportional
                // to the contour perimeter
                approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);

                // square contours should have 4 vertices after approximation
                // relatively large area (to filter out noisy contours)
                // and be convex.
                // Note: absolute value of an area is used because
                // area may be positive or negative - in accordance with the
                // contour orientation
                if( approx.size() == 4 &&
                    fabs(contourArea(Mat(approx))) > 1000 &&
                    isContourConvex(Mat(approx)) )
                {
                    double maxCosine = 0;

                    for( int j = 2; j < 5; j++ )
                    {
                        // find the maximum cosine of the angle between joint edges
                        double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));
                        maxCosine = MAX(maxCosine, cosine);
                    }

                    // if cosines of all angles are small
                    // (all angles are ~90 degree) then write quandrange
                    // vertices to resultant sequence
                    if( maxCosine < 0.3 )
                        squares.push_back(approx);
                }
            }
        }
    }
}

// the function draws all the squares in the image
static void drawSquares( Mat& image, const vector<vector<Point> >& squares )
{
    for( size_t i = 0; i < squares.size(); i++ )
    {
        const Point* p = &squares[i][0];
        int n = (int)squares[i].size();
        polylines(image, &p, &n, 1, true, Scalar(0,255,0), 3, CV_AA);
    }

    imshow(wndname, image);
}

int main(int /*argc*/, char** /*argv*/) {
    // Instantiate VideoCapture object. See here for details:
    // http://opencv.willowgarage.com/documentation/cpp/reading_and_writing_images_and_video.html
    VideoCapture cap(1);

    // Configure video. Our camera NEEDS the frame width to be set to 720
    // pixels.
    cap.set(CV_CAP_PROP_FRAME_WIDTH, 720);
    cap.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
    //cap.set(CV_CAP_PROP_FPS, 20);

    // Instantiate a Mat in which to store each video frame.
    Mat origFrame;
    Mat resizedFrame;

    namedWindow(wndname, 1);
    cvNamedWindow("control panel");
    cvCreateTrackbar("threshold", "control panel", &thresh, 300, NULL);
    vector<vector<Point> > squares;

    while (true) {
        // Capture image.
        cap >> origFrame;

        // Resize the image to increase processing rate. See here for details:
        // http://opencv.willowgarage.com/documentation/cpp/image_filtering.html
        pyrDown(origFrame, resizedFrame, Size(origFrame.cols/2, origFrame.rows/2));

        // Find and draw squares.
        findSquares(resizedFrame, squares);
        drawSquares(resizedFrame, squares);

        // Show the image, with the squares overlaid.
        imshow(wndname, resizedFrame);

        // Wait 5 milliseconds.
        waitKey(5);
    }

    return 0;
}
<|endoftext|>


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

/*
 * Blocking EEPROM Read and Writes.
 * This program shows usage of FastArduino EEPROM API.
 * It interfaces with user through the UART console and allows:
 * - writing values to EEPROM
 * - reading values to EEPROM
 *
 * Wiring: TODO
 * - on ATmega328P based boards (including Arduino UNO):
 * - on Arduino MEGA:
 * - on ATtinyX4 based boards:
 *   - D1: TX output connected to Serial-USB allowing traces display on a PC terminal
 */

#include <fastarduino/time.h>
#include <fastarduino/i2c.h>

#if defined(ARDUINO_UNO)
#define HARDWARE_UART 1
#include <fastarduino/uart.h>
static constexpr const board::USART UART = board::USART::USART0;
static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 64;
// Define vectors we need in the example
REGISTER_UATX_ISR(0)
#else
#error "Current target is not yet supported!"
#endif

// UART for traces
static char output_buffer[OUTPUT_BUFFER_SIZE];
static serial::hard::UATX<UART> uart{output_buffer};
static streams::FormattedOutput<streams::OutputBuffer> out = uart.fout();

// DS1307 specific
const uint8_t DEVICE_ADDRESS = 0x68 << 1;
union BCD
{
	struct
	{
		uint8_t units	:4;
		uint8_t tens	:4;
	};
	uint8_t two_digits;
};

//TODO check if packed attribute is really necessary
struct RealTime
{
	BCD seconds;
	BCD minutes;
	BCD hours;
	uint8_t weekday;
	BCD day;
	BCD month;
	BCD	year;
} __attribute__ ((packed));

const uint32_t I2C_FREQUENCY = 100000;

// NOTE we use prescaler = 1 everywhere
constexpr uint8_t calculate_TWBR(uint32_t frequency)
{
	return (F_CPU / frequency - 16UL) / 2;
}

// TODO traits for: SDA, SCL pins
int main() __attribute__((OS_main));
int main()
{
	sei();

	uart.register_handler();
	uart.begin(115200);
	out.width(0);
	out.base(streams::FormatBase::Base::hex);
	out << "Start\n" << streams::flush;

	// Start TWI interface
	//====================
	i2c::I2CManager manager;
	manager.begin();
	out << "I2C interface started\n" << streams::flush;
	out << "status #1 " << manager.error() << '\n' << streams::flush;
	time::delay_ms(1000);

	i2c::I2CDevice rtc{manager};

	RealTime init_time;
	init_time.day.two_digits = 0x11;
	init_time.month.two_digits = 0x06;
	init_time.year.two_digits = 0x17;
	init_time.weekday = 1;
	init_time.hours.two_digits = 0x12;
	init_time.minutes.two_digits = 0;
	init_time.seconds.two_digits = 0;

	// Initialize clock date
	//=======================
	rtc.write(DEVICE_ADDRESS, uint8_t(0), i2c::BusConditions::START_NO_STOP);
	rtc.write(DEVICE_ADDRESS, init_time, i2c::BusConditions::NO_START_STOP);
	out << "status #2 " << manager.error() << '\n' << streams::flush;

	time::delay_ms(2000);

	// Read clock
	//============
	RealTime time;
	rtc.write(DEVICE_ADDRESS, uint8_t(0), i2c::BusConditions::START_NO_STOP);
	out << "status #3 " << manager.error() << '\n' << streams::flush;
	rtc.read(DEVICE_ADDRESS, time, i2c::BusConditions::REPEAT_START_STOP);
	out << "status #4 " << manager.error() << '\n' << streams::flush;

	out	<< "RTC: "
		<< time.day.tens << time.day.units << '.'
		<< time.month.tens << time.month.units << '.'
		<< time.year.tens << time.year.units << ' '
		<< time.hours.tens << time.hours.units << ':'
		<< time.minutes.tens << time.minutes.units << ':'
		<< time.seconds.tens << time.seconds.units << '\n'
		<< streams::flush;

	// Stop TWI interface
	//===================
	manager.end();
	out << "status #5 " << manager.error() << '\n' << streams::flush;
	out << "End\n" << streams::flush;
}
<commit_msg>Cleanup I2C example (DS1307 RTC).<commit_after>//   Copyright 2016-2017 Jean-Francois Poilpret
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

/*
 * Blocking EEPROM Read and Writes.
 * This program shows usage of FastArduino EEPROM API.
 * It interfaces with user through the UART console and allows:
 * - writing values to EEPROM
 * - reading values to EEPROM
 *
 * Wiring: TODO
 * - on ATmega328P based boards (including Arduino UNO):
 * - on Arduino MEGA:
 * - on ATtinyX4 based boards:
 *   - D1: TX output connected to Serial-USB allowing traces display on a PC terminal
 */

#include <fastarduino/time.h>
#include <fastarduino/i2c.h>

#if defined(ARDUINO_UNO)
#define HARDWARE_UART 1
#include <fastarduino/uart.h>
static constexpr const board::USART UART = board::USART::USART0;
static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 64;
// Define vectors we need in the example
REGISTER_UATX_ISR(0)
#else
#error "Current target is not yet supported!"
#endif

// UART for traces
static char output_buffer[OUTPUT_BUFFER_SIZE];
static serial::hard::UATX<UART> uart{output_buffer};
static streams::FormattedOutput<streams::OutputBuffer> out = uart.fout();

// DS1307 specific
const uint8_t DEVICE_ADDRESS = 0x68 << 1;
union BCD
{
	struct
	{
		uint8_t units	:4;
		uint8_t tens	:4;
	};
	uint8_t two_digits;
};

struct RealTime
{
	BCD seconds;
	BCD minutes;
	BCD hours;
	uint8_t weekday;
	BCD day;
	BCD month;
	BCD	year;
};

const uint32_t I2C_FREQUENCY = 100000;

int main() __attribute__((OS_main));
int main()
{
	board::init();
	sei();

	uart.register_handler();
	uart.begin(115200);
	out.width(0);
	out.base(streams::FormatBase::Base::hex);
	out << "Start\n" << streams::flush;

	// Start TWI interface
	//====================
	i2c::I2CManager manager;
	manager.begin();
	out << "I2C interface started\n" << streams::flush;
	out << "status #1 " << manager.error() << '\n' << streams::flush;
	time::delay_ms(1000);

	i2c::I2CDevice rtc{manager};

	RealTime init_time;
	init_time.day.two_digits = 0x11;
	init_time.month.two_digits = 0x06;
	init_time.year.two_digits = 0x17;
	init_time.weekday = 1;
	init_time.hours.two_digits = 0x12;
	init_time.minutes.two_digits = 0;
	init_time.seconds.two_digits = 0;

	// Initialize clock date
	//=======================
	rtc.write(DEVICE_ADDRESS, uint8_t(0), i2c::BusConditions::START_NO_STOP);
	rtc.write(DEVICE_ADDRESS, init_time, i2c::BusConditions::NO_START_STOP);
	out << "status #2 " << manager.error() << '\n' << streams::flush;

	time::delay_ms(2000);

	// Read clock
	//============
	RealTime time;
	rtc.write(DEVICE_ADDRESS, uint8_t(0), i2c::BusConditions::START_NO_STOP);
	out << "status #3 " << manager.error() << '\n' << streams::flush;
	rtc.read(DEVICE_ADDRESS, time, i2c::BusConditions::REPEAT_START_STOP);
	out << "status #4 " << manager.error() << '\n' << streams::flush;

	out	<< "RTC: "
		<< time.day.tens << time.day.units << '.'
		<< time.month.tens << time.month.units << '.'
		<< time.year.tens << time.year.units << ' '
		<< time.hours.tens << time.hours.units << ':'
		<< time.minutes.tens << time.minutes.units << ':'
		<< time.seconds.tens << time.seconds.units << '\n'
		<< streams::flush;

	// Stop TWI interface
	//===================
	manager.end();
	out << "status #5 " << manager.error() << '\n' << streams::flush;
	out << "End\n" << streams::flush;
}
<|endoftext|>


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

/*
 * Check DS1307 I2C device (real-time clock) and display output to the UART console.
 * This program uses FastArduino DS1307 support API.
 *
 * Wiring:
 * NB: you should add pullup resistors (10K-22K typically) on both SDA and SCL lines.
 * WARNING: wiring is very sensitive for I2C connections! When using breadboard, ensure
 * wires connections are tight and stable.
 * - on ATmega328P based boards (including Arduino UNO):
 *   - A4 (PC4, SDA): connected to DS1307 SDA pin
 *   - A5 (PC5, SCL): connected to DS1307 SCL pin
 *   - direct USB access
 * - on Arduino LEONARDO:
 *   - D2 (PD1, SDA): connected to DS1307 SDA pin
 *   - D3 (PD0, SCL): connected to DS1307 SDA pin
 *   - direct USB access
 * - on Arduino MEGA:
 *   - D20 (PD1, SDA): connected to DS1307 SDA pin
 *   - D21 (PD0, SCL): connected to DS1307 SDA pin
 *   - direct USB access
 * - on ATtinyX4 based boards:
 *   - D6 (PA6, SDA): connected to DS1307 SDA pin
 *   - D4 (PA4, SCL): connected to DS1307 SDA pin
 *   - D8 (PB0, TX): connected to SerialUSB converter
 * - on ATtinyX5 based boards:
 *   - D0 (PB0, SDA): connected to DS1307 SDA pin
 *   - D2 (PB2, SCL): connected to DS1307 SDA pin
 *   - D3 (PB3, TX): connected to SerialUSB converter
 */

#include <fastarduino/time.h>
#include <fastarduino/new_i2c_handler.h>
#include <fastarduino/devices/new_ds1307.h>
#include <fastarduino/iomanip.h>
#include <fastarduino/new_i2c_debug.h>
#include <fastarduino/new_i2c_status.h>

#if defined(ARDUINO_UNO) || defined(ARDUINO_NANO) || defined(BREADBOARD_ATMEGA328P)
#define HARDWARE_UART 1
#include <fastarduino/uart.h>
static constexpr const board::USART UART = board::USART::USART0;
static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 64;
static constexpr uint8_t I2C_BUFFER_SIZE = 32;
// Define vectors we need in the example
REGISTER_UATX_ISR(0)
#elif defined(ARDUINO_MEGA)
#define HARDWARE_UART 1
#include <fastarduino/uart.h>
static constexpr const board::USART UART = board::USART::USART0;
static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 64;
static constexpr uint8_t I2C_BUFFER_SIZE = 32;
// Define vectors we need in the example
REGISTER_UATX_ISR(0)
#elif defined(ARDUINO_LEONARDO)
#define HARDWARE_UART 1
#include <fastarduino/uart.h>
static constexpr const board::USART UART = board::USART::USART1;
static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 64;
static constexpr uint8_t I2C_BUFFER_SIZE = 32;
// Define vectors we need in the example
REGISTER_UATX_ISR(1)
#elif defined(BREADBOARD_ATTINYX4)
#define HARDWARE_UART 0
#include <fastarduino/soft_uart.h>
static constexpr const board::DigitalPin TX = board::DigitalPin::D8_PB0;
static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 64;
#elif defined(BREADBOARD_ATTINYX5)
#define HARDWARE_UART 0
#include <fastarduino/soft_uart.h>
static constexpr const board::DigitalPin TX = board::DigitalPin::D3_PB3;
static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 64;
#else
#error "Current target is not yet supported!"
#endif

// #define DEBUG_I2C
// #define FORCE_SYNC

// UART buffer for traces
static char output_buffer[OUTPUT_BUFFER_SIZE];

using devices::rtc::DS1307;
using devices::rtc::WeekDay;
using devices::rtc::tm;
using devices::rtc::SquareWaveFrequency;
using namespace streams;

#ifdef DEBUG_I2C
static constexpr const uint8_t DEBUG_SIZE = 32;
using DEBUGGER = i2c::debug::I2CDebugStatusRecorder<DEBUG_SIZE, DEBUG_SIZE>;
#	if I2C_TRUE_ASYNC and not defined(FORCE_SYNC)
using MANAGER = i2c::I2CAsyncStatusDebugManager<
	i2c::I2CMode::STANDARD, i2c::I2CErrorPolicy::CLEAR_ALL_COMMANDS, DEBUGGER&, DEBUGGER&>;
static MANAGER::I2CCOMMAND i2c_buffer[I2C_BUFFER_SIZE];
#	else
using MANAGER = i2c::I2CSyncStatusDebugManager<i2c::I2CMode::STANDARD, DEBUGGER&, DEBUGGER&>;
#	endif
#define DEBUG(OUT) debugger.trace(OUT)
#define SHOW_STATUS(OUT)

#else

using STATUS = i2c::status::I2CLatestStatusHolder;
#	if I2C_TRUE_ASYNC and not defined(FORCE_SYNC)
using MANAGER = i2c::I2CAsyncStatusManager<
	i2c::I2CMode::STANDARD, i2c::I2CErrorPolicy::CLEAR_ALL_COMMANDS, STATUS&>;
static MANAGER::I2CCOMMAND i2c_buffer[I2C_BUFFER_SIZE];
#	else
using MANAGER = i2c::I2CSyncManager<i2c::I2CMode::STANDARD, STATUS&>;
#	endif
#define DEBUG(OUT)
#define SHOW_STATUS(OUT) OUT << streams::hex << status_holder.latest_status() << streams::endl
#endif

#if I2C_TRUE_ASYNC and not defined(FORCE_SYNC)
REGISTER_I2C_ISR(MANAGER)
#endif

void display_status(ostream& out, char index, uint8_t status)
{
	out << hex << F("status #") << index << ' ' << status << endl;
}

void display_ram(ostream& out, const uint8_t* data, uint8_t size)
{
	out << hex << F("RAM content\n");
	for (uint8_t i = 0; i < size; ++i)
	{
		if (!(i % 8)) out << endl;
		out << setw(2) << data[i] << ' ';
	}
	out << endl;
}

void display_time(ostream& out, const tm& time)
{
	out	<< dec << F("RTC: [")
		<< uint8_t(time.tm_wday) << ']'
		<< time.tm_mday << '.'
		<< time.tm_mon << '.'
		<< time.tm_year << ' '
		<< time.tm_hour << ':'
		<< time.tm_min << ':'
		<< time.tm_sec
		<< endl;
}

int main() __attribute__((OS_main));
int main()
{
	board::init();
	sei();
#if HARDWARE_UART
	serial::hard::UATX<UART> uart{output_buffer};
#else
	serial::soft::UATX<TX> uart{output_buffer};
#endif
	uart.begin(115200);
	ostream out = uart.out();
	out << F("Start") << endl;

	// Start TWI interface
	//====================
#ifdef DEBUG_I2C
	DEBUGGER debugger;
#else
	STATUS status_holder;
#endif

#if I2C_TRUE_ASYNC and not defined(FORCE_SYNC)
#	ifdef DEBUG_I2C
	MANAGER manager{i2c_buffer, debugger, debugger};
#	else
	MANAGER manager{i2c_buffer, status_holder};
#	endif
#else
#	ifdef DEBUG_I2C
	MANAGER manager{debugger, debugger};
#	else
	MANAGER manager{status_holder};
#	endif
#endif

	manager.begin();
	out << F("I2C interface started") << endl;
	SHOW_STATUS(out);
	time::delay_ms(1000);

	DS1307<MANAGER> rtc{manager};

	// read RAM content and print out
	uint8_t data[DS1307<MANAGER>::ram_size()];
	memset(data, 0, sizeof data);
	rtc.get_ram(0, data);
	SHOW_STATUS(out);
	display_ram(out, data, sizeof data);
	DEBUG(out);

	tm time1;
	time1.tm_hour = 8;
	time1.tm_min = 45;
	time1.tm_sec = 30;
	time1.tm_wday = WeekDay::TUESDAY;
	time1.tm_mday = 13;
	time1.tm_mon = 6;
	time1.tm_year = 17;

	// Initialize clock date
	//=======================
	rtc.set_datetime(time1);
	SHOW_STATUS(out);
	DEBUG(out);

	time::delay_ms(2000);

	// Read clock
	//============
	tm time2;
	rtc.get_datetime(time2);
	display_time(out, time2);
	SHOW_STATUS(out);
	DEBUG(out);

	// Enable output clock
	//====================
	rtc.enable_output(SquareWaveFrequency::FREQ_1HZ);
	SHOW_STATUS(out);
	DEBUG(out);

	// Provide 10 seconds delay to allow checking square wave output with an oscilloscope
	time::delay_ms(10000);

	rtc.disable_output(false);
	SHOW_STATUS(out);
	DEBUG(out);

	// write RAM content
	for (uint8_t i = 0; i < sizeof(data); ++i)
		data[i] = i;
	rtc.set_ram(0, data);
	SHOW_STATUS(out);
	DEBUG(out);

	// Stop TWI interface
	//===================
	manager.end();
	out << F("End") << endl;
}
<commit_msg>Fix compilation bug.<commit_after>//   Copyright 2016-2020 Jean-Francois Poilpret
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

/*
 * Check DS1307 I2C device (real-time clock) and display output to the UART console.
 * This program uses FastArduino DS1307 support API.
 *
 * Wiring:
 * NB: you should add pullup resistors (10K-22K typically) on both SDA and SCL lines.
 * WARNING: wiring is very sensitive for I2C connections! When using breadboard, ensure
 * wires connections are tight and stable.
 * - on ATmega328P based boards (including Arduino UNO):
 *   - A4 (PC4, SDA): connected to DS1307 SDA pin
 *   - A5 (PC5, SCL): connected to DS1307 SCL pin
 *   - direct USB access
 * - on Arduino LEONARDO:
 *   - D2 (PD1, SDA): connected to DS1307 SDA pin
 *   - D3 (PD0, SCL): connected to DS1307 SDA pin
 *   - direct USB access
 * - on Arduino MEGA:
 *   - D20 (PD1, SDA): connected to DS1307 SDA pin
 *   - D21 (PD0, SCL): connected to DS1307 SDA pin
 *   - direct USB access
 * - on ATtinyX4 based boards:
 *   - D6 (PA6, SDA): connected to DS1307 SDA pin
 *   - D4 (PA4, SCL): connected to DS1307 SDA pin
 *   - D8 (PB0, TX): connected to SerialUSB converter
 * - on ATtinyX5 based boards:
 *   - D0 (PB0, SDA): connected to DS1307 SDA pin
 *   - D2 (PB2, SCL): connected to DS1307 SDA pin
 *   - D3 (PB3, TX): connected to SerialUSB converter
 */

#include <fastarduino/time.h>
#include <fastarduino/new_i2c_handler.h>
#include <fastarduino/devices/new_ds1307.h>
#include <fastarduino/iomanip.h>
#include <fastarduino/new_i2c_debug.h>
#include <fastarduino/new_i2c_status.h>

#if defined(ARDUINO_UNO) || defined(ARDUINO_NANO) || defined(BREADBOARD_ATMEGA328P)
#define HARDWARE_UART 1
#include <fastarduino/uart.h>
static constexpr const board::USART UART = board::USART::USART0;
static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 64;
static constexpr uint8_t I2C_BUFFER_SIZE = 32;
// Define vectors we need in the example
REGISTER_UATX_ISR(0)
#elif defined(ARDUINO_MEGA)
#define HARDWARE_UART 1
#include <fastarduino/uart.h>
static constexpr const board::USART UART = board::USART::USART0;
static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 64;
static constexpr uint8_t I2C_BUFFER_SIZE = 32;
// Define vectors we need in the example
REGISTER_UATX_ISR(0)
#elif defined(ARDUINO_LEONARDO)
#define HARDWARE_UART 1
#include <fastarduino/uart.h>
static constexpr const board::USART UART = board::USART::USART1;
static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 64;
static constexpr uint8_t I2C_BUFFER_SIZE = 32;
// Define vectors we need in the example
REGISTER_UATX_ISR(1)
#elif defined(BREADBOARD_ATTINYX4)
#define HARDWARE_UART 0
#include <fastarduino/soft_uart.h>
static constexpr const board::DigitalPin TX = board::DigitalPin::D8_PB0;
static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 64;
#elif defined(BREADBOARD_ATTINYX5)
#define HARDWARE_UART 0
#include <fastarduino/soft_uart.h>
static constexpr const board::DigitalPin TX = board::DigitalPin::D3_PB3;
static constexpr const uint8_t OUTPUT_BUFFER_SIZE = 64;
#else
#error "Current target is not yet supported!"
#endif

// #define DEBUG_I2C
#define FORCE_SYNC

// UART buffer for traces
static char output_buffer[OUTPUT_BUFFER_SIZE];

using devices::rtc::DS1307;
using devices::rtc::WeekDay;
using devices::rtc::tm;
using devices::rtc::SquareWaveFrequency;
using namespace streams;

#ifdef DEBUG_I2C
static constexpr const uint8_t DEBUG_SIZE = 32;
using DEBUGGER = i2c::debug::I2CDebugStatusRecorder<DEBUG_SIZE, DEBUG_SIZE>;
#	if I2C_TRUE_ASYNC and not defined(FORCE_SYNC)
using MANAGER = i2c::I2CAsyncStatusDebugManager<
	i2c::I2CMode::STANDARD, i2c::I2CErrorPolicy::CLEAR_ALL_COMMANDS, DEBUGGER&, DEBUGGER&>;
static MANAGER::I2CCOMMAND i2c_buffer[I2C_BUFFER_SIZE];
#	else
using MANAGER = i2c::I2CSyncStatusDebugManager<i2c::I2CMode::STANDARD, DEBUGGER&, DEBUGGER&>;
#	endif
#define DEBUG(OUT) debugger.trace(OUT)
#define SHOW_STATUS(OUT)

#else

using STATUS = i2c::status::I2CLatestStatusHolder;
#	if I2C_TRUE_ASYNC and not defined(FORCE_SYNC)
using MANAGER = i2c::I2CAsyncStatusManager<
	i2c::I2CMode::STANDARD, i2c::I2CErrorPolicy::CLEAR_ALL_COMMANDS, STATUS&>;
static MANAGER::I2CCOMMAND i2c_buffer[I2C_BUFFER_SIZE];
#	else
using MANAGER = i2c::I2CSyncStatusManager<i2c::I2CMode::STANDARD, STATUS&>;
#	endif
#define DEBUG(OUT)
#define SHOW_STATUS(OUT) OUT << streams::hex << status_holder.latest_status() << streams::endl
#endif

#if I2C_TRUE_ASYNC and not defined(FORCE_SYNC)
REGISTER_I2C_ISR(MANAGER)
#endif

void display_status(ostream& out, char index, uint8_t status)
{
	out << hex << F("status #") << index << ' ' << status << endl;
}

void display_ram(ostream& out, const uint8_t* data, uint8_t size)
{
	out << hex << F("RAM content\n");
	for (uint8_t i = 0; i < size; ++i)
	{
		if (!(i % 8)) out << endl;
		out << setw(2) << data[i] << ' ';
	}
	out << endl;
}

void display_time(ostream& out, const tm& time)
{
	out	<< dec << F("RTC: [")
		<< uint8_t(time.tm_wday) << ']'
		<< time.tm_mday << '.'
		<< time.tm_mon << '.'
		<< time.tm_year << ' '
		<< time.tm_hour << ':'
		<< time.tm_min << ':'
		<< time.tm_sec
		<< endl;
}

int main() __attribute__((OS_main));
int main()
{
	board::init();
	sei();
#if HARDWARE_UART
	serial::hard::UATX<UART> uart{output_buffer};
#else
	serial::soft::UATX<TX> uart{output_buffer};
#endif
	uart.begin(115200);
	ostream out = uart.out();
	out << F("Start") << endl;

	// Start TWI interface
	//====================
#ifdef DEBUG_I2C
	DEBUGGER debugger;
#else
	STATUS status_holder;
#endif

#if I2C_TRUE_ASYNC and not defined(FORCE_SYNC)
#	ifdef DEBUG_I2C
	MANAGER manager{i2c_buffer, debugger, debugger};
#	else
	MANAGER manager{i2c_buffer, status_holder};
#	endif
#else
#	ifdef DEBUG_I2C
	MANAGER manager{debugger, debugger};
#	else
	MANAGER manager{status_holder};
#	endif
#endif

	manager.begin();
	out << F("I2C interface started") << endl;
	SHOW_STATUS(out);
	time::delay_ms(1000);

	DS1307<MANAGER> rtc{manager};

	// read RAM content and print out
	uint8_t data[DS1307<MANAGER>::ram_size()];
	memset(data, 0, sizeof data);
	rtc.get_ram(0, data);
	SHOW_STATUS(out);
	display_ram(out, data, sizeof data);
	DEBUG(out);

	tm time1;
	time1.tm_hour = 8;
	time1.tm_min = 45;
	time1.tm_sec = 30;
	time1.tm_wday = WeekDay::TUESDAY;
	time1.tm_mday = 13;
	time1.tm_mon = 6;
	time1.tm_year = 17;

	// Initialize clock date
	//=======================
	rtc.set_datetime(time1);
	SHOW_STATUS(out);
	DEBUG(out);

	time::delay_ms(2000);

	// Read clock
	//============
	tm time2;
	rtc.get_datetime(time2);
	display_time(out, time2);
	SHOW_STATUS(out);
	DEBUG(out);

	// Enable output clock
	//====================
	rtc.enable_output(SquareWaveFrequency::FREQ_1HZ);
	SHOW_STATUS(out);
	DEBUG(out);

	// Provide 10 seconds delay to allow checking square wave output with an oscilloscope
	time::delay_ms(10000);

	rtc.disable_output(false);
	SHOW_STATUS(out);
	DEBUG(out);

	// write RAM content
	for (uint8_t i = 0; i < sizeof(data); ++i)
		data[i] = i;
	rtc.set_ram(0, data);
	SHOW_STATUS(out);
	DEBUG(out);

	// Stop TWI interface
	//===================
	manager.end();
	out << F("End") << endl;
}
<|endoftext|>


<commit_before>/// @file Utils.cpp
///
/// The utilities unit test.
///
/// @ingroup UnitTest
///
/// @par Copyright (c) 2017 vcdMaker team
///
/// Permission is hereby granted, free of charge, to any person obtaining a
/// copy of this software and associated documentation files (the "Software"),
/// to deal in the Software without restriction, including without limitation
/// the rights to use, copy, modify, merge, publish, distribute, sublicense,
/// and/or sell copies of the Software, and to permit persons to whom the
/// Software is furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included
/// in all copies or substantial portions of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
/// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
/// IN THE SOFTWARE.

#include "catch.hpp"

#include "Utils.h"

using namespace std::string_literals;

using StringVector = std::vector<std::string>;

/// Unit test for Split().
TEST_CASE("UTILS::Split")
{
    REQUIRE((UTILS::Split(""s, '\0')) == (StringVector{}));
    REQUIRE((UTILS::Split("abcd"s, '\0')) == (StringVector{"abcd"s}));
    REQUIRE((UTILS::Split("a b c d"s, ' ')) == (StringVector{"a"s, "b"s, "c"s, "d"s}));
    REQUIRE((UTILS::Split(" a b c d"s, ' ')) == (StringVector{"a"s, "b"s, "c"s, "d"s}));
    REQUIRE((UTILS::Split("a b c d "s, ' ')) == (StringVector{"a"s, "b"s, "c"s, "d"s}));
    REQUIRE((UTILS::Split(" a b c d "s, ' ')) == (StringVector{"a"s, "b"s, "c"s, "d"s}));
    REQUIRE((UTILS::Split("a b   c  d"s, ' ')) == (StringVector{"a"s, "b"s, "c"s, "d"s}));
}

/// Unit test for IsTimeUnitValid().
TEST_CASE("UTILS::IsTimeUnitValid")
{
    REQUIRE(UTILS::IsTimeUnitValid("a"s));
    REQUIRE(UTILS::IsTimeUnitValid("b"s));
    REQUIRE(UTILS::IsTimeUnitValid("c"s));
    REQUIRE(UTILS::IsTimeUnitValid("d"s));

    REQUIRE_FALSE(UTILS::IsTimeUnitValid("e"s));
}

/// Unit test for GetTimeUnitIndex().
TEST_CASE("UTILS::GetTimeUnitIndex")
{
    REQUIRE(UTILS::GetTimeUnitIndex("a"s) == 0);
    REQUIRE(UTILS::GetTimeUnitIndex("b"s) == 1);
    REQUIRE(UTILS::GetTimeUnitIndex("c"s) == 2);
    REQUIRE(UTILS::GetTimeUnitIndex("d"s) == 3);

    REQUIRE_THROWS(UTILS::GetTimeUnitIndex("e"s));
}
<commit_msg>Missing doxygen comment<commit_after>/// @file Utils.cpp
///
/// The utilities unit test.
///
/// @ingroup UnitTest
///
/// @par Copyright (c) 2017 vcdMaker team
///
/// Permission is hereby granted, free of charge, to any person obtaining a
/// copy of this software and associated documentation files (the "Software"),
/// to deal in the Software without restriction, including without limitation
/// the rights to use, copy, modify, merge, publish, distribute, sublicense,
/// and/or sell copies of the Software, and to permit persons to whom the
/// Software is furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included
/// in all copies or substantial portions of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
/// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
/// IN THE SOFTWARE.

#include "catch.hpp"

#include "Utils.h"

using namespace std::string_literals;

/// Vector of strings.
using StringVector = std::vector<std::string>;

/// Unit test for Split().
TEST_CASE("UTILS::Split")
{
    REQUIRE((UTILS::Split(""s, '\0')) == (StringVector{}));
    REQUIRE((UTILS::Split("abcd"s, '\0')) == (StringVector{"abcd"s}));
    REQUIRE((UTILS::Split("a b c d"s, ' ')) == (StringVector{"a"s, "b"s, "c"s, "d"s}));
    REQUIRE((UTILS::Split(" a b c d"s, ' ')) == (StringVector{"a"s, "b"s, "c"s, "d"s}));
    REQUIRE((UTILS::Split("a b c d "s, ' ')) == (StringVector{"a"s, "b"s, "c"s, "d"s}));
    REQUIRE((UTILS::Split(" a b c d "s, ' ')) == (StringVector{"a"s, "b"s, "c"s, "d"s}));
    REQUIRE((UTILS::Split("a b   c  d"s, ' ')) == (StringVector{"a"s, "b"s, "c"s, "d"s}));
}

/// Unit test for IsTimeUnitValid().
TEST_CASE("UTILS::IsTimeUnitValid")
{
    REQUIRE(UTILS::IsTimeUnitValid("a"s));
    REQUIRE(UTILS::IsTimeUnitValid("b"s));
    REQUIRE(UTILS::IsTimeUnitValid("c"s));
    REQUIRE(UTILS::IsTimeUnitValid("d"s));

    REQUIRE_FALSE(UTILS::IsTimeUnitValid("e"s));
}

/// Unit test for GetTimeUnitIndex().
TEST_CASE("UTILS::GetTimeUnitIndex")
{
    REQUIRE(UTILS::GetTimeUnitIndex("a"s) == 0);
    REQUIRE(UTILS::GetTimeUnitIndex("b"s) == 1);
    REQUIRE(UTILS::GetTimeUnitIndex("c"s) == 2);
    REQUIRE(UTILS::GetTimeUnitIndex("d"s) == 3);

    REQUIRE_THROWS(UTILS::GetTimeUnitIndex("e"s));
}
<|endoftext|>


<commit_before>#include "QmitkTransferFunctionGeneratorWidget.h"

#include <mitkTransferFunctionProperty.h>
#include <mitkRenderingManager.h>

#include <QFileDialog>

#include <SceneSerializationExports.h>
#include <mitkTransferFunctionPropertySerializer.h>
#include <mitkTransferFunctionPropertyDeserializer.h>

static char* presetNames[] = {  "choose an internal transferfunction preset",
                              "CT Generic",
                              "CT Black & White",
                              "CT Cardiac",
                              "CT Bone",
                              "CT Bone (with Gradient)",
                              "MR Generic" };

static int numPresetNames = sizeof( presetNames ) / sizeof( char * );

QmitkTransferFunctionGeneratorWidget::QmitkTransferFunctionGeneratorWidget(QWidget* parent,
    Qt::WindowFlags f) :
  QWidget(parent, f)
{
  histoGramm = NULL;

  this->setupUi(this);

  // LevelWindow Tab
  {
    connect( m_CrossLevelWindow, SIGNAL( SignalDeltaMove( int, int ) ), this, SLOT( OnDeltaLevelWindow( int, int ) ) );
  }

  // Threshold Tab
  {
    connect( m_CrossThreshold, SIGNAL( SignalDeltaMove( int, int ) ), this, SLOT( OnDeltaThreshold( int, int ) ) );
    thDelta = 1;
  }

  // Presets Tab
  {
    for(int r=0; r< numPresetNames; r++)
        m_TransferFunctionComboBox->insertItem( presetNames[r]);

    connect( m_TransferFunctionComboBox, SIGNAL( activated( int ) ), this, SLOT( OnMitkInternalPreset( int ) ) );

    connect( m_SavePreset, SIGNAL( clicked() ), this, SLOT( OnSavePreset() ) );

    connect( m_LoadPreset, SIGNAL( clicked() ), this, SLOT( OnLoadPreset() ) );
  }

  presetFileName = ".";
}

void QmitkTransferFunctionGeneratorWidget::OnSavePreset( )
{
  if(tfpToChange.IsNull())
    return;

  mitk::TransferFunction::Pointer tf = tfpToChange->GetValue();

  std::string fileName;
  std::string fileNameOutput;

  presetFileName = QFileDialog::getSaveFileName( this,"Choose a filename to save the transferfunction",presetFileName, "Transferfunction (*.xml)" );

  fileName=presetFileName.ascii();

  LOG_INFO << "Saving Transferfunction under path: " << fileName;

  fileNameOutput= ReduceFileName(fileName);

  if ( mitk::TransferFunctionPropertySerializer::SerializeTransferFunction( fileName.c_str(),  tf ))
    m_InfoPreset->setText( QString( (std::string("saved ")+ fileNameOutput).c_str() ) );
  else
    m_InfoPreset->setText( QString( std::string("saving failed").c_str() ) );
                                           /*
  FILE *f=fopen("c:\\temp.txt","w");

  // grayvalue -> opacity
  {
    mitk::TransferFunction::ControlPoints scalarOpacityPoints = tf->GetScalarOpacityPoints();
    fprintf(f,"// grayvalue->opacity \n"
              "{\n"
              "  vtkPiecewiseFunction *f=tf->GetScalarOpacityFunction();\n"
              "  f->RemoveAllPoints();\n");
    for ( mitk::TransferFunction::ControlPoints::iterator iter = scalarOpacityPoints.begin(); iter != scalarOpacityPoints.end(); ++iter )
    fprintf(f,"  f->AddPoint(%f,%f);\n",iter->first, iter->second);
    fprintf(f,"  f->Modified();\n"
              "}\n");
  }

  // gradient
  {
    mitk::TransferFunction::ControlPoints gradientOpacityPoints = tf->GetGradientOpacityPoints();
    fprintf(f,"// gradient at grayvalue->opacity \n"
              "{\n"
              "  vtkPiecewiseFunction *f=tf->GetGradientOpacityFunction();\n"
              "  f->RemoveAllPoints();\n");
    for ( mitk::TransferFunction::ControlPoints::iterator iter = gradientOpacityPoints.begin(); iter != gradientOpacityPoints.end(); ++iter )
    fprintf(f,"  f->AddPoint(%f,%f);\n",iter->first, iter->second);
    fprintf(f,"  f->Modified();\n"
              "}\n");
  }

  // color
  {
    mitk::TransferFunction::RGBControlPoints points = tf->GetRGBPoints();

    fprintf(f,"// grayvalue->color \n"
              "{\n"
              "  vtkColorTransferFunction *f=tf->GetColorTransferFunction();\n"
              "  f->RemoveAllPoints();\n");
    for ( mitk::TransferFunction::RGBControlPoints::iterator iter = points.begin(); iter != points.end(); ++iter )
    fprintf(f,"  f->AddRGBPoint(%f,%f,%f,%f);\n",iter->first, iter->second[0], iter->second[1], iter->second[2]);
    fprintf(f,"  f->Modified();\n"
              "}\n");
  }

  fclose(f);

  LOG_INFO << "saved under C:\\temp.txt";
                                             */
}

void QmitkTransferFunctionGeneratorWidget::OnLoadPreset( )
{
  if(tfpToChange.IsNull())
    return;

  std::string fileName;
  std::string fileNameOutput;

  presetFileName = QFileDialog::getOpenFileName( this,"Choose a file to open the transferfunction from",presetFileName, "Transferfunction (*.xml)"  );

  fileName=presetFileName.ascii();

  LOG_INFO << "Loading Transferfunction from path: " << fileName;

  fileNameOutput= ReduceFileName(fileName);

  mitk::TransferFunction::Pointer tf = mitk::TransferFunctionPropertyDeserializer::DeserializeTransferFunction(fileName.c_str());

  if(tf.IsNotNull())
  {
    if( histoGramm )
      tf->InitializeByItkHistogram( histoGramm );

    tfpToChange->SetValue( tf );

    m_InfoPreset->setText( QString( (std::string("loaded ")+ fileNameOutput).c_str() ) );
    mitk::RenderingManager::GetInstance()->RequestUpdateAll();
    emit SignalUpdateCanvas();

    /*
    vtkFloatingPointType* dp = tf->GetScalarOpacityFunction()->GetDataPointer();
    for (int i = 0; i < tf->GetScalarOpacityFunction()->GetSize(); i++)
    {
      LOG_INFO << "x: " << dp[i * 2] << " y: " << dp[i * 2 + 1];
    }
    */
  }
}

void QmitkTransferFunctionGeneratorWidget::OnMitkInternalPreset( int mode )
{
  if(tfpToChange.IsNull())
    return;

  //first item is only information
  if( --mode == -1 )
    return;

  //revert to first item
  m_TransferFunctionComboBox->setCurrentIndex( 0 );

  // -- Creat new TransferFunction
  tfpToChange->GetValue()->SetTransferFunctionMode( mode );
  mitk::RenderingManager::GetInstance()->RequestUpdateAll();
  emit SignalUpdateCanvas();
  m_InfoPreset->setText( QString( (std::string("selected ")+ std::string(presetNames[mode+1])).c_str() ) );
}

static double transformationGlocke ( double x )
{
  double z = 0.1;

  double a = 2 - 2 * z;

  double b = 2 * z - 1;

  x = a * x + b;

  return x;
}

static double stepFunctionGlocke ( double x )
{
  x = 1-(2*x -1.0); // map [0.5;1] to [0,1]
  x = x * ( 3*x - 2*x*x ); // apply smoothing function

  x = x * x;

  return x;
}

void QmitkTransferFunctionGeneratorWidget::OnDeltaLevelWindow(int dx, int dy)      // bell
{
  //std::string infoText;

//  m_InfoThreshold->setText( QString( x.c_str() ) );

  if(tfpToChange.IsNull())
    return;

  thPos += dx;
  thDelta -= dy;

  if(thDelta < 1)
    thDelta = 1;

  if(thDelta > 1024)
    thDelta = 1024;

  if(thPos < histoMinimum)
    thPos = histoMinimum;

  if(thPos > histoMaximum)
    thPos = histoMaximum;

  std::stringstream ss;

  ss << "Click on the cross and move the mouse"<<"\n"
     <<"\n"
     << "center at " << thPos << "\n"
     << "width " << thDelta * 2;

  m_InfoLevelWindow->setText( QString( ss.str().c_str() ) );

  mitk::TransferFunction::Pointer tf = tfpToChange->GetValue();

  // grayvalue->opacity
  {
    vtkPiecewiseFunction *f=tf->GetScalarOpacityFunction();
    f->RemoveAllPoints();

    for( int r = 0; r<= 6; r++)
    {
      double relPos = (r / 6.0) * 0.5 + 0.5;
      f->AddPoint(thPos+thDelta*(-transformationGlocke(relPos)),stepFunctionGlocke(relPos));
      f->AddPoint(thPos+thDelta*( transformationGlocke(relPos)),stepFunctionGlocke(relPos));
    }

    f->Modified();
  }

  // gradient at grayvalue->opacity
  {
    vtkPiecewiseFunction *f=tf->GetGradientOpacityFunction();
    f->RemoveAllPoints();

    f->AddPoint( 0, 1.0 );
    f->Modified();
  }
/*
  // grayvalue->color
  {
    vtkColorTransferFunction *ctf=tf->GetColorTransferFunction();
    ctf->RemoveAllPoints();
    ctf->AddRGBPoint( 0, 1.0, 1.0, 1.0 );
    ctf->Modified();
  }
  */
  tf->Modified();

  mitk::RenderingManager::GetInstance()->RequestUpdateAll();
  emit SignalUpdateCanvas();
}

static double stepFunctionThreshold ( double x )
{
  x = 0.5*x + 0.5; // map [-1;1] to [0,1]
  x = x * ( 3*x - 2*x*x ); // apply smoothing function

  x = x * x;

  return x;
}

void QmitkTransferFunctionGeneratorWidget::OnDeltaThreshold(int dx, int dy)   // LEVELWINDOW
{

  if(tfpToChange.IsNull())
    return;

  thPos += dx;
  thDelta += dy;

  if(thDelta < 1)
    thDelta = 1;

  if(thDelta > 1024)
    thDelta = 1024;

  if(thPos < histoMinimum)
    thPos = histoMinimum;

  if(thPos > histoMaximum)
    thPos = histoMaximum;
          /*
  LOG_INFO << "threshold pos: " << thPos << " delta: " << thDelta;

  LOG_INFO << "histoMinimum: " << histoMinimum << " max: " << histoMaximum;
            */

  std::stringstream ss;

  ss << "Click on the cross and move the mouse"<<"\n"
     <<"\n"
     << "threshold at " << thPos << "\n"
     << "width " << thDelta * 2;

  m_InfoThreshold->setText( QString( ss.str().c_str() ) );

  mitk::TransferFunction::Pointer tf = tfpToChange->GetValue();

  // grayvalue->opacity
  {
    vtkPiecewiseFunction *f=tf->GetScalarOpacityFunction();
    f->RemoveAllPoints();

    for( int r = 1; r<= 4; r++)
    {
      double relPos = r / 4.0;
      f->AddPoint(thPos+thDelta*(-relPos),stepFunctionThreshold(-relPos));
      f->AddPoint(thPos+thDelta*( relPos),stepFunctionThreshold( relPos));
    }
    f->Modified();
  }

  // gradient at grayvalue->opacity
  {
    vtkPiecewiseFunction *f=tf->GetGradientOpacityFunction();
    f->RemoveAllPoints();
    f->AddPoint( 0, 1.0 );
    f->Modified();
  }
/*
  // grayvalue->color
  {
    vtkColorTransferFunction *ctf=tf->GetColorTransferFunction();
    ctf->RemoveAllPoints();
    ctf->AddRGBPoint( 0, 1.0, 1.0, 1.0 );
    ctf->Modified();
  }
  */

  tf->Modified();
  mitk::RenderingManager::GetInstance()->RequestUpdateAll();
  emit SignalUpdateCanvas();

}

std::string QmitkTransferFunctionGeneratorWidget::ReduceFileName(std::string fileNameLong )
{
  if (fileNameLong.length()< 40)
    return fileNameLong;

  //LOG_INFO <<" fileName > 20 ";

  std::string fileNameShort;
  std::string fileNameRevert;

  for(int i=0; i< fileNameLong.length(); i++)
  {
    if(i<3)
    {
      char x= fileNameLong[i];
      fileNameShort= fileNameShort+x;
    }
    if(i==3)
    {
      fileNameShort= fileNameShort+"...";
      break;
    }
  }
  //LOG_INFO <<" fileNameShort: " << fileNameShort.c_str();
  for(int i=fileNameLong.length()-1; i>= 0; i--)
  {
    std::string x=std::string("")+fileNameLong[i];

    if ( x.compare("/")==0 || x.compare("\\")==0)
    {
      fileNameRevert= "/" + fileNameRevert;
      break;
    }

    if (i>=fileNameLong.length()-24)
    {
      fileNameRevert= x+ fileNameRevert;
      LOG_INFO <<" fileNameRevert: " << fileNameRevert.c_str();
    }
    else
    {
      fileNameRevert= "/..." + fileNameRevert;
      break;
    }

  }

  return fileNameShort+fileNameRevert;
}

QmitkTransferFunctionGeneratorWidget::~QmitkTransferFunctionGeneratorWidget()
{
}

void QmitkTransferFunctionGeneratorWidget::SetDataTreeNode(mitk::DataTreeNode* node)
{
  histoGramm = NULL;

  if (node)
  {
    tfpToChange = dynamic_cast<mitk::TransferFunctionProperty*>(node->GetProperty("TransferFunction"));

    if(!tfpToChange)
    {
      if (! dynamic_cast<mitk::Image*>(node->GetData()))
      {
        LOG_WARN << "QmitkTransferFunctionGeneratorWidget::SetDataTreeNode called with non-image node";
        return;
      }

      node->SetProperty("TransferFunction", tfpToChange = mitk::TransferFunctionProperty::New() );
      dynamic_cast<mitk::TransferFunctionProperty*>(node->GetProperty("TransferFunction"));
    }

    mitk::TransferFunction::Pointer tf = tfpToChange->GetValue();

    if( mitk::Image* image = dynamic_cast<mitk::Image*>( node->GetData() ) )
      tf->InitializeByItkHistogram( histoGramm = image->GetScalarHistogram() );

    thPos = ( tf->GetMin() + tf->GetMax() ) / 2;

    histoMinimum = tf->GetMin();
    histoMaximum = tf->GetMax();
  }
  else
  {
    tfpToChange = 0;
    m_InfoPreset->setText( QString( "" ) );

  }
}

<commit_msg>ENH (#2733): If you click on the cross, the bell is wider now<commit_after>#include "QmitkTransferFunctionGeneratorWidget.h"

#include <mitkTransferFunctionProperty.h>
#include <mitkRenderingManager.h>

#include <QFileDialog>

#include <SceneSerializationExports.h>
#include <mitkTransferFunctionPropertySerializer.h>
#include <mitkTransferFunctionPropertyDeserializer.h>

static char* presetNames[] = {  "choose an internal transferfunction preset",
                              "CT Generic",
                              "CT Black & White",
                              "CT Cardiac",
                              "CT Bone",
                              "CT Bone (with Gradient)",
                              "MR Generic" };

static int numPresetNames = sizeof( presetNames ) / sizeof( char * );

QmitkTransferFunctionGeneratorWidget::QmitkTransferFunctionGeneratorWidget(QWidget* parent,
    Qt::WindowFlags f) :
  QWidget(parent, f)
{
  histoGramm = NULL;

  this->setupUi(this);

  // LevelWindow Tab
  {
    connect( m_CrossLevelWindow, SIGNAL( SignalDeltaMove( int, int ) ), this, SLOT( OnDeltaLevelWindow( int, int ) ) );
  }

  // Threshold Tab
  {
    connect( m_CrossThreshold, SIGNAL( SignalDeltaMove( int, int ) ), this, SLOT( OnDeltaThreshold( int, int ) ) );
    thDelta = 100;
  }

  // Presets Tab
  {
    for(int r=0; r< numPresetNames; r++)
        m_TransferFunctionComboBox->insertItem( presetNames[r]);

    connect( m_TransferFunctionComboBox, SIGNAL( activated( int ) ), this, SLOT( OnMitkInternalPreset( int ) ) );

    connect( m_SavePreset, SIGNAL( clicked() ), this, SLOT( OnSavePreset() ) );

    connect( m_LoadPreset, SIGNAL( clicked() ), this, SLOT( OnLoadPreset() ) );
  }

  presetFileName = ".";
}

void QmitkTransferFunctionGeneratorWidget::OnSavePreset( )
{
  if(tfpToChange.IsNull())
    return;

  mitk::TransferFunction::Pointer tf = tfpToChange->GetValue();

  std::string fileName;
  std::string fileNameOutput;

  presetFileName = QFileDialog::getSaveFileName( this,"Choose a filename to save the transferfunction",presetFileName, "Transferfunction (*.xml)" );

  fileName=presetFileName.ascii();

  LOG_INFO << "Saving Transferfunction under path: " << fileName;

  fileNameOutput= ReduceFileName(fileName);

  if ( mitk::TransferFunctionPropertySerializer::SerializeTransferFunction( fileName.c_str(),  tf ))
    m_InfoPreset->setText( QString( (std::string("saved ")+ fileNameOutput).c_str() ) );
  else
    m_InfoPreset->setText( QString( std::string("saving failed").c_str() ) );
                                           /*
  FILE *f=fopen("c:\\temp.txt","w");

  // grayvalue -> opacity
  {
    mitk::TransferFunction::ControlPoints scalarOpacityPoints = tf->GetScalarOpacityPoints();
    fprintf(f,"// grayvalue->opacity \n"
              "{\n"
              "  vtkPiecewiseFunction *f=tf->GetScalarOpacityFunction();\n"
              "  f->RemoveAllPoints();\n");
    for ( mitk::TransferFunction::ControlPoints::iterator iter = scalarOpacityPoints.begin(); iter != scalarOpacityPoints.end(); ++iter )
    fprintf(f,"  f->AddPoint(%f,%f);\n",iter->first, iter->second);
    fprintf(f,"  f->Modified();\n"
              "}\n");
  }

  // gradient
  {
    mitk::TransferFunction::ControlPoints gradientOpacityPoints = tf->GetGradientOpacityPoints();
    fprintf(f,"// gradient at grayvalue->opacity \n"
              "{\n"
              "  vtkPiecewiseFunction *f=tf->GetGradientOpacityFunction();\n"
              "  f->RemoveAllPoints();\n");
    for ( mitk::TransferFunction::ControlPoints::iterator iter = gradientOpacityPoints.begin(); iter != gradientOpacityPoints.end(); ++iter )
    fprintf(f,"  f->AddPoint(%f,%f);\n",iter->first, iter->second);
    fprintf(f,"  f->Modified();\n"
              "}\n");
  }

  // color
  {
    mitk::TransferFunction::RGBControlPoints points = tf->GetRGBPoints();

    fprintf(f,"// grayvalue->color \n"
              "{\n"
              "  vtkColorTransferFunction *f=tf->GetColorTransferFunction();\n"
              "  f->RemoveAllPoints();\n");
    for ( mitk::TransferFunction::RGBControlPoints::iterator iter = points.begin(); iter != points.end(); ++iter )
    fprintf(f,"  f->AddRGBPoint(%f,%f,%f,%f);\n",iter->first, iter->second[0], iter->second[1], iter->second[2]);
    fprintf(f,"  f->Modified();\n"
              "}\n");
  }

  fclose(f);

  LOG_INFO << "saved under C:\\temp.txt";
                                             */
}

void QmitkTransferFunctionGeneratorWidget::OnLoadPreset( )
{
  if(tfpToChange.IsNull())
    return;

  std::string fileName;
  std::string fileNameOutput;

  presetFileName = QFileDialog::getOpenFileName( this,"Choose a file to open the transferfunction from",presetFileName, "Transferfunction (*.xml)"  );

  fileName=presetFileName.ascii();

  LOG_INFO << "Loading Transferfunction from path: " << fileName;

  fileNameOutput= ReduceFileName(fileName);

  mitk::TransferFunction::Pointer tf = mitk::TransferFunctionPropertyDeserializer::DeserializeTransferFunction(fileName.c_str());

  if(tf.IsNotNull())
  {
    if( histoGramm )
      tf->InitializeByItkHistogram( histoGramm );

    tfpToChange->SetValue( tf );

    m_InfoPreset->setText( QString( (std::string("loaded ")+ fileNameOutput).c_str() ) );
    mitk::RenderingManager::GetInstance()->RequestUpdateAll();
    emit SignalUpdateCanvas();

    /*
    vtkFloatingPointType* dp = tf->GetScalarOpacityFunction()->GetDataPointer();
    for (int i = 0; i < tf->GetScalarOpacityFunction()->GetSize(); i++)
    {
      LOG_INFO << "x: " << dp[i * 2] << " y: " << dp[i * 2 + 1];
    }
    */
  }
}

void QmitkTransferFunctionGeneratorWidget::OnMitkInternalPreset( int mode )
{
  if(tfpToChange.IsNull())
    return;

  //first item is only information
  if( --mode == -1 )
    return;

  //revert to first item
  m_TransferFunctionComboBox->setCurrentIndex( 0 );

  // -- Creat new TransferFunction
  tfpToChange->GetValue()->SetTransferFunctionMode( mode );
  mitk::RenderingManager::GetInstance()->RequestUpdateAll();
  emit SignalUpdateCanvas();
  m_InfoPreset->setText( QString( (std::string("selected ")+ std::string(presetNames[mode+1])).c_str() ) );
}

static double transformationGlocke ( double x )
{
  double z = 0.1;

  double a = 2 - 2 * z;

  double b = 2 * z - 1;

  x = a * x + b;

  return x;
}

static double stepFunctionGlocke ( double x )
{
  x = 1-(2*x -1.0); // map [0.5;1] to [0,1]
  x = x * ( 3*x - 2*x*x ); // apply smoothing function

  x = x * x;

  return x;
}

void QmitkTransferFunctionGeneratorWidget::OnDeltaLevelWindow(int dx, int dy)      // bell
{
  //std::string infoText;

//  m_InfoThreshold->setText( QString( x.c_str() ) );

  if(tfpToChange.IsNull())
    return;

  thPos += dx;
  thDelta -= dy;

  if(thDelta < 1)
    thDelta = 1;

  if(thDelta > 1024)
    thDelta = 1024;

  if(thPos < histoMinimum)
    thPos = histoMinimum;

  if(thPos > histoMaximum)
    thPos = histoMaximum;

  std::stringstream ss;

  ss << "Click on the cross and move the mouse"<<"\n"
     <<"\n"
     << "center at " << thPos << "\n"
     << "width " << thDelta * 2;

  m_InfoLevelWindow->setText( QString( ss.str().c_str() ) );

  mitk::TransferFunction::Pointer tf = tfpToChange->GetValue();

  // grayvalue->opacity
  {
    vtkPiecewiseFunction *f=tf->GetScalarOpacityFunction();
    f->RemoveAllPoints();

    for( int r = 0; r<= 6; r++)
    {
      double relPos = (r / 6.0) * 0.5 + 0.5;
      f->AddPoint(thPos+thDelta*(-transformationGlocke(relPos)),stepFunctionGlocke(relPos));
      f->AddPoint(thPos+thDelta*( transformationGlocke(relPos)),stepFunctionGlocke(relPos));
    }

    f->Modified();
  }

  // gradient at grayvalue->opacity
  {
    vtkPiecewiseFunction *f=tf->GetGradientOpacityFunction();
    f->RemoveAllPoints();

    f->AddPoint( 0, 1.0 );
    f->Modified();
  }
/*
  // grayvalue->color
  {
    vtkColorTransferFunction *ctf=tf->GetColorTransferFunction();
    ctf->RemoveAllPoints();
    ctf->AddRGBPoint( 0, 1.0, 1.0, 1.0 );
    ctf->Modified();
  }
  */
  tf->Modified();

  mitk::RenderingManager::GetInstance()->RequestUpdateAll();
  emit SignalUpdateCanvas();
}

static double stepFunctionThreshold ( double x )
{
  x = 0.5*x + 0.5; // map [-1;1] to [0,1]
  x = x * ( 3*x - 2*x*x ); // apply smoothing function

  x = x * x;

  return x;
}

void QmitkTransferFunctionGeneratorWidget::OnDeltaThreshold(int dx, int dy)   // LEVELWINDOW
{

  if(tfpToChange.IsNull())
    return;

  thPos += dx;
  thDelta += dy;

  if(thDelta < 1)
    thDelta = 1;

  if(thDelta > 1024)
    thDelta = 1024;

  if(thPos < histoMinimum)
    thPos = histoMinimum;

  if(thPos > histoMaximum)
    thPos = histoMaximum;
          /*
  LOG_INFO << "threshold pos: " << thPos << " delta: " << thDelta;

  LOG_INFO << "histoMinimum: " << histoMinimum << " max: " << histoMaximum;
            */

  std::stringstream ss;

  ss << "Click on the cross and move the mouse"<<"\n"
     <<"\n"
     << "threshold at " << thPos << "\n"
     << "width " << thDelta * 2;

  m_InfoThreshold->setText( QString( ss.str().c_str() ) );

  mitk::TransferFunction::Pointer tf = tfpToChange->GetValue();

  // grayvalue->opacity
  {
    vtkPiecewiseFunction *f=tf->GetScalarOpacityFunction();
    f->RemoveAllPoints();

    for( int r = 1; r<= 4; r++)
    {
      double relPos = r / 4.0;
      f->AddPoint(thPos+thDelta*(-relPos),stepFunctionThreshold(-relPos));
      f->AddPoint(thPos+thDelta*( relPos),stepFunctionThreshold( relPos));
    }
    f->Modified();
  }

  // gradient at grayvalue->opacity
  {
    vtkPiecewiseFunction *f=tf->GetGradientOpacityFunction();
    f->RemoveAllPoints();
    f->AddPoint( 0, 1.0 );
    f->Modified();
  }
/*
  // grayvalue->color
  {
    vtkColorTransferFunction *ctf=tf->GetColorTransferFunction();
    ctf->RemoveAllPoints();
    ctf->AddRGBPoint( 0, 1.0, 1.0, 1.0 );
    ctf->Modified();
  }
  */

  tf->Modified();
  mitk::RenderingManager::GetInstance()->RequestUpdateAll();
  emit SignalUpdateCanvas();

}

std::string QmitkTransferFunctionGeneratorWidget::ReduceFileName(std::string fileNameLong )
{
  if (fileNameLong.length()< 40)
    return fileNameLong;

  //LOG_INFO <<" fileName > 20 ";

  std::string fileNameShort;
  std::string fileNameRevert;

  for(int i=0; i< fileNameLong.length(); i++)
  {
    if(i<3)
    {
      char x= fileNameLong[i];
      fileNameShort= fileNameShort+x;
    }
    if(i==3)
    {
      fileNameShort= fileNameShort+"...";
      break;
    }
  }
  //LOG_INFO <<" fileNameShort: " << fileNameShort.c_str();
  for(int i=fileNameLong.length()-1; i>= 0; i--)
  {
    std::string x=std::string("")+fileNameLong[i];

    if ( x.compare("/")==0 || x.compare("\\")==0)
    {
      fileNameRevert= "/" + fileNameRevert;
      break;
    }

    if (i>=fileNameLong.length()-24)
    {
      fileNameRevert= x+ fileNameRevert;
      LOG_INFO <<" fileNameRevert: " << fileNameRevert.c_str();
    }
    else
    {
      fileNameRevert= "/..." + fileNameRevert;
      break;
    }

  }

  return fileNameShort+fileNameRevert;
}

QmitkTransferFunctionGeneratorWidget::~QmitkTransferFunctionGeneratorWidget()
{
}

void QmitkTransferFunctionGeneratorWidget::SetDataTreeNode(mitk::DataTreeNode* node)
{
  histoGramm = NULL;

  if (node)
  {
    tfpToChange = dynamic_cast<mitk::TransferFunctionProperty*>(node->GetProperty("TransferFunction"));

    if(!tfpToChange)
    {
      if (! dynamic_cast<mitk::Image*>(node->GetData()))
      {
        LOG_WARN << "QmitkTransferFunctionGeneratorWidget::SetDataTreeNode called with non-image node";
        return;
      }

      node->SetProperty("TransferFunction", tfpToChange = mitk::TransferFunctionProperty::New() );
      dynamic_cast<mitk::TransferFunctionProperty*>(node->GetProperty("TransferFunction"));
    }

    mitk::TransferFunction::Pointer tf = tfpToChange->GetValue();

    if( mitk::Image* image = dynamic_cast<mitk::Image*>( node->GetData() ) )
      tf->InitializeByItkHistogram( histoGramm = image->GetScalarHistogram() );

    thPos = ( tf->GetMin() + tf->GetMax() ) / 2;

    histoMinimum = tf->GetMin();
    histoMaximum = tf->GetMax();
  }
  else
  {
    tfpToChange = 0;
    m_InfoPreset->setText( QString( "" ) );

  }
}

<|endoftext|>


<commit_before>AliPHOSCorrelationsTest* AddTaskPi0Correlations (   	const char* name = "Pi0Corr",
						const char* options = "11h",
						UInt_t offlineTriggerMask = AliVEvent::kCentral,
						AliPHOSCorrelationsTest::TriggerSelection internalTriggerSelection = AliPHOSCorrelationsTest::kNoSelection,
						Double_t sigmaWidth = 3.,
						Int_t downCentLimit = 0,
						Int_t upCentLimit = 90 )
{
	//Author: Ponomarenko Daniil (Daniil.Ponomarenko@cern.ch)
	/* $Id$ */

	AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
	if (!mgr)
	{
		::Error("AddTaskPi0CorrelationsL", "No analysis manager to connect to");
		return NULL;
	}

	if (!mgr->GetInputEventHandler())
	{
		::Error("AddTaskPi0CorrelationsL", "This task requires an input event handler");
		return NULL;
	}

	stringstream ss;
	ss << downCentLimit;
	string strDownCentLimit = ss.str();
	char text[255];
	sprintf(text,"%2i",upCentLimit);
	string strUpCentLimit = text;
	TString centralityBorder = TString ("CB") + strDownCentLimit.c_str() + TString ("t") + strUpCentLimit.c_str() + TString ("Cnt");
	TString sigmaBorder = Form("%2iSigma", int(sigmaWidth*10.));
	if (sigmaWidth == 0) sigmaBorder = "00Sigma";
	TString sName = TString (name) + sigmaBorder + centralityBorder ;

	AliPHOSCorrelationsTest* task = new AliPHOSCorrelationsTest(Form("%sTask", sName.Data()),internalTriggerSelection);

	if( TString(options).Contains("10h") )	{
		task->SetPeriod( AliPHOSCorrelationsTest::kLHC10h );
		task->SetCentralityEstimator("V0M");
	}
	if( TString(options).Contains("11h") )	{
		task->SetPeriod( AliPHOSCorrelationsTest::kLHC11h );
		task->SetCentralityEstimator("V0M");
	}
	if( TString(options).Contains("13") )	{
		task->SetPeriod( AliPHOSCorrelationsTest::kLHC13 );
		task->SetCentralityEstimator("V0A");
	}

	// Binning
	// TODO: Make other binning for 0-10% and 20-50%
	//Any:
	if( AliVEvent::kAny == offlineTriggerMask )
	{
		const int nbins = 8;
		Double_t cbin[nbins+1] = {0., 10., 20., 30., 40., 50., 60., 70., 80.};
		TArrayD tbin(nbins+1, cbin);
		Int_t    nMixed[nbins] = {6, 40, 40, 40, 40, 80, 80, 80};
		TArrayI tNMixed(nbins, nMixed);
		task->SetCentralityBinning(tbin, tNMixed);
	}
	//Central:
	if( AliVEvent::kCentral == offlineTriggerMask )
	{
		const int nbins = 4;
		Double_t cbin[nbins+1] = {0., 5., 8., 9., 10.};
		TArrayD tbin(nbins+1, cbin);
		Int_t    nMixed[nbins] = {6, 6, 6, 6};
		TArrayI tNMixed(nbins, nMixed);
		task->SetCentralityBinning(tbin, tNMixed);
	}
	// SemiCentral:
	if( AliVEvent::kSemiCentral == offlineTriggerMask )
	{
		const int nbins = 8;
		Double_t cbin[nbins+1] = {10., 11., 12., 13., 15., 20., 30., 40., 50.};
		TArrayD tbin(nbins+1, cbin);
		Int_t    nMixed[nbins] = {40, 40, 40, 40, 40, 40, 40, 40};
		TArrayI tNMixed(nbins, nMixed);
		task->SetCentralityBinning(tbin, tNMixed);
	}
	//INT7:
	if( AliVEvent::kINT7 == offlineTriggerMask || AliVEvent::kPHI7 == offlineTriggerMask)
	{
		const int nbins = 8;
		Double_t cbin[nbins+1] = {0., 10., 20., 30., 40., 50., 60., 70., 80.};
		TArrayD tbin(nbins+1, cbin);
		Int_t    nMixed[nbins] = {6, 40, 40, 40, 40, 80, 80, 80};
		TArrayI tNMixed(nbins, nMixed);
		task->SetCentralityBinning(tbin, tNMixed);
	}
	// MB or PHOS Trigger:
	if( AliVEvent::kMB == offlineTriggerMask || AliVEvent::kPHOSPb == offlineTriggerMask )
	{
		const int nbins = 8;
		Double_t cbin[nbins+1] = {0., 10., 20., 30., 40., 50., 60., 70., 80.};
		TArrayD tbin(nbins+1, cbin);
		Int_t    nMixed[nbins] = {6, 40, 40, 40, 40, 80, 80, 80};
		TArrayI tNMixed(nbins, nMixed);
		task->SetCentralityBinning(tbin, tNMixed);
	}

	task->SelectCollisionCandidates(offlineTriggerMask);
	task->SetInternalTriggerSelection(internalTriggerSelection);
	task->EnableTOFCut(true, 100.e-9);
	task->SetCentralityBorders(downCentLimit , upCentLimit) ;
	task->SetSigmaWidth(sigmaWidth);

	mgr->AddTask(task);
	mgr->ConnectInput(task, 0, mgr->GetCommonInputContainer() );

	TString cname(Form("%sCoutput1", sName.Data()));
	TString pname(Form("%s:%s", AliAnalysisManager::GetCommonFileName(), sName.Data()));
	AliAnalysisDataContainer *coutput1 = mgr->CreateContainer(cname.Data(), TList::Class(), AliAnalysisManager::kOutputContainer, pname.Data());
	mgr->ConnectOutput(task, 1, coutput1);

	return task;
}

<commit_msg>Class name fixed<commit_after>AliPHOSCorrelations* AddTaskPi0Correlations (   	const char* name = "Pi0Corr",
						const char* options = "11h",
						UInt_t offlineTriggerMask = AliVEvent::kCentral,
						AliPHOSCorrelations::TriggerSelection internalTriggerSelection = AliPHOSCorrelations::kNoSelection,
						Double_t sigmaWidth = 3.,
						Int_t downCentLimit = 0,
						Int_t upCentLimit = 90 )
{
	//Author: Ponomarenko Daniil (Daniil.Ponomarenko@cern.ch)
	/* $Id$ */

	AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
	if (!mgr)
	{
		::Error("AddTaskPi0CorrelationsL", "No analysis manager to connect to");
		return NULL;
	}

	if (!mgr->GetInputEventHandler())
	{
		::Error("AddTaskPi0CorrelationsL", "This task requires an input event handler");
		return NULL;
	}

	stringstream ss;
	ss << downCentLimit;
	string strDownCentLimit = ss.str();
	char text[255];
	sprintf(text,"%2i",upCentLimit);
	string strUpCentLimit = text;
	TString centralityBorder = TString ("CB") + strDownCentLimit.c_str() + TString ("t") + strUpCentLimit.c_str() + TString ("Cnt");
	TString sigmaBorder = Form("%2iSigma", int(sigmaWidth*10.));
	if (sigmaWidth == 0) sigmaBorder = "00Sigma";
	TString sName = TString (name) + sigmaBorder + centralityBorder ;

	AliPHOSCorrelations* task = new AliPHOSCorrelations(Form("%sTask", sName.Data()),internalTriggerSelection);

	if( TString(options).Contains("10h") )	{
		task->SetPeriod( AliPHOSCorrelations::kLHC10h );
		task->SetCentralityEstimator("V0M");
	}
	if( TString(options).Contains("11h") )	{
		task->SetPeriod( AliPHOSCorrelations::kLHC11h );
		task->SetCentralityEstimator("V0M");
	}
	if( TString(options).Contains("13") )	{
		task->SetPeriod( AliPHOSCorrelations::kLHC13 );
		task->SetCentralityEstimator("V0A");
	}

	// Binning
	// TODO: Make other binning for 0-10% and 20-50%
	//Any:
	if( AliVEvent::kAny == offlineTriggerMask )
	{
		const int nbins = 8;
		Double_t cbin[nbins+1] = {0., 10., 20., 30., 40., 50., 60., 70., 80.};
		TArrayD tbin(nbins+1, cbin);
		Int_t    nMixed[nbins] = {6, 40, 40, 40, 40, 80, 80, 80};
		TArrayI tNMixed(nbins, nMixed);
		task->SetCentralityBinning(tbin, tNMixed);
	}
	//Central:
	if( AliVEvent::kCentral == offlineTriggerMask )
	{
		const int nbins = 4;
		Double_t cbin[nbins+1] = {0., 5., 8., 9., 10.};
		TArrayD tbin(nbins+1, cbin);
		Int_t    nMixed[nbins] = {6, 6, 6, 6};
		TArrayI tNMixed(nbins, nMixed);
		task->SetCentralityBinning(tbin, tNMixed);
	}
	// SemiCentral:
	if( AliVEvent::kSemiCentral == offlineTriggerMask )
	{
		const int nbins = 8;
		Double_t cbin[nbins+1] = {10., 11., 12., 13., 15., 20., 30., 40., 50.};
		TArrayD tbin(nbins+1, cbin);
		Int_t    nMixed[nbins] = {40, 40, 40, 40, 40, 40, 40, 40};
		TArrayI tNMixed(nbins, nMixed);
		task->SetCentralityBinning(tbin, tNMixed);
	}
	//INT7:
	if( AliVEvent::kINT7 == offlineTriggerMask || AliVEvent::kPHI7 == offlineTriggerMask)
	{
		const int nbins = 8;
		Double_t cbin[nbins+1] = {0., 10., 20., 30., 40., 50., 60., 70., 80.};
		TArrayD tbin(nbins+1, cbin);
		Int_t    nMixed[nbins] = {6, 40, 40, 40, 40, 80, 80, 80};
		TArrayI tNMixed(nbins, nMixed);
		task->SetCentralityBinning(tbin, tNMixed);
	}
	// MB or PHOS Trigger:
	if( AliVEvent::kMB == offlineTriggerMask || AliVEvent::kPHOSPb == offlineTriggerMask )
	{
		const int nbins = 8;
		Double_t cbin[nbins+1] = {0., 10., 20., 30., 40., 50., 60., 70., 80.};
		TArrayD tbin(nbins+1, cbin);
		Int_t    nMixed[nbins] = {6, 40, 40, 40, 40, 80, 80, 80};
		TArrayI tNMixed(nbins, nMixed);
		task->SetCentralityBinning(tbin, tNMixed);
	}

	task->SelectCollisionCandidates(offlineTriggerMask);
	task->SetInternalTriggerSelection(internalTriggerSelection);
	task->EnableTOFCut(true, 100.e-9);
	task->SetCentralityBorders(downCentLimit , upCentLimit) ;
	task->SetSigmaWidth(sigmaWidth);

	mgr->AddTask(task);
	mgr->ConnectInput(task, 0, mgr->GetCommonInputContainer() );

	TString cname(Form("%sCoutput1", sName.Data()));
	TString pname(Form("%s:%s", AliAnalysisManager::GetCommonFileName(), sName.Data()));
	AliAnalysisDataContainer *coutput1 = mgr->CreateContainer(cname.Data(), TList::Class(), AliAnalysisManager::kOutputContainer, pname.Data());
	mgr->ConnectOutput(task, 1, coutput1);

	return task;
}

<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "qmakekitinformation.h"

#include "qmakekitinformation.h"
#include "qmakekitconfigwidget.h"

#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/toolchainmanager.h>

#include <qtsupport/baseqtversion.h>
#include <qtsupport/qtkitinformation.h>

namespace Qt4ProjectManager {
namespace Internal {
const char MKSPEC_INFORMATION[] = "QtPM4.mkSpecInformation";
} // namespace Internal

QmakeKitInformation::QmakeKitInformation()
{
    setObjectName(QLatin1String("QmakeKitInformation"));
}

Core::Id QmakeKitInformation::dataId() const
{
    static Core::Id id = Core::Id(Internal::MKSPEC_INFORMATION);
    return id;
}

unsigned int QmakeKitInformation::priority() const
{
    return 24000;
}

QVariant QmakeKitInformation::defaultValue(ProjectExplorer::Kit *k) const
{
    Q_UNUSED(k);
    return QString();
}

QList<ProjectExplorer::Task> QmakeKitInformation::validate(const ProjectExplorer::Kit *k) const
{
    QList<ProjectExplorer::Task> result;
    QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(k);

    Utils::FileName mkspec = QmakeKitInformation::mkspec(k);
    if (!version && !mkspec.isEmpty())
        result << ProjectExplorer::Task(ProjectExplorer::Task::Warning,
                                        tr("No Qt version set, so mkspec is ignored."),
                                        Utils::FileName(), -1,
                                        Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
    if (version && !version->hasMkspec(mkspec))
        result << ProjectExplorer::Task(ProjectExplorer::Task::Error,
                                        tr("Mkspec not found for Qt version."),
                                        Utils::FileName(), -1,
                                        Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
    return result;
}

void QmakeKitInformation::setup(ProjectExplorer::Kit *k)
{
    QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(k);
    if (!version)
        return;

    Utils::FileName spec = QmakeKitInformation::mkspec(k);
    if (spec.isEmpty())
        spec = version->mkspec();

    ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(k);

    if (!tc || !tc->suggestedMkspecList().contains(spec)) {
        QList<ProjectExplorer::ToolChain *> tcList = ProjectExplorer::ToolChainManager::instance()->toolChains();
        foreach (ProjectExplorer::ToolChain *current, tcList) {
            if (version->qtAbis().contains(current->targetAbi())
                    && current->suggestedMkspecList().contains(spec)) {
                ProjectExplorer::ToolChainKitInformation::setToolChain(k, current);
                break;
            }
        }
    }
}

ProjectExplorer::KitConfigWidget *
QmakeKitInformation::createConfigWidget(ProjectExplorer::Kit *k) const
{
    return new Internal::QmakeKitConfigWidget(k);
}

ProjectExplorer::KitInformation::ItemList QmakeKitInformation::toUserOutput(ProjectExplorer::Kit *k) const
{
    return ItemList() << qMakePair(tr("mkspec"), mkspec(k).toUserOutput());
}

Utils::FileName QmakeKitInformation::mkspec(const ProjectExplorer::Kit *k)
{
    if (!k)
        return Utils::FileName();
    return Utils::FileName::fromString(k->value(Core::Id(Internal::MKSPEC_INFORMATION)).toString());
}

Utils::FileName QmakeKitInformation::effectiveMkspec(const ProjectExplorer::Kit *k)
{
    if (!k)
        return Utils::FileName();
    Utils::FileName spec = mkspec(k);
    if (spec.isEmpty())
        return defaultMkspec(k);
    return spec;
}

void QmakeKitInformation::setMkspec(ProjectExplorer::Kit *k, const Utils::FileName &fn)
{
    if (fn == defaultMkspec(k))
        k->setValue(Core::Id(Internal::MKSPEC_INFORMATION), QString());
    else
        k->setValue(Core::Id(Internal::MKSPEC_INFORMATION), fn.toString());
}

Utils::FileName QmakeKitInformation::defaultMkspec(const ProjectExplorer::Kit *k)
{
    QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(k);
    if (!version) // No version, so no qmake
        return Utils::FileName();

    return version->mkspecFor(ProjectExplorer::ToolChainKitInformation::toolChain(k));
}

} // namespace Qt4ProjectManager
<commit_msg>Improve selection of compiler when creating desktop kit<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "qmakekitinformation.h"

#include "qmakekitinformation.h"
#include "qmakekitconfigwidget.h"

#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/toolchainmanager.h>

#include <qtsupport/baseqtversion.h>
#include <qtsupport/qtkitinformation.h>

namespace Qt4ProjectManager {
namespace Internal {
const char MKSPEC_INFORMATION[] = "QtPM4.mkSpecInformation";
} // namespace Internal

QmakeKitInformation::QmakeKitInformation()
{
    setObjectName(QLatin1String("QmakeKitInformation"));
}

Core::Id QmakeKitInformation::dataId() const
{
    static Core::Id id = Core::Id(Internal::MKSPEC_INFORMATION);
    return id;
}

unsigned int QmakeKitInformation::priority() const
{
    return 24000;
}

QVariant QmakeKitInformation::defaultValue(ProjectExplorer::Kit *k) const
{
    Q_UNUSED(k);
    return QString();
}

QList<ProjectExplorer::Task> QmakeKitInformation::validate(const ProjectExplorer::Kit *k) const
{
    QList<ProjectExplorer::Task> result;
    QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(k);

    Utils::FileName mkspec = QmakeKitInformation::mkspec(k);
    if (!version && !mkspec.isEmpty())
        result << ProjectExplorer::Task(ProjectExplorer::Task::Warning,
                                        tr("No Qt version set, so mkspec is ignored."),
                                        Utils::FileName(), -1,
                                        Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
    if (version && !version->hasMkspec(mkspec))
        result << ProjectExplorer::Task(ProjectExplorer::Task::Error,
                                        tr("Mkspec not found for Qt version."),
                                        Utils::FileName(), -1,
                                        Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
    return result;
}

void QmakeKitInformation::setup(ProjectExplorer::Kit *k)
{
    QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(k);
    if (!version)
        return;

    Utils::FileName spec = QmakeKitInformation::mkspec(k);
    if (spec.isEmpty())
        spec = version->mkspec();

    ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(k);

    if (!tc || !tc->suggestedMkspecList().contains(spec)) {
        QList<ProjectExplorer::ToolChain *> tcList = ProjectExplorer::ToolChainManager::instance()->toolChains();
        ProjectExplorer::ToolChain *possibleTc = 0;
        foreach (ProjectExplorer::ToolChain *current, tcList) {
            if (version->qtAbis().contains(current->targetAbi())) {
                possibleTc = current;
                if (current->suggestedMkspecList().contains(spec))
                    break;
            }
        }
        ProjectExplorer::ToolChainKitInformation::setToolChain(k, possibleTc);
    }
}

ProjectExplorer::KitConfigWidget *
QmakeKitInformation::createConfigWidget(ProjectExplorer::Kit *k) const
{
    return new Internal::QmakeKitConfigWidget(k);
}

ProjectExplorer::KitInformation::ItemList QmakeKitInformation::toUserOutput(ProjectExplorer::Kit *k) const
{
    return ItemList() << qMakePair(tr("mkspec"), mkspec(k).toUserOutput());
}

Utils::FileName QmakeKitInformation::mkspec(const ProjectExplorer::Kit *k)
{
    if (!k)
        return Utils::FileName();
    return Utils::FileName::fromString(k->value(Core::Id(Internal::MKSPEC_INFORMATION)).toString());
}

Utils::FileName QmakeKitInformation::effectiveMkspec(const ProjectExplorer::Kit *k)
{
    if (!k)
        return Utils::FileName();
    Utils::FileName spec = mkspec(k);
    if (spec.isEmpty())
        return defaultMkspec(k);
    return spec;
}

void QmakeKitInformation::setMkspec(ProjectExplorer::Kit *k, const Utils::FileName &fn)
{
    if (fn == defaultMkspec(k))
        k->setValue(Core::Id(Internal::MKSPEC_INFORMATION), QString());
    else
        k->setValue(Core::Id(Internal::MKSPEC_INFORMATION), fn.toString());
}

Utils::FileName QmakeKitInformation::defaultMkspec(const ProjectExplorer::Kit *k)
{
    QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(k);
    if (!version) // No version, so no qmake
        return Utils::FileName();

    return version->mkspecFor(ProjectExplorer::ToolChainKitInformation::toolChain(k));
}

} // namespace Qt4ProjectManager
<|endoftext|>


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

#include <unistd.h>
#include <chrono>
#include <iostream>
#include <string>
#include <thread>
#include <vector>
#include "src/core/request_inprocess.h"

namespace ni = nvidia::inferenceserver;
namespace nic = nvidia::inferenceserver::client;

#define FAIL_IF_ERR(X, MSG)                                        \
  do {                                                             \
    nic::Error err = (X);                                          \
    if (!err.IsOk()) {                                             \
      std::cerr << "error: " << (MSG) << ": " << err << std::endl; \
      exit(1);                                                     \
    }                                                              \
  } while (false)

namespace {

void
Usage(char** argv, const std::string& msg = std::string())
{
  if (!msg.empty()) {
    std::cerr << "error: " << msg << std::endl;
  }

  std::cerr << "Usage: " << argv[0] << " [options]" << std::endl;
  std::cerr << "\t-v" << std::endl;
  std::cerr << "\t-r [model repository absolute path]" << std::endl;

  exit(1);
}

}  // namespace

int
main(int argc, char** argv)
{
  bool verbose = false;
  std::string model_repository_path;

  // Parse commandline...
  int opt;
  while ((opt = getopt(argc, argv, "vr:")) != -1) {
    switch (opt) {
      case 'v':
        verbose = true;
        break;
      case 'r':
        model_repository_path = optarg;
        break;
      case '?':
        Usage(argv);
        break;
    }
  }

  if (model_repository_path.empty()) {
    Usage(argv, "-r must be used to specify model repository path");
  }

  // Set the options for inference server and then create the
  // inference server object.
  std::unique_ptr<nic::InferenceServerContext::Options> server_options;
  FAIL_IF_ERR(
      nic::InferenceServerContext::Options::Create(&server_options),
      "unable to create inference server options");
  server_options->SetModelRepositoryPath(model_repository_path);

  std::unique_ptr<nic::InferenceServerContext> server_ctx;
  FAIL_IF_ERR(
      nic::InferenceServerContext::Create(&server_ctx, server_options),
      "unable to create inference server context");

  // Wait until the server is both live and ready.
  std::unique_ptr<nic::ServerHealthContext> health_ctx;
  FAIL_IF_ERR(
      nic::ServerHealthInProcessContext::Create(
          &health_ctx, server_ctx, verbose),
      "unable to create health context");

  size_t health_iters = 0;
  while (true) {
    bool live, ready;
    FAIL_IF_ERR(health_ctx->GetLive(&live), "unable to get server liveness");
    FAIL_IF_ERR(health_ctx->GetReady(&ready), "unable to get server readiness");
    std::cout << "Server Health: live " << live << ", ready " << ready
              << std::endl;
    if (live && ready) {
      break;
    }

    if (++health_iters >= 10) {
      std::cerr << "failed to find healthy inference server" << std::endl;
      exit(1);
    }

    std::this_thread::sleep_for(std::chrono::milliseconds(500));
  }

  // Check status of the server.
  std::unique_ptr<nic::ServerStatusContext> status_ctx;
  FAIL_IF_ERR(
      nic::ServerStatusInProcessContext::Create(
          &status_ctx, server_ctx, verbose),
      "unable to create status context");

  ni::ServerStatus server_status;
  FAIL_IF_ERR(
      status_ctx->GetServerStatus(&server_status),
      "unable to get server status");
  std::cout << "Server Status:" << std::endl;
  std::cout << server_status.DebugString() << std::endl;

  // Create an inference context for the model.  We use a simple model
  // that takes 2 input tensors of 16 integers each and returns 2
  // output tensors of 16 integers each. One output tensor is the
  // element-wise sum of the inputs and one output is the element-wise
  // difference.
  const std::string model_name("simple");

  std::unique_ptr<nic::InferContext> infer_ctx;
  FAIL_IF_ERR(
      nic::InferInProcessContext::Create(
          &infer_ctx, server_ctx, model_name, -1 /* model_version */, verbose),
      "unable to create inference context");

  std::unique_ptr<nic::InferContext::Options> infer_options;
  FAIL_IF_ERR(
      nic::InferContext::Options::Create(&infer_options),
      "unable to create inference options");

  const size_t batch_size = 1;
  infer_options->SetBatchSize(batch_size);
  for (const auto& output : infer_ctx->Outputs()) {
    infer_options->AddRawResult(output);
  }

  FAIL_IF_ERR(
      infer_ctx->SetRunOptions(*infer_options),
      "unable to set inference options");

  // Create the data for the two input tensors. Initialize the first
  // to unique integers and the second to all ones.
  std::vector<int32_t> input0_data(16);
  std::vector<int32_t> input1_data(16);
  for (size_t i = 0; i < 16; ++i) {
    input0_data[i] = i;
    input1_data[i] = 1;
  }

  // Initialize the inputs with the data.
  std::shared_ptr<nic::InferContext::Input> input0, input1;
  FAIL_IF_ERR(infer_ctx->GetInput("INPUT0", &input0), "unable to get INPUT0");
  FAIL_IF_ERR(infer_ctx->GetInput("INPUT1", &input1), "unable to get INPUT1");

  FAIL_IF_ERR(input0->Reset(), "unable to reset INPUT0");
  FAIL_IF_ERR(input1->Reset(), "unable to reset INPUT1");

  FAIL_IF_ERR(
      input0->SetRaw(
          reinterpret_cast<uint8_t*>(&input0_data[0]),
          input0_data.size() * sizeof(int32_t)),
      "unable to set data for INPUT0");
  FAIL_IF_ERR(
      input1->SetRaw(
          reinterpret_cast<uint8_t*>(&input1_data[0]),
          input1_data.size() * sizeof(int32_t)),
      "unable to set data for INPUT1");

  std::map<std::string, std::unique_ptr<nic::InferContext::Result>> results;
  FAIL_IF_ERR(infer_ctx->Run(&results), "unable to run model");

  // We expect there to be 2 results. Walk over all 16 result elements
  // and print the sum and difference calculated by the model.
  if (results.size() != 2) {
    std::cerr << "error: expected 2 results, got " << results.size()
              << std::endl;
  }

  for (size_t i = 0; i < 16; ++i) {
    int32_t r0, r1;
    FAIL_IF_ERR(
        results["OUTPUT0"]->GetRawAtCursor(0 /* batch idx */, &r0),
        "unable to get OUTPUT0 result at idx " + std::to_string(i));
    FAIL_IF_ERR(
        results["OUTPUT1"]->GetRawAtCursor(0 /* batch idx */, &r1),
        "unable to get OUTPUT1 result at idx " + std::to_string(i));
    std::cout << input0_data[i] << " + " << input1_data[i] << " = " << r0
              << std::endl;
    std::cout << input0_data[i] << " - " << input1_data[i] << " = " << r1
              << std::endl;

    if ((input0_data[i] + input1_data[i]) != r0) {
      std::cerr << "error: incorrect sum" << std::endl;
      exit(1);
    }
    if ((input0_data[i] - input1_data[i]) != r1) {
      std::cerr << "error: incorrect difference" << std::endl;
      exit(1);
    }
  }

  return 0;
}
<commit_msg>Build simple_inprocess example at same time as trtserver<commit_after><|endoftext|>