<commit_before>/*
 * sd.cpp
 *
 * Application SD card functionality for Wind Data logger
 *
 * Matt Little/James Fowkes
 * August 2015
 */

/************ External Libraries*****************************/
#include <Arduino.h>
#include <Rtc_Pcf8563.h>
#include <SdFat.h>

/************ Application Libraries*****************************/

#include "app.h"
#include "utility.h"
#include "battery.h"
#include "external_volts_amps.h"
#include "wind.h"
#include "temperature.h"
#include "irradiance.h"
#include "rtc.h"
#include "sd.h"

/*
 * Defines
 */

#define SD_CHIP_SELECT_PIN 10 // The SD card Chip Select pin 10
#define SD_CARD_DETECT_PIN 9  // The SD card detect is on pin 6

#define DATA_STRING_LENGTH 128

/*
 * Private Variables
 */

static long s_dataCounter = 0;  // This holds the number of seconds since the last data store
static long s_sampleTime = 2;  // This is the time between samples for the DAQ

static volatile bool s_writePending = false;  // A flag to tell the code when to write data
static char s_last_used_date[16];

// The other SD card pins (D11,D12,D13) are all set within s_SD.h
static int s_lastCardDetect = LOW;  // This is the flag for the old reading of the card detect

// SD file system object and file
static SdFat s_sd;
static SdFile s_datafile;

static char s_dataString[DATA_STRING_LENGTH];
static FixedLengthAccumulator s_accumulator = FixedLengthAccumulator(NULL, 0);

static char s_filename[] = "DXXXXXX.csv";  // This is a holder for the full file name
static char s_deviceID[3]; // A buffer to hold the device ID

static char comma = ',';

// These are Char Strings - they are stored in program memory to save space in data memory
// These are a mixutre of error messages and serial printed information
// These MUST be in the same order as the fields are written to the CSV file!
const char s_pstr_headers[] PROGMEM = \
  "Ref, Date, Time, " \
  WINDSPEED_HEADERS \
  WIND_DIRECTION_HEADERS \
  TEMPERATURE_HEADERS \
  IRRADIANCE_HEADERS \
  EXTERNAL_VOLTS_HEADERS \
  EXTERNAL_AMPS_HEADERS \
  "Batt V";

const char s_pstr_initialised[] PROGMEM = "Init SD OK. Headers:";
const char s_pstr_not_initialised[] PROGMEM = "Init SD Failed";
const char s_pstr_noSD[] PROGMEM = "No SD card";
const char s_pstrerroropen[] PROGMEM = "Error open";
const char s_pstr_file_already_exists[] PROGMEM = "File already exists";

/*
 * Private Functions
 */

/*
 * writeDataString
 * Opens the current file for writing and appends the current data string
 */
static void writeDataString()
{
    s_datafile.open(s_filename, O_RDWR | O_CREAT | O_AT_END);    // Open the correct file
    // if the file is available, write to it:
    if (s_sd.exists(s_filename))
    {
      s_datafile.println(s_dataString);
      s_datafile.close();
      // print to the serial port too:
      Serial.println(s_dataString);
    }
    // if the file isn't open, pop up an error:
    else {
      if(APP_InDebugMode())
      {
        Serial.println(PStringToRAM(s_pstrerroropen));
      }
  }
}

/*

#define DATA_STRING_LENGTH 128
* Public Functions
 */

/*
 * SD_Setup
 * Initalises the SD card
 */
void SD_Setup()
{
    pinMode(SD_CARD_DETECT_PIN,INPUT);  // D9 is the SD card detect on pin 9.

  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
    pinMode(SD_CHIP_SELECT_PIN, OUTPUT);

  // Initialize the SD card at SPI_HALF_SPEED to avoid bus errors
  // We use SPI_HALF_SPEED here as I am using resistor level shifters.

  s_accumulator.attach(s_dataString, DATA_STRING_LENGTH);

  if (!s_sd.begin(SD_CHIP_SELECT_PIN, SPI_HALF_SPEED)) {
    if(APP_InDebugMode())
    {
      Serial.println(PStringToRAM(s_pstr_not_initialised));
    }
  // don't do anything more:
  // Want to turn on an ERROR LED here
  	return;
  }
  else
  {
  	if(APP_InDebugMode())
  	{
  		Serial.println(PStringToRAM(s_pstr_initialised));
      Serial.println(PStringToRAM(s_pstr_headers));
  	}
  }
}

/*
 * SD_SetDeviceID
 * Sets the local device ID (the ID gets written to datalogging file)
 */
void SD_SetDeviceID(char * id)
{
	s_deviceID[0] = id[0];
	s_deviceID[1] = id[1];
}

/*
 * SD_SetSampleTime
 * Changes the sample time
 */
void SD_SetSampleTime(long newSampleTime)
{
	s_sampleTime = newSampleTime;
}

/*
 * SD_CreateFileForToday
 * Creates a new file if one doesn't exist for current date.
 */
void SD_CreateFileForToday()
{
  // Check there is a file created with the date in the title
  // If it does then create a new one with the new name
  // The name is created from:
  // DMMDDYY.CSV, where YY is the year MM is the month, DD is the day
  // You must add on the '0' to convert to ASCII

	RTC_GetYYMMDDString(&s_filename[1]);

	if(APP_InDebugMode())
	{
		Serial.println(s_filename);
	}

	if(!s_sd.exists(s_filename))
	{
    // open the file for write at end like the Native SD library
		if (!s_datafile.open(s_filename, O_RDWR | O_CREAT | O_AT_END))
		{
      if(APP_InDebugMode())
      {
        Serial.println(PStringToRAM(s_pstrerroropen));
      }
		}
    // if the file opened okay, write to it and sync:
    s_datafile.println(PStringToRAM(s_pstr_headers));
		s_datafile.sync();
	}

	else
	{
    if(APP_InDebugMode())
    {
      Serial.println(PStringToRAM(s_pstr_file_already_exists));
    }
	}

}

/***************************************************
 *  Name:        SD_WriteIsPending
 *
 *  Returns:     Value of s_writePending
 *
 *  Parameters:  None.
 *
 *  Description: Returns TRUE if application should begin write procedure
 *
 ***************************************************/
 bool SD_WriteIsPending()
 {
  return s_writePending;
 }

/***************************************************
 *  Name:        SD_WriteIsPending
 *
 *  Returns:     None
 *
 *  Parameters:  None
 *
 *  Description: Forces the write pending flag to true
 *
 ***************************************************/
 void SD_ForcePendingWrite()
 {
  s_writePending = true;
 }

 void SD_WriteData()
 {
  const char * current_date;
  const char * current_time;

  // *********** WIND SPEED ******************************************
  // Want to get the number of pulses and average into the sample time
  // This gives us the average wind speed
  // pulsecounterold holds the value of pulses.
  // This can be converted into the wind speed using the time and
  // the pulse-wind speed characterisitic of the anemometer.
  // Do this as post processing - pulse count is most important.

  // *********** WIND DIRECTION **************************************
  // This can be checked every second and an average used
    // If this interrupt has happened then we want to write data to SD card:
  // Save the pulsecounter value (this will be stored to write to SD card)
  WIND_StoreWindPulseCounts();
  WIND_AnalyseWindDirection();

  // *********** TEMPERATURE *****************************************
  // Two versions of this - either with thermistor or I2C sensor (if connected)
  // Thermistor version
  // Get the temperature readings and store to variables

  BATT_UpdateBatteryVoltage();

    // *********** EXTERNAL VOLTAGE ***************************************
    // From Vcc-680k--46k-GND potential divider
  VA_UpdateExternalVoltage();

    // ********** EXTERNAL CURRENTS **************************************
    // Measured using a hall effect current sensor
    // Either using a ACS*** or a LEM HTFS 200-P
    // Comment out whichever you are not using

  VA_UpdateExternalCurrent();

    // ******** put this data into a file ********************************
    // ****** Check filename *********************************************
    // Each day we want to write a new file.
    // Compare date with previous stored date, every second
  current_date = RTC_GetDate(RTCC_DATE_WORLD);
  current_time = RTC_GetTime();

  if(strcmp(current_date, s_last_used_date) != 0)
  {
     // If date has changed then create a new file
     memcpy(s_last_used_date, current_date, 10);
     SD_CreateFileForToday();  // Create the corrct filename (from date)
  }

  s_accumulator.reset();
  s_accumulator.writeChar(s_deviceID[0]);
  s_accumulator.writeChar(s_deviceID[1]);
  s_accumulator.writeChar(comma);
  s_accumulator.writeString(current_date);
  s_accumulator.writeChar(comma);
  s_accumulator.writeString(current_time);

  #if READ_WINDSPEED == 1
  s_accumulator.writeChar(comma);
  WIND_WritePulseCountToBuffer(0, &s_accumulator);
  s_accumulator.writeChar(comma);
  WIND_WritePulseCountToBuffer(1, &s_accumulator);
  #endif

  #if READ_WIND_DIRECTION == 1
  s_accumulator.writeChar(comma);
  WIND_WriteDirectionToBuffer(&s_accumulator);
  #endif

  #if READ_TEMPERATURE == 1
  s_accumulator.writeChar(comma);
  TEMP_WriteTemperatureToBuffer(&s_accumulator);
  #endif

  #if READ_IRRADIANCE == 1
  s_accumulator.writeChar(comma);
  IRR_WriteIrradianceToBuffer(&s_accumulator);
  #endif

  #if READ_EXTERNAL_VOLTS == 1
  s_accumulator.writeChar(comma);
  VA_WriteExternalVoltageToBuffer(&s_accumulator);
  #endif

  #if READ_EXTERNAL_AMPS == 1
  s_accumulator.writeChar(comma);
  VA_WriteExternalCurrentToBuffer(&s_accumulator);
  #endif

  s_accumulator.writeChar(comma);
  BATT_WriteVoltageToBuffer(&s_accumulator);

  /*
  int index;
  s_dataString[index++] = s_deviceID[0];
  s_dataString[index++] = s_deviceID[1];
  s_dataString[index++] = comma;
  memcpy(&s_dataString[index], current_date, 10); index += 10; // Date is exactly 10 chars long
  s_dataString[index++] = comma;
  memcpy(&s_dataString[index], current_time, 8); index += 8; // Time is exactly 8 chars long
  s_dataString[index++] = comma;
  index += WIND_WritePulseCountToBuffer(0, &s_dataString[index]);
  s_dataString[index++] = comma;
  index += WIND_WritePulseCountToBuffer(1, &s_dataString[index]);
  s_dataString[index++] = comma;
  index += WIND_WriteDirectionToBuffer(&s_dataString[index]);
  s_dataString[index++] = comma;
  #if READ_TEMPERATURE == 1
  index += TEMP_WriteTemperatureToBuffer(&s_dataString[index]);
  s_dataString[index++] = comma;
  #endif
  index += BATT_WriteVoltageToBuffer(&s_dataString[index]);
  s_dataString[index++] = comma;
  index += VA_WriteExternalVoltageToBuffer(&s_dataString[index]);
  s_dataString[index++] = comma;
  index += VA_WriteExternalCurrentToBuffer(&s_dataString[index]);
  s_dataString[index++] = '\0';
  */

  // ************** Write it to the SD card *************
  // This depends upon the card detect.
  // If card is there then write to the file
  // If card has recently been inserted then initialise the card/filenames
  // If card is not there then flash LEDs

  if(digitalRead(SD_CARD_DETECT_PIN)==LOW&&s_lastCardDetect==HIGH)
  {
    delay(100);  // Wait for switch to settle down.
    // There was no card previously so re-initialise and re-check the filename
    SD_Setup();
    SD_CreateFileForToday();
  }
  if(digitalRead(SD_CARD_DETECT_PIN)==LOW&&s_lastCardDetect==LOW)
  {
      //Ensure that there is a card present)
      // We then write the data to the SD card here:
    writeDataString();
  }
  else
  {
     // print to the serial port too:
    Serial.println(PStringToRAM(s_pstr_noSD));
    Serial.println(s_dataString);
  }

    s_lastCardDetect = digitalRead(SD_CARD_DETECT_PIN);  // Store the old value of the card detect

    s_writePending = false;
}

/***************************************************
 *  Name:        SD_SecondTick
 *
 *  Returns:     Nothing.
 *
 *  Parameters:  None.
 *
 *  Description: To be called every second by the RTC library.
 *               Decides when to update the SD card data
 *
 ***************************************************/
void SD_SecondTick()
{
  s_dataCounter++;
  if ((s_writePending == false) && (s_dataCounter >= s_sampleTime))  // This stops us loosing data if a second is missed
  {
    // Reset the DataCounter
    s_dataCounter = 0;
    s_writePending = true;
  }
}

/***************************************************
 *  Name:        SD_ResetCounter
 *
 *  Returns:     Nothing.
 *
 *  Parameters:  None.
 *
 *  Description: Forces reset of the data storage counter
 *
 ***************************************************/
void SD_ResetCounter()
{
    s_dataCounter = 0;
}

/***************************************************
 *  Name:        SD_ResetCounter
 *
 *  Returns:     TRUE if SD card is present
 *
 *  Parameters:  None.
 *
 *  Description: Tests the card detect pin (LOW if card present)
 *
 ***************************************************/
bool SD_CardIsPresent()
{
  return digitalRead(SD_CARD_DETECT_PIN)==LOW;
}
<commit_msg>Moved selective field write to own function<commit_after>/*
 * sd.cpp
 *
 * Application SD card functionality for Wind Data logger
 *
 * Matt Little/James Fowkes
 * August 2015
 */

/************ External Libraries*****************************/
#include <Arduino.h>
#include <Rtc_Pcf8563.h>
#include <SdFat.h>

/************ Application Libraries*****************************/

#include "app.h"
#include "utility.h"
#include "battery.h"
#include "external_volts_amps.h"
#include "wind.h"
#include "temperature.h"
#include "irradiance.h"
#include "rtc.h"
#include "sd.h"

/*
 * Defines
 */

#define SD_CHIP_SELECT_PIN 10 // The SD card Chip Select pin 10
#define SD_CARD_DETECT_PIN 9  // The SD card detect is on pin 6

#define DATA_STRING_LENGTH 128

/*
 * Private Variables
 */

static long s_dataCounter = 0;  // This holds the number of seconds since the last data store
static long s_sampleTime = 2;  // This is the time between samples for the DAQ

static volatile bool s_writePending = false;  // A flag to tell the code when to write data
static char s_last_used_date[16];

// The other SD card pins (D11,D12,D13) are all set within s_SD.h
static int s_lastCardDetect = LOW;  // This is the flag for the old reading of the card detect

// SD file system object and file
static SdFat s_sd;
static SdFile s_datafile;

static char s_dataString[DATA_STRING_LENGTH];
static FixedLengthAccumulator s_accumulator = FixedLengthAccumulator(NULL, 0);

static char s_filename[] = "DXXXXXX.csv";  // This is a holder for the full file name
static char s_deviceID[3]; // A buffer to hold the device ID

static char comma = ',';

// These are Char Strings - they are stored in program memory to save space in data memory
// These are a mixutre of error messages and serial printed information
// These MUST be in the same order as the fields are written to the CSV file!
const char s_pstr_headers[] PROGMEM = \
  "Ref, Date, Time, " \
  WINDSPEED_HEADERS \
  WIND_DIRECTION_HEADERS \
  TEMPERATURE_HEADERS \
  IRRADIANCE_HEADERS \
  EXTERNAL_VOLTS_HEADERS \
  EXTERNAL_AMPS_HEADERS \
  "Batt V";

const char s_pstr_initialised[] PROGMEM = "Init SD OK. Headers:";
const char s_pstr_not_initialised[] PROGMEM = "Init SD Failed";
const char s_pstr_noSD[] PROGMEM = "No SD card";
const char s_pstrerroropen[] PROGMEM = "Error open";
const char s_pstr_file_already_exists[] PROGMEM = "File already exists";

/*
 * Private Functions
 */

static void write_configurable_fields(FixedLengthAccumulator * accum)
{
  #if READ_WINDSPEED == 1
  accum->writeChar(comma);
  WIND_WritePulseCountToBuffer(0, accum);
  accum->writeChar(comma);
  WIND_WritePulseCountToBuffer(1, accum);
  #endif

  #if READ_WIND_DIRECTION == 1
  accum->writeChar(comma);
  WIND_WriteDirectionToBuffer(accum);
  #endif

  #if READ_TEMPERATURE == 1
  accum->writeChar(comma);
  TEMP_WriteTemperatureToBuffer(accum);
  #endif

  #if READ_IRRADIANCE == 1
  accum->writeChar(comma);
  IRR_WriteIrradianceToBuffer(accum);
  #endif

  #if READ_EXTERNAL_VOLTS == 1
  accum->writeChar(comma);
  VA_WriteExternalVoltageToBuffer(accum);
  #endif

  #if READ_EXTERNAL_AMPS == 1
  accum->writeChar(comma);
  VA_WriteExternalCurrentToBuffer(accum);
  #endif
}

/*
 * writeDataString
 * Opens the current file for writing and appends the current data string
 */
static void writeDataString()
{
    s_datafile.open(s_filename, O_RDWR | O_CREAT | O_AT_END);    // Open the correct file
    // if the file is available, write to it:
    if (s_sd.exists(s_filename))
    {
      s_datafile.println(s_dataString);
      s_datafile.close();
      // print to the serial port too:
      Serial.println(s_dataString);
    }
    // if the file isn't open, pop up an error:
    else {
      if(APP_InDebugMode())
      {
        Serial.println(PStringToRAM(s_pstrerroropen));
      }
  }
}

/*

#define DATA_STRING_LENGTH 128
* Public Functions
 */

/*
 * SD_Setup
 * Initalises the SD card
 */
void SD_Setup()
{
    pinMode(SD_CARD_DETECT_PIN,INPUT);  // D9 is the SD card detect on pin 9.

  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
    pinMode(SD_CHIP_SELECT_PIN, OUTPUT);

  // Initialize the SD card at SPI_HALF_SPEED to avoid bus errors
  // We use SPI_HALF_SPEED here as I am using resistor level shifters.

  s_accumulator.attach(s_dataString, DATA_STRING_LENGTH);

  if (!s_sd.begin(SD_CHIP_SELECT_PIN, SPI_HALF_SPEED)) {
    if(APP_InDebugMode())
    {
      Serial.println(PStringToRAM(s_pstr_not_initialised));
    }
  // don't do anything more:
  // Want to turn on an ERROR LED here
  	return;
  }
  else
  {
  	if(APP_InDebugMode())
  	{
  		Serial.println(PStringToRAM(s_pstr_initialised));
      Serial.println(PStringToRAM(s_pstr_headers));
  	}
  }
}

/*
 * SD_SetDeviceID
 * Sets the local device ID (the ID gets written to datalogging file)
 */
void SD_SetDeviceID(char * id)
{
	s_deviceID[0] = id[0];
	s_deviceID[1] = id[1];
}

/*
 * SD_SetSampleTime
 * Changes the sample time
 */
void SD_SetSampleTime(long newSampleTime)
{
	s_sampleTime = newSampleTime;
}

/*
 * SD_CreateFileForToday
 * Creates a new file if one doesn't exist for current date.
 */
void SD_CreateFileForToday()
{
  // Check there is a file created with the date in the title
  // If it does then create a new one with the new name
  // The name is created from:
  // DMMDDYY.CSV, where YY is the year MM is the month, DD is the day
  // You must add on the '0' to convert to ASCII

	RTC_GetYYMMDDString(&s_filename[1]);

	if(APP_InDebugMode())
	{
		Serial.println(s_filename);
	}

	if(!s_sd.exists(s_filename))
	{
    // open the file for write at end like the Native SD library
		if (!s_datafile.open(s_filename, O_RDWR | O_CREAT | O_AT_END))
		{
      if(APP_InDebugMode())
      {
        Serial.println(PStringToRAM(s_pstrerroropen));
      }
		}
    // if the file opened okay, write to it and sync:
    s_datafile.println(PStringToRAM(s_pstr_headers));
		s_datafile.sync();
	}

	else
	{
    if(APP_InDebugMode())
    {
      Serial.println(PStringToRAM(s_pstr_file_already_exists));
    }
	}

}

/***************************************************
 *  Name:        SD_WriteIsPending
 *
 *  Returns:     Value of s_writePending
 *
 *  Parameters:  None.
 *
 *  Description: Returns TRUE if application should begin write procedure
 *
 ***************************************************/
 bool SD_WriteIsPending()
 {
  return s_writePending;
 }

/***************************************************
 *  Name:        SD_WriteIsPending
 *
 *  Returns:     None
 *
 *  Parameters:  None
 *
 *  Description: Forces the write pending flag to true
 *
 ***************************************************/
 void SD_ForcePendingWrite()
 {
  s_writePending = true;
 }

 void SD_WriteData()
 {
  const char * current_date;
  const char * current_time;

  // *********** WIND SPEED ******************************************
  // Want to get the number of pulses and average into the sample time
  // This gives us the average wind speed
  // pulsecounterold holds the value of pulses.
  // This can be converted into the wind speed using the time and
  // the pulse-wind speed characterisitic of the anemometer.
  // Do this as post processing - pulse count is most important.

  // *********** WIND DIRECTION **************************************
  // This can be checked every second and an average used
    // If this interrupt has happened then we want to write data to SD card:
  // Save the pulsecounter value (this will be stored to write to SD card)
  WIND_StoreWindPulseCounts();
  WIND_AnalyseWindDirection();

  // *********** TEMPERATURE *****************************************
  // Two versions of this - either with thermistor or I2C sensor (if connected)
  // Thermistor version
  // Get the temperature readings and store to variables

  BATT_UpdateBatteryVoltage();

    // *********** EXTERNAL VOLTAGE ***************************************
    // From Vcc-680k--46k-GND potential divider
  VA_UpdateExternalVoltage();

    // ********** EXTERNAL CURRENTS **************************************
    // Measured using a hall effect current sensor
    // Either using a ACS*** or a LEM HTFS 200-P
    // Comment out whichever you are not using

  VA_UpdateExternalCurrent();

    // ******** put this data into a file ********************************
    // ****** Check filename *********************************************
    // Each day we want to write a new file.
    // Compare date with previous stored date, every second
  current_date = RTC_GetDate(RTCC_DATE_WORLD);
  current_time = RTC_GetTime();

  if(strcmp(current_date, s_last_used_date) != 0)
  {
     // If date has changed then create a new file
     memcpy(s_last_used_date, current_date, 10);
     SD_CreateFileForToday();  // Create the corrct filename (from date)
  }

  s_accumulator.reset();
  s_accumulator.writeChar(s_deviceID[0]);
  s_accumulator.writeChar(s_deviceID[1]);
  s_accumulator.writeChar(comma);
  s_accumulator.writeString(current_date);
  s_accumulator.writeChar(comma);
  s_accumulator.writeString(current_time);

  write_configurable_fields(&s_accumulator);

  s_accumulator.writeChar(comma);
  BATT_WriteVoltageToBuffer(&s_accumulator);

  // ************** Write it to the SD card *************
  // This depends upon the card detect.
  // If card is there then write to the file
  // If card has recently been inserted then initialise the card/filenames
  // If card is not there then flash LEDs

  if(digitalRead(SD_CARD_DETECT_PIN)==LOW&&s_lastCardDetect==HIGH)
  {
    delay(100);  // Wait for switch to settle down.
    // There was no card previously so re-initialise and re-check the filename
    SD_Setup();
    SD_CreateFileForToday();
  }
  if(digitalRead(SD_CARD_DETECT_PIN)==LOW&&s_lastCardDetect==LOW)
  {
      //Ensure that there is a card present)
      // We then write the data to the SD card here:
    writeDataString();
  }
  else
  {
     // print to the serial port too:
    Serial.println(PStringToRAM(s_pstr_noSD));
    Serial.println(s_dataString);
  }

    s_lastCardDetect = digitalRead(SD_CARD_DETECT_PIN);  // Store the old value of the card detect

    s_writePending = false;
}

/***************************************************
 *  Name:        SD_SecondTick
 *
 *  Returns:     Nothing.
 *
 *  Parameters:  None.
 *
 *  Description: To be called every second by the RTC library.
 *               Decides when to update the SD card data
 *
 ***************************************************/
void SD_SecondTick()
{
  s_dataCounter++;
  if ((s_writePending == false) && (s_dataCounter >= s_sampleTime))  // This stops us loosing data if a second is missed
  {
    // Reset the DataCounter
    s_dataCounter = 0;
    s_writePending = true;
  }
}

/***************************************************
 *  Name:        SD_ResetCounter
 *
 *  Returns:     Nothing.
 *
 *  Parameters:  None.
 *
 *  Description: Forces reset of the data storage counter
 *
 ***************************************************/
void SD_ResetCounter()
{
    s_dataCounter = 0;
}

/***************************************************
 *  Name:        SD_ResetCounter
 *
 *  Returns:     TRUE if SD card is present
 *
 *  Parameters:  None.
 *
 *  Description: Tests the card detect pin (LOW if card present)
 *
 ***************************************************/
bool SD_CardIsPresent()
{
  return digitalRead(SD_CARD_DETECT_PIN)==LOW;
}
<|endoftext|>


<commit_before>#include <ros/package.h>
#include <cv_bridge/cv_bridge.h>
#include <boost/shared_ptr.hpp>
#include <boost/filesystem.hpp>
#include <opencv2/opencv.hpp>

#include "opencv_utils.h"
#include "template_pose.h"

/** \brief Parameter constructor. Sets the parameter struct to default values.
  */
template_pose::TemplatePose::Params::Params() :
  queue_size(DEFAULT_QUEUE_SIZE),
  desc_threshold(DEFAULT_DESC_THRESHOLD),
  min_matches(DEFAULT_MIN_MATCHES),
  min_inliers(DEFAULT_MIN_INLIERS),
  desc_type("SIFT"),
  bucket_width(DEFAULT_BUCKET_WIDTH),
  bucket_height(DEFAULT_BUCKET_HEIGHT),
  max_bucket_features(DEFAULT_MAX_BUCKET_FEATURES),
  template_width(DEFAULT_TEMPLATE_WIDTH),
  template_height(DEFAULT_TEMPLATE_HEIGHT)
{}

/** \brief Class constructor. Reads node parameters and initialize some properties.
  * \param nh public node handler
  * \param nhp private node handler
  */
template_pose::TemplatePose::TemplatePose(
  ros::NodeHandle nh, ros::NodeHandle nhp) : nh_(nh), nhp_(nhp)
{
  // Read the node parameters
  readParameters();

  // Initialize the stereo slam
  initialize();
}

/** \brief Messages callback. This function is called when synchronized image
  * messages are received.
  * @return
  * \param l_img ros image message of type sensor_msgs::Image
  * \param l_info ros info image message of type sensor_msgs::CameraInfo
  */
void template_pose::TemplatePose::msgsCallback(
                                  const sensor_msgs::ImageConstPtr& img,
                                  const sensor_msgs::CameraInfoConstPtr& img_info)
{

  // Check if service is called or not
  if (listen_services_ && !(do_detection_ || toggle_detection_))
  {
    ROS_INFO("[TemplatePose:] Waiting for start service...");
    return;
  }

  // Convert image message to Mat
  cv_bridge::CvImagePtr img_ptr;
  try
  {
    img_ptr = cv_bridge::toCvCopy(img, enc::BGR8);
  }
  catch (cv_bridge::Exception& e)
  {
    ROS_ERROR("[TemplatePose:] cv_bridge exception: %s", e.what());
    return;
  }

  if(first_iter_)
  {
    // Initialize camera matrix
    const Mat P(3,4, CV_64FC1, const_cast<double*>(img_info->P.data()));
    camera_matrix_ = P.colRange(Range(0,3)).clone();

    // Do not repeat
    first_iter_ = false;
  }

  // Set the images
  img_prop_.setImg(img_ptr->image);

  // Estimate the transform
  tf::Transform est_tf;
  if(estimateTransform(est_tf))
    camera_to_template_ = est_tf;
  else
    ROS_INFO("[TemplatePose:] No transform found.");

  // Publish the transform
  tf_broadcaster_.sendTransform(
    tf::StampedTransform(camera_to_template_, img->header.stamp,
    params_.frame_id, params_.template_frame_id));

  // Log
  double x, y, z, roll, pitch, yaw;
  camera_to_template_.getBasis().getRPY(roll, pitch, yaw);
  x = camera_to_template_.getOrigin().x();
  y = camera_to_template_.getOrigin().y();
  z = camera_to_template_.getOrigin().z();
  ROS_INFO_STREAM("[TemplatePose:] Camera to template image:" <<
                  " [" << x << ", " << y << ", " << z <<
                  ", " << roll*180/M_PI << ", " << pitch*180/M_PI <<
                  ", " << yaw*180/M_PI << "]");

  toggle_detection_ = false;
}

/** \brief Reads the stereo slam node parameters
  */
void template_pose::TemplatePose::readParameters()
{
  Params params;

  // General parameters
  nhp_.param("queue_size", params.queue_size, 2);
  nhp_.param("desc_threshold", params.desc_threshold, 0.8);
  nhp_.param("min_matches", params.min_matches, 40);
  nhp_.param("min_inliers", params.min_inliers, 20);
  nhp_.param("template_image_name", params.template_image_name, std::string("template.png"));
  nhp_.param("frame_id", params.frame_id, std::string("/camera"));
  nhp_.param("template_frame_id", params.template_frame_id, std::string("/template_image"));
  nhp_.param("desc_type", params.desc_type, std::string("SIFT"));
  nhp_.param("bucket_width", params.bucket_width, 30);
  nhp_.param("bucket_height", params.bucket_height, 30);
  nhp_.param("max_bucket_features", params.max_bucket_features, 10);
  nhp_.param("template_width", params.template_width, 0.5);
  nhp_.param("template_height", params.template_height, 0.16);

  // Set stereo slam parameters
  setParams(params);

  // Topics subscriptions
  string image_topic, image_info_topic;
  nhp_.param("image_topic", image_topic, string("/left/image_rect_color"));
  nhp_.param("image_info_topic", image_info_topic, string("/left/camera_info"));
  image_transport::ImageTransport it(nh_);
  image_sub_.subscribe(it, image_topic, 1);
  info_sub_.subscribe(nh_, image_info_topic, 1);

  // Services to start or stop the template detection
  nhp_.param("listen_services", listen_services_, false);
  detect_service_ = nhp_.advertiseService("detect", &TemplatePose::detectSrv, this);
  start_service_ = nhp_.advertiseService("start_detection", &TemplatePose::startDetectionSrv, this);
  stop_service_ = nhp_.advertiseService("stop_detection", &TemplatePose::stopDetectionSrv, this);

  // Advertise the image matches publisher
  matches_image_pub_ = nhp_.advertise<sensor_msgs::Image>("matches", 1);
}

/** \brief Initializes the template pose class
  * @return true if all ok
  */
bool template_pose::TemplatePose::initialize()
{
  // Initialize parameters
  first_iter_ = true;
  camera_to_template_.setIdentity();

  // Initialize service bool variables
  if (listen_services_)
    do_detection_ = false;
  else
    do_detection_ = true;

  // Check if template image exists
  string template_file = params_.template_image_name;
  if (!boost::filesystem::exists(template_file))
  {
    ROS_ERROR_STREAM("[TemplatePose:] The template image file does not exists: " <<
                     template_file);
    return false;
  }

  // Read the template image
  Mat img_temp = imread(template_file, CV_LOAD_IMAGE_COLOR);

  // Initialize image properties objects
  template_pose::ImageProperties::Params image_params;
  image_params.desc_type = params_.desc_type;
  image_params.bucket_width = params_.bucket_width;
  image_params.bucket_height = params_.bucket_height;
  image_params.max_bucket_features = params_.max_bucket_features;
  image_params.px_meter_x = (float)img_temp.cols / (float)params_.template_width;
  image_params.px_meter_y = (float)img_temp.rows / (float)params_.template_height;

  // Set the image properties
  template_prop_.setParams(image_params);
  img_prop_.setParams(image_params);

  // Compute template properties
  template_prop_.setImg(img_temp);
  template_prop_.compute3D();

  // Callback synchronization
  bool approx;
  nhp_.param("approximate_sync", approx, false);
  if (approx)
  {
    approximate_sync_.reset(new ApproximateSync(ApproximatePolicy(params_.queue_size),
                                    image_sub_,
                                    info_sub_) );
    approximate_sync_->registerCallback(boost::bind(
        &template_pose::TemplatePose::msgsCallback,
        this, _1, _2));
  }
  else
  {
    exact_sync_.reset(new ExactSync(ExactPolicy(params_.queue_size),
                                    image_sub_,
                                    info_sub_) );
    exact_sync_->registerCallback(boost::bind(
        &template_pose::TemplatePose::msgsCallback,
        this, _1, _2));
  }

  return true;
}

/** \brief Estimates the transform between the template and the stereo frame
  * @return true if all ok
  * \param - output tf transform
  */
bool template_pose::TemplatePose::estimateTransform(tf::Transform& output)
{
  // Initialize output
  output.setIdentity();

  // Crosscheck descriptors matching
  Mat desc_image = img_prop_.getDesc();
  Mat desc_template = template_prop_.getDesc();
  vector<DMatch> matches;
  Mat match_mask;
  template_pose::OpencvUtils::crossCheckThresholdMatching(desc_image,
  desc_template, params_.desc_threshold, match_mask, matches);

  // Publish matches
  if (matches_image_pub_.getNumSubscribers() > 0)
  {
    Mat img_matches;
    drawMatches(img_prop_.getImg(),
                img_prop_.getKp(),
                template_prop_.getImg(),
                template_prop_.getKp(),
                matches, img_matches);

    cv_bridge::CvImage cv_image;
    cv_image.encoding = enc::BGR8;
    cv_image.image = img_matches;
    matches_image_pub_.publish(cv_image.toImageMsg());
  }

  ROS_INFO_STREAM("[TemplatePose:] Found " << matches.size() <<
   " matches (min_matches is: " << params_.min_matches << ")");

  // Sanity check
  if ((int)matches.size() < params_.min_matches)
    return false;

  // Extract keypoints and 3d points of vertex i and j
  vector<KeyPoint> kp_image = img_prop_.getKp();
  vector<Point3f> points3d_template = template_prop_.get3Dpoints();

  vector<Point2f> matched_keypoints;
  vector<Point3f> matched_3d_points;
  for (size_t i = 0; i < matches.size(); ++i)
  {
    int idx_image = matches[i].queryIdx;
    int idx_template = matches[i].trainIdx;
    matched_3d_points.push_back(points3d_template[idx_template]);
    matched_keypoints.push_back(kp_image[idx_image].pt);
  }

  // Compute the transformation between the vertices
  Mat rvec, tvec;
  vector<int> inliers;
  solvePnPRansac(matched_3d_points, matched_keypoints, camera_matrix_,
                 Mat(), rvec, tvec, false /* no extrinsic guess */,
                 100 /* iterations */, 4.0 /* reproj. error */,
                 params_.min_inliers /* min inliers */, inliers);

  ROS_INFO_STREAM("[TemplatePose:] Found " << inliers.size() <<
   " inliers (min_inliers is: " << params_.min_inliers << ")");

  // Sanity check
  if (static_cast<int>(inliers.size()) < params_.min_inliers)
    return false;

  // Ok, build the tf
  tf::Vector3 axis(rvec.at<double>(0, 0),
                   rvec.at<double>(1, 0),
                   rvec.at<double>(2, 0));
  double angle = cv::norm(rvec);
  tf::Quaternion quaternion(axis, angle);

  tf::Vector3 translation(tvec.at<double>(0, 0), tvec.at<double>(1, 0),
      tvec.at<double>(2, 0));

  output = tf::Transform(quaternion, translation);
  return true;
}

bool template_pose::TemplatePose::detectSrv(std_srvs::Empty::Request&, std_srvs::Empty::Response&)
{
  camera_to_template_.setIdentity();
  do_detection_ = false;
  toggle_detection_ = true;
  ROS_INFO("[TemplatePose:] Service Detect requested.");
  return true;
}

bool template_pose::TemplatePose::startDetectionSrv(std_srvs::Empty::Request&, std_srvs::Empty::Response&)
{
  camera_to_template_.setIdentity();
  do_detection_ = true;
  ROS_INFO("[TemplatePose:] Service Start Detection requested.");
  return true;
}

bool template_pose::TemplatePose::stopDetectionSrv(std_srvs::Empty::Request&, std_srvs::Empty::Response&)
{
  do_detection_ = false;
  ROS_INFO("[TemplatePose:] Service Stop Detection requested.");
  return true;
}
<commit_msg>changed waiting message of services for a ONCE message type<commit_after>#include <ros/package.h>
#include <cv_bridge/cv_bridge.h>
#include <boost/shared_ptr.hpp>
#include <boost/filesystem.hpp>
#include <opencv2/opencv.hpp>

#include "opencv_utils.h"
#include "template_pose.h"

/** \brief Parameter constructor. Sets the parameter struct to default values.
  */
template_pose::TemplatePose::Params::Params() :
  queue_size(DEFAULT_QUEUE_SIZE),
  desc_threshold(DEFAULT_DESC_THRESHOLD),
  min_matches(DEFAULT_MIN_MATCHES),
  min_inliers(DEFAULT_MIN_INLIERS),
  desc_type("SIFT"),
  bucket_width(DEFAULT_BUCKET_WIDTH),
  bucket_height(DEFAULT_BUCKET_HEIGHT),
  max_bucket_features(DEFAULT_MAX_BUCKET_FEATURES),
  template_width(DEFAULT_TEMPLATE_WIDTH),
  template_height(DEFAULT_TEMPLATE_HEIGHT)
{}

/** \brief Class constructor. Reads node parameters and initialize some properties.
  * \param nh public node handler
  * \param nhp private node handler
  */
template_pose::TemplatePose::TemplatePose(
  ros::NodeHandle nh, ros::NodeHandle nhp) : nh_(nh), nhp_(nhp)
{
  // Read the node parameters
  readParameters();

  // Initialize the stereo slam
  initialize();
}

/** \brief Messages callback. This function is called when synchronized image
  * messages are received.
  * @return
  * \param l_img ros image message of type sensor_msgs::Image
  * \param l_info ros info image message of type sensor_msgs::CameraInfo
  */
void template_pose::TemplatePose::msgsCallback(
                                  const sensor_msgs::ImageConstPtr& img,
                                  const sensor_msgs::CameraInfoConstPtr& img_info)
{

  // Check if service is called or not
  if (listen_services_ && !(do_detection_ || toggle_detection_))
  {
    ROS_INFO_ONCE("[TemplatePose:] Waiting for start service...");
    return;
  }

  // Convert image message to Mat
  cv_bridge::CvImagePtr img_ptr;
  try
  {
    img_ptr = cv_bridge::toCvCopy(img, enc::BGR8);
  }
  catch (cv_bridge::Exception& e)
  {
    ROS_ERROR("[TemplatePose:] cv_bridge exception: %s", e.what());
    return;
  }

  if(first_iter_)
  {
    // Initialize camera matrix
    const Mat P(3,4, CV_64FC1, const_cast<double*>(img_info->P.data()));
    camera_matrix_ = P.colRange(Range(0,3)).clone();

    // Do not repeat
    first_iter_ = false;
  }

  // Set the images
  img_prop_.setImg(img_ptr->image);

  // Estimate the transform
  tf::Transform est_tf;
  if(estimateTransform(est_tf))
    camera_to_template_ = est_tf;
  else
    ROS_INFO("[TemplatePose:] No transform found.");

  // Publish the transform
  tf_broadcaster_.sendTransform(
    tf::StampedTransform(camera_to_template_, img->header.stamp,
    params_.frame_id, params_.template_frame_id));

  // Log
  double x, y, z, roll, pitch, yaw;
  camera_to_template_.getBasis().getRPY(roll, pitch, yaw);
  x = camera_to_template_.getOrigin().x();
  y = camera_to_template_.getOrigin().y();
  z = camera_to_template_.getOrigin().z();
  ROS_INFO_STREAM("[TemplatePose:] Camera to template image:" <<
                  " [" << x << ", " << y << ", " << z <<
                  ", " << roll*180/M_PI << ", " << pitch*180/M_PI <<
                  ", " << yaw*180/M_PI << "]");

  toggle_detection_ = false;
}

/** \brief Reads the stereo slam node parameters
  */
void template_pose::TemplatePose::readParameters()
{
  Params params;

  // General parameters
  nhp_.param("queue_size", params.queue_size, 2);
  nhp_.param("desc_threshold", params.desc_threshold, 0.8);
  nhp_.param("min_matches", params.min_matches, 40);
  nhp_.param("min_inliers", params.min_inliers, 20);
  nhp_.param("template_image_name", params.template_image_name, std::string("template.png"));
  nhp_.param("frame_id", params.frame_id, std::string("/camera"));
  nhp_.param("template_frame_id", params.template_frame_id, std::string("/template_image"));
  nhp_.param("desc_type", params.desc_type, std::string("SIFT"));
  nhp_.param("bucket_width", params.bucket_width, 30);
  nhp_.param("bucket_height", params.bucket_height, 30);
  nhp_.param("max_bucket_features", params.max_bucket_features, 10);
  nhp_.param("template_width", params.template_width, 0.5);
  nhp_.param("template_height", params.template_height, 0.16);

  // Set stereo slam parameters
  setParams(params);

  // Topics subscriptions
  string image_topic, image_info_topic;
  nhp_.param("image_topic", image_topic, string("/left/image_rect_color"));
  nhp_.param("image_info_topic", image_info_topic, string("/left/camera_info"));
  image_transport::ImageTransport it(nh_);
  image_sub_.subscribe(it, image_topic, 1);
  info_sub_.subscribe(nh_, image_info_topic, 1);

  // Services to start or stop the template detection
  nhp_.param("listen_services", listen_services_, false);
  detect_service_ = nhp_.advertiseService("detect", &TemplatePose::detectSrv, this);
  start_service_ = nhp_.advertiseService("start_detection", &TemplatePose::startDetectionSrv, this);
  stop_service_ = nhp_.advertiseService("stop_detection", &TemplatePose::stopDetectionSrv, this);

  // Advertise the image matches publisher
  matches_image_pub_ = nhp_.advertise<sensor_msgs::Image>("matches", 1);
}

/** \brief Initializes the template pose class
  * @return true if all ok
  */
bool template_pose::TemplatePose::initialize()
{
  // Initialize parameters
  first_iter_ = true;
  camera_to_template_.setIdentity();

  // Initialize service bool variables
  if (listen_services_)
    do_detection_ = false;
  else
    do_detection_ = true;

  // Check if template image exists
  string template_file = params_.template_image_name;
  if (!boost::filesystem::exists(template_file))
  {
    ROS_ERROR_STREAM("[TemplatePose:] The template image file does not exists: " <<
                     template_file);
    return false;
  }

  // Read the template image
  Mat img_temp = imread(template_file, CV_LOAD_IMAGE_COLOR);

  // Initialize image properties objects
  template_pose::ImageProperties::Params image_params;
  image_params.desc_type = params_.desc_type;
  image_params.bucket_width = params_.bucket_width;
  image_params.bucket_height = params_.bucket_height;
  image_params.max_bucket_features = params_.max_bucket_features;
  image_params.px_meter_x = (float)img_temp.cols / (float)params_.template_width;
  image_params.px_meter_y = (float)img_temp.rows / (float)params_.template_height;

  // Set the image properties
  template_prop_.setParams(image_params);
  img_prop_.setParams(image_params);

  // Compute template properties
  template_prop_.setImg(img_temp);
  template_prop_.compute3D();

  // Callback synchronization
  bool approx;
  nhp_.param("approximate_sync", approx, false);
  if (approx)
  {
    approximate_sync_.reset(new ApproximateSync(ApproximatePolicy(params_.queue_size),
                                    image_sub_,
                                    info_sub_) );
    approximate_sync_->registerCallback(boost::bind(
        &template_pose::TemplatePose::msgsCallback,
        this, _1, _2));
  }
  else
  {
    exact_sync_.reset(new ExactSync(ExactPolicy(params_.queue_size),
                                    image_sub_,
                                    info_sub_) );
    exact_sync_->registerCallback(boost::bind(
        &template_pose::TemplatePose::msgsCallback,
        this, _1, _2));
  }

  return true;
}

/** \brief Estimates the transform between the template and the stereo frame
  * @return true if all ok
  * \param - output tf transform
  */
bool template_pose::TemplatePose::estimateTransform(tf::Transform& output)
{
  // Initialize output
  output.setIdentity();

  // Crosscheck descriptors matching
  Mat desc_image = img_prop_.getDesc();
  Mat desc_template = template_prop_.getDesc();
  vector<DMatch> matches;
  Mat match_mask;
  template_pose::OpencvUtils::crossCheckThresholdMatching(desc_image,
  desc_template, params_.desc_threshold, match_mask, matches);

  // Publish matches
  if (matches_image_pub_.getNumSubscribers() > 0)
  {
    Mat img_matches;
    drawMatches(img_prop_.getImg(),
                img_prop_.getKp(),
                template_prop_.getImg(),
                template_prop_.getKp(),
                matches, img_matches);

    cv_bridge::CvImage cv_image;
    cv_image.encoding = enc::BGR8;
    cv_image.image = img_matches;
    matches_image_pub_.publish(cv_image.toImageMsg());
  }

  ROS_INFO_STREAM("[TemplatePose:] Found " << matches.size() <<
   " matches (min_matches is: " << params_.min_matches << ")");

  // Sanity check
  if ((int)matches.size() < params_.min_matches)
    return false;

  // Extract keypoints and 3d points of vertex i and j
  vector<KeyPoint> kp_image = img_prop_.getKp();
  vector<Point3f> points3d_template = template_prop_.get3Dpoints();

  vector<Point2f> matched_keypoints;
  vector<Point3f> matched_3d_points;
  for (size_t i = 0; i < matches.size(); ++i)
  {
    int idx_image = matches[i].queryIdx;
    int idx_template = matches[i].trainIdx;
    matched_3d_points.push_back(points3d_template[idx_template]);
    matched_keypoints.push_back(kp_image[idx_image].pt);
  }

  // Compute the transformation between the vertices
  Mat rvec, tvec;
  vector<int> inliers;
  solvePnPRansac(matched_3d_points, matched_keypoints, camera_matrix_,
                 Mat(), rvec, tvec, false /* no extrinsic guess */,
                 100 /* iterations */, 4.0 /* reproj. error */,
                 params_.min_inliers /* min inliers */, inliers);

  ROS_INFO_STREAM("[TemplatePose:] Found " << inliers.size() <<
   " inliers (min_inliers is: " << params_.min_inliers << ")");

  // Sanity check
  if (static_cast<int>(inliers.size()) < params_.min_inliers)
    return false;

  // Ok, build the tf
  tf::Vector3 axis(rvec.at<double>(0, 0),
                   rvec.at<double>(1, 0),
                   rvec.at<double>(2, 0));
  double angle = cv::norm(rvec);
  tf::Quaternion quaternion(axis, angle);

  tf::Vector3 translation(tvec.at<double>(0, 0), tvec.at<double>(1, 0),
      tvec.at<double>(2, 0));

  output = tf::Transform(quaternion, translation);
  return true;
}

bool template_pose::TemplatePose::detectSrv(std_srvs::Empty::Request&, std_srvs::Empty::Response&)
{
  camera_to_template_.setIdentity();
  do_detection_ = false;
  toggle_detection_ = true;
  ROS_INFO("[TemplatePose:] Service Detect requested.");
  return true;
}

bool template_pose::TemplatePose::startDetectionSrv(std_srvs::Empty::Request&, std_srvs::Empty::Response&)
{
  camera_to_template_.setIdentity();
  do_detection_ = true;
  ROS_INFO("[TemplatePose:] Service Start Detection requested.");
  return true;
}

bool template_pose::TemplatePose::stopDetectionSrv(std_srvs::Empty::Request&, std_srvs::Empty::Response&)
{
  do_detection_ = false;
  ROS_INFO("[TemplatePose:] Service Stop Detection requested.");
  return true;
}
<|endoftext|>


<commit_before>// Resource.cpp
// Implements the Resource Class

#include "GenericResource.h"

#include "CycException.h"
#include "Logger.h"

bool GenericResource::type_is_logged_ = false;
table_ptr GenericResource::genres_table = new Table("GenericResources");

using namespace std;

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GenericResource::GenericResource(std::string units,
                                 std::string quality, double quantity) : Resource() {
  units_ = units;
  quality_ = quality;
  quantity_ = quantity;
  recorded_ = false;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int GenericResource::stateID() {
  return 0;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GenericResource::GenericResource(const GenericResource& other) {
  units_ = other.units_;
  quality_ = other.quality_;
  quantity_ = other.quantity_;
};

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
rsrc_ptr GenericResource::clone() {
  CLOG(LEV_DEBUG2) << "GenericResource ID=" << ID_ << " was cloned.";
  print();
  return rsrc_ptr(new GenericResource(*this));
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void GenericResource::print() {
  CLOG(LEV_DEBUG3) << "GenericResource ID=" << ID_ << ", quality=" << quality_
                   << ", quantity=" << quantity_ << ", units=" << units_;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool GenericResource::checkQuality(rsrc_ptr other){
  bool toRet = false;

  toRet = (units_ == other->units());
  return toRet;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void GenericResource::absorb(gen_rsrc_ptr other) {
  if (! checkQuality(boost::dynamic_pointer_cast<Resource>(other))) {
    throw CycGenResourceIncompatible("incompatible resource types.");
  }

  quantity_ += other->quantity();
  other->setQuantity(0);
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
gen_rsrc_ptr GenericResource::extract(double quantity) {
  if (quantity > quantity_) {
    throw CycGenResourceOverExtract("Attempted to extract more quantity than exists.");
  }

  quantity_ -= quantity;

  return gen_rsrc_ptr(new GenericResource(units_, quality_, quantity));
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void GenericResource::addToTable() {
  Resource::addToTable();

  if ( !genres_table->defined() ) {
    GenericResource::define_table();
  }

  if (recorded_) {
    return;
  }

  recorded_ = true;

  data an_id( ID() );
  entry id("ResourceID", an_id);

  data a_qual( quality() );
  entry qual("Quality", a_qual);

  row aRow;
  aRow.push_back(id), aRow.push_back(qual);

  genres_table->addRow(aRow);
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void GenericResource::define_table() {
  genres_table->addField("ResourceID","INTEGER");
  genres_table->addField("Quality","VARCHAR(128)");

  primary_key pk;
  pk.push_back("ResourceID");
  genres_table->setPrimaryKey(pk);

  genres_table->tableDefined();
}

<commit_msg>fixes bug where split generic resources were not having quality recorded in output db.<commit_after>// Resource.cpp
// Implements the Resource Class

#include "GenericResource.h"

#include "CycException.h"
#include "Logger.h"

bool GenericResource::type_is_logged_ = false;
table_ptr GenericResource::genres_table = new Table("GenericResources");

using namespace std;

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GenericResource::GenericResource(std::string units,
                                 std::string quality, double quantity) : Resource() {
  units_ = units;
  quality_ = quality;
  quantity_ = quantity;
  recorded_ = false;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int GenericResource::stateID() {
  return 0;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GenericResource::GenericResource(const GenericResource& other) {
  units_ = other.units_;
  quality_ = other.quality_;
  quantity_ = other.quantity_;
  recorded_ = false;
};

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
rsrc_ptr GenericResource::clone() {
  CLOG(LEV_DEBUG2) << "GenericResource ID=" << ID_ << " was cloned.";
  print();
  return rsrc_ptr(new GenericResource(*this));
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void GenericResource::print() {
  CLOG(LEV_DEBUG3) << "GenericResource ID=" << ID_ << ", quality=" << quality_
                   << ", quantity=" << quantity_ << ", units=" << units_;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool GenericResource::checkQuality(rsrc_ptr other){
  bool toRet = false;

  toRet = (units_ == other->units());
  return toRet;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void GenericResource::absorb(gen_rsrc_ptr other) {
  if (! checkQuality(boost::dynamic_pointer_cast<Resource>(other))) {
    throw CycGenResourceIncompatible("incompatible resource types.");
  }

  quantity_ += other->quantity();
  other->setQuantity(0);
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
gen_rsrc_ptr GenericResource::extract(double quantity) {
  if (quantity > quantity_) {
    throw CycGenResourceOverExtract("Attempted to extract more quantity than exists.");
  }

  quantity_ -= quantity;

  return gen_rsrc_ptr(new GenericResource(units_, quality_, quantity));
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void GenericResource::addToTable() {
  Resource::addToTable();

  if ( !genres_table->defined() ) {
    GenericResource::define_table();
  }

  if (recorded_) {
    return;
  }

  recorded_ = true;

  data an_id( ID() );
  entry id("ResourceID", an_id);

  data a_qual( quality() );
  entry qual("Quality", a_qual);

  row aRow;
  aRow.push_back(id), aRow.push_back(qual);

  genres_table->addRow(aRow);
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void GenericResource::define_table() {
  genres_table->addField("ResourceID","INTEGER");
  genres_table->addField("Quality","VARCHAR(128)");

  primary_key pk;
  pk.push_back("ResourceID");
  genres_table->setPrimaryKey(pk);

  genres_table->tableDefined();
}

<|endoftext|>


<commit_before>/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

#include "ImGuiLayer.h"

#include "SkCanvas.h"
#include "SkImage.h"
#include "SkPixmap.h"
#include "SkSwizzle.h"
#include "SkVertices.h"

#include "imgui.h"

#include <stdlib.h>
#include <map>

using namespace sk_app;

ImGuiLayer::ImGuiLayer() {
    // ImGui initialization:
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO();

    // Keymap...
    io.KeyMap[ImGuiKey_Tab] = (int)Window::Key::kTab;
    io.KeyMap[ImGuiKey_LeftArrow] = (int)Window::Key::kLeft;
    io.KeyMap[ImGuiKey_RightArrow] = (int)Window::Key::kRight;
    io.KeyMap[ImGuiKey_UpArrow] = (int)Window::Key::kUp;
    io.KeyMap[ImGuiKey_DownArrow] = (int)Window::Key::kDown;
    io.KeyMap[ImGuiKey_PageUp] = (int)Window::Key::kPageUp;
    io.KeyMap[ImGuiKey_PageDown] = (int)Window::Key::kPageDown;
    io.KeyMap[ImGuiKey_Home] = (int)Window::Key::kHome;
    io.KeyMap[ImGuiKey_End] = (int)Window::Key::kEnd;
    io.KeyMap[ImGuiKey_Delete] = (int)Window::Key::kDelete;
    io.KeyMap[ImGuiKey_Backspace] = (int)Window::Key::kBack;
    io.KeyMap[ImGuiKey_Enter] = (int)Window::Key::kOK;
    io.KeyMap[ImGuiKey_Escape] = (int)Window::Key::kEscape;
    io.KeyMap[ImGuiKey_A] = (int)Window::Key::kA;
    io.KeyMap[ImGuiKey_C] = (int)Window::Key::kC;
    io.KeyMap[ImGuiKey_V] = (int)Window::Key::kV;
    io.KeyMap[ImGuiKey_X] = (int)Window::Key::kX;
    io.KeyMap[ImGuiKey_Y] = (int)Window::Key::kY;
    io.KeyMap[ImGuiKey_Z] = (int)Window::Key::kZ;

    int w, h;
    unsigned char* pixels;
    io.Fonts->GetTexDataAsAlpha8(&pixels, &w, &h);
    SkImageInfo info = SkImageInfo::MakeA8(w, h);
    SkPixmap pmap(info, pixels, info.minRowBytes());
    SkMatrix localMatrix = SkMatrix::MakeScale(1.0f / w, 1.0f / h);
    auto fontImage = SkImage::MakeFromRaster(pmap, nullptr, nullptr);
    auto fontShader = fontImage->makeShader(&localMatrix);
    fFontPaint.setShader(fontShader);
    fFontPaint.setColor(SK_ColorWHITE);
    fFontPaint.setFilterQuality(kLow_SkFilterQuality);
    io.Fonts->TexID = &fFontPaint;
}

ImGuiLayer::~ImGuiLayer() {
    ImGui::DestroyContext();
}

void ImGuiLayer::onAttach(Window* window) {
    fWindow = window;
}

bool ImGuiLayer::onMouse(int x, int y, Window::InputState state, uint32_t modifiers) {
    ImGuiIO& io = ImGui::GetIO();
    io.MousePos.x = static_cast<float>(x);
    io.MousePos.y = static_cast<float>(y);
    if (Window::kDown_InputState == state) {
        io.MouseDown[0] = true;
    } else if (Window::kUp_InputState == state) {
        io.MouseDown[0] = false;
    }
    return io.WantCaptureMouse;
}

bool ImGuiLayer::onMouseWheel(float delta, uint32_t modifiers) {
    ImGuiIO& io = ImGui::GetIO();
    io.MouseWheel += delta;
    return true;
}

void ImGuiLayer::skiaWidget(const ImVec2& size, SkiaWidgetFunc func) {
    intptr_t funcIndex = fSkiaWidgetFuncs.count();
    fSkiaWidgetFuncs.push_back(func);
    ImGui::Image((ImTextureID)funcIndex, size);
}

void ImGuiLayer::onPrePaint() {
    // Update ImGui input
    ImGuiIO& io = ImGui::GetIO();
    io.DeltaTime = 1.0f / 60.0f;
    io.DisplaySize.x = static_cast<float>(fWindow->width());
    io.DisplaySize.y = static_cast<float>(fWindow->height());

    io.KeyAlt = io.KeysDown[static_cast<int>(Window::Key::kOption)];
    io.KeyCtrl = io.KeysDown[static_cast<int>(Window::Key::kCtrl)];
    io.KeyShift = io.KeysDown[static_cast<int>(Window::Key::kShift)];

    ImGui::NewFrame();
}

void ImGuiLayer::onPaint(SkCanvas* canvas) {
    // This causes ImGui to rebuild vertex/index data based on all immediate-mode commands
    // (widgets, etc...) that have been issued
    ImGui::Render();

    // Then we fetch the most recent data, and convert it so we can render with Skia
    const ImDrawData* drawData = ImGui::GetDrawData();
    SkTDArray<SkPoint> pos;
    SkTDArray<SkPoint> uv;
    SkTDArray<SkColor> color;

    for (int i = 0; i < drawData->CmdListsCount; ++i) {
        const ImDrawList* drawList = drawData->CmdLists[i];

        // De-interleave all vertex data (sigh), convert to Skia types
        pos.rewind(); uv.rewind(); color.rewind();
        for (int j = 0; j < drawList->VtxBuffer.size(); ++j) {
            const ImDrawVert& vert = drawList->VtxBuffer[j];
            pos.push_back(SkPoint::Make(vert.pos.x, vert.pos.y));
            uv.push_back(SkPoint::Make(vert.uv.x, vert.uv.y));
            color.push_back(vert.col);
        }
        // ImGui colors are RGBA
        SkSwapRB(color.begin(), color.begin(), color.count());

        int indexOffset = 0;

        // Draw everything with canvas.drawVertices...
        for (int j = 0; j < drawList->CmdBuffer.size(); ++j) {
            const ImDrawCmd* drawCmd = &drawList->CmdBuffer[j];

            SkAutoCanvasRestore acr(canvas, true);

            // TODO: Find min/max index for each draw, so we know how many vertices (sigh)
            if (drawCmd->UserCallback) {
                drawCmd->UserCallback(drawList, drawCmd);
            } else {
                intptr_t idIndex = (intptr_t)drawCmd->TextureId;
                if (idIndex < fSkiaWidgetFuncs.count()) {
                    // Small image IDs are actually indices into a list of callbacks. We directly
                    // examing the vertex data to deduce the image rectangle, then reconfigure the
                    // canvas to be clipped and translated so that the callback code gets to use
                    // Skia to render a widget in the middle of an ImGui panel.
                    ImDrawIdx rectIndex = drawList->IdxBuffer[indexOffset];
                    SkPoint tl = pos[rectIndex], br = pos[rectIndex + 2];
                    canvas->clipRect(SkRect::MakeLTRB(tl.fX, tl.fY, br.fX, br.fY));
                    canvas->translate(tl.fX, tl.fY);
                    fSkiaWidgetFuncs[idIndex](canvas);
                } else {
                    SkPaint* paint = static_cast<SkPaint*>(drawCmd->TextureId);
                    SkASSERT(paint);

                    canvas->clipRect(SkRect::MakeLTRB(drawCmd->ClipRect.x, drawCmd->ClipRect.y,
                                                      drawCmd->ClipRect.z, drawCmd->ClipRect.w));
                    auto vertices = SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode,
                                                         drawList->VtxBuffer.size(),
                                                         pos.begin(), uv.begin(), color.begin(),
                                                         drawCmd->ElemCount,
                                                         drawList->IdxBuffer.begin() + indexOffset);
                    canvas->drawVertices(vertices, SkBlendMode::kModulate, *paint);
                    indexOffset += drawCmd->ElemCount;
                }
            }
        }
    }

    fSkiaWidgetFuncs.reset();
}

bool ImGuiLayer::onKey(sk_app::Window::Key key, sk_app::Window::InputState state, uint32_t modifiers) {
    ImGuiIO& io = ImGui::GetIO();
    io.KeysDown[static_cast<int>(key)] = (Window::kDown_InputState == state);
    return io.WantCaptureKeyboard;
}

bool ImGuiLayer::onChar(SkUnichar c, uint32_t modifiers) {
    ImGuiIO& io = ImGui::GetIO();
    if (io.WantTextInput) {
        if (c > 0 && c < 0x10000) {
            io.AddInputCharacter(c);
        }
        return true;
    }
    return false;
}
<commit_msg>Give ImGui the correct DeltaTime<commit_after>/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

#include "ImGuiLayer.h"

#include "SkCanvas.h"
#include "SkImage.h"
#include "SkPixmap.h"
#include "SkSwizzle.h"
#include "SkTime.h"
#include "SkVertices.h"

#include "imgui.h"

#include <stdlib.h>
#include <map>

using namespace sk_app;

ImGuiLayer::ImGuiLayer() {
    // ImGui initialization:
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO();

    // Keymap...
    io.KeyMap[ImGuiKey_Tab] = (int)Window::Key::kTab;
    io.KeyMap[ImGuiKey_LeftArrow] = (int)Window::Key::kLeft;
    io.KeyMap[ImGuiKey_RightArrow] = (int)Window::Key::kRight;
    io.KeyMap[ImGuiKey_UpArrow] = (int)Window::Key::kUp;
    io.KeyMap[ImGuiKey_DownArrow] = (int)Window::Key::kDown;
    io.KeyMap[ImGuiKey_PageUp] = (int)Window::Key::kPageUp;
    io.KeyMap[ImGuiKey_PageDown] = (int)Window::Key::kPageDown;
    io.KeyMap[ImGuiKey_Home] = (int)Window::Key::kHome;
    io.KeyMap[ImGuiKey_End] = (int)Window::Key::kEnd;
    io.KeyMap[ImGuiKey_Delete] = (int)Window::Key::kDelete;
    io.KeyMap[ImGuiKey_Backspace] = (int)Window::Key::kBack;
    io.KeyMap[ImGuiKey_Enter] = (int)Window::Key::kOK;
    io.KeyMap[ImGuiKey_Escape] = (int)Window::Key::kEscape;
    io.KeyMap[ImGuiKey_A] = (int)Window::Key::kA;
    io.KeyMap[ImGuiKey_C] = (int)Window::Key::kC;
    io.KeyMap[ImGuiKey_V] = (int)Window::Key::kV;
    io.KeyMap[ImGuiKey_X] = (int)Window::Key::kX;
    io.KeyMap[ImGuiKey_Y] = (int)Window::Key::kY;
    io.KeyMap[ImGuiKey_Z] = (int)Window::Key::kZ;

    int w, h;
    unsigned char* pixels;
    io.Fonts->GetTexDataAsAlpha8(&pixels, &w, &h);
    SkImageInfo info = SkImageInfo::MakeA8(w, h);
    SkPixmap pmap(info, pixels, info.minRowBytes());
    SkMatrix localMatrix = SkMatrix::MakeScale(1.0f / w, 1.0f / h);
    auto fontImage = SkImage::MakeFromRaster(pmap, nullptr, nullptr);
    auto fontShader = fontImage->makeShader(&localMatrix);
    fFontPaint.setShader(fontShader);
    fFontPaint.setColor(SK_ColorWHITE);
    fFontPaint.setFilterQuality(kLow_SkFilterQuality);
    io.Fonts->TexID = &fFontPaint;
}

ImGuiLayer::~ImGuiLayer() {
    ImGui::DestroyContext();
}

void ImGuiLayer::onAttach(Window* window) {
    fWindow = window;
}

bool ImGuiLayer::onMouse(int x, int y, Window::InputState state, uint32_t modifiers) {
    ImGuiIO& io = ImGui::GetIO();
    io.MousePos.x = static_cast<float>(x);
    io.MousePos.y = static_cast<float>(y);
    if (Window::kDown_InputState == state) {
        io.MouseDown[0] = true;
    } else if (Window::kUp_InputState == state) {
        io.MouseDown[0] = false;
    }
    return io.WantCaptureMouse;
}

bool ImGuiLayer::onMouseWheel(float delta, uint32_t modifiers) {
    ImGuiIO& io = ImGui::GetIO();
    io.MouseWheel += delta;
    return true;
}

void ImGuiLayer::skiaWidget(const ImVec2& size, SkiaWidgetFunc func) {
    intptr_t funcIndex = fSkiaWidgetFuncs.count();
    fSkiaWidgetFuncs.push_back(func);
    ImGui::Image((ImTextureID)funcIndex, size);
}

void ImGuiLayer::onPrePaint() {
    // Update ImGui input
    ImGuiIO& io = ImGui::GetIO();

    static double previousTime = 0.0;
    double currentTime = SkTime::GetSecs();
    io.DeltaTime = static_cast<float>(currentTime - previousTime);
    previousTime = currentTime;

    io.DisplaySize.x = static_cast<float>(fWindow->width());
    io.DisplaySize.y = static_cast<float>(fWindow->height());

    io.KeyAlt = io.KeysDown[static_cast<int>(Window::Key::kOption)];
    io.KeyCtrl = io.KeysDown[static_cast<int>(Window::Key::kCtrl)];
    io.KeyShift = io.KeysDown[static_cast<int>(Window::Key::kShift)];

    ImGui::NewFrame();
}

void ImGuiLayer::onPaint(SkCanvas* canvas) {
    // This causes ImGui to rebuild vertex/index data based on all immediate-mode commands
    // (widgets, etc...) that have been issued
    ImGui::Render();

    // Then we fetch the most recent data, and convert it so we can render with Skia
    const ImDrawData* drawData = ImGui::GetDrawData();
    SkTDArray<SkPoint> pos;
    SkTDArray<SkPoint> uv;
    SkTDArray<SkColor> color;

    for (int i = 0; i < drawData->CmdListsCount; ++i) {
        const ImDrawList* drawList = drawData->CmdLists[i];

        // De-interleave all vertex data (sigh), convert to Skia types
        pos.rewind(); uv.rewind(); color.rewind();
        for (int j = 0; j < drawList->VtxBuffer.size(); ++j) {
            const ImDrawVert& vert = drawList->VtxBuffer[j];
            pos.push_back(SkPoint::Make(vert.pos.x, vert.pos.y));
            uv.push_back(SkPoint::Make(vert.uv.x, vert.uv.y));
            color.push_back(vert.col);
        }
        // ImGui colors are RGBA
        SkSwapRB(color.begin(), color.begin(), color.count());

        int indexOffset = 0;

        // Draw everything with canvas.drawVertices...
        for (int j = 0; j < drawList->CmdBuffer.size(); ++j) {
            const ImDrawCmd* drawCmd = &drawList->CmdBuffer[j];

            SkAutoCanvasRestore acr(canvas, true);

            // TODO: Find min/max index for each draw, so we know how many vertices (sigh)
            if (drawCmd->UserCallback) {
                drawCmd->UserCallback(drawList, drawCmd);
            } else {
                intptr_t idIndex = (intptr_t)drawCmd->TextureId;
                if (idIndex < fSkiaWidgetFuncs.count()) {
                    // Small image IDs are actually indices into a list of callbacks. We directly
                    // examing the vertex data to deduce the image rectangle, then reconfigure the
                    // canvas to be clipped and translated so that the callback code gets to use
                    // Skia to render a widget in the middle of an ImGui panel.
                    ImDrawIdx rectIndex = drawList->IdxBuffer[indexOffset];
                    SkPoint tl = pos[rectIndex], br = pos[rectIndex + 2];
                    canvas->clipRect(SkRect::MakeLTRB(tl.fX, tl.fY, br.fX, br.fY));
                    canvas->translate(tl.fX, tl.fY);
                    fSkiaWidgetFuncs[idIndex](canvas);
                } else {
                    SkPaint* paint = static_cast<SkPaint*>(drawCmd->TextureId);
                    SkASSERT(paint);

                    canvas->clipRect(SkRect::MakeLTRB(drawCmd->ClipRect.x, drawCmd->ClipRect.y,
                                                      drawCmd->ClipRect.z, drawCmd->ClipRect.w));
                    auto vertices = SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode,
                                                         drawList->VtxBuffer.size(),
                                                         pos.begin(), uv.begin(), color.begin(),
                                                         drawCmd->ElemCount,
                                                         drawList->IdxBuffer.begin() + indexOffset);
                    canvas->drawVertices(vertices, SkBlendMode::kModulate, *paint);
                    indexOffset += drawCmd->ElemCount;
                }
            }
        }
    }

    fSkiaWidgetFuncs.reset();
}

bool ImGuiLayer::onKey(sk_app::Window::Key key, sk_app::Window::InputState state, uint32_t modifiers) {
    ImGuiIO& io = ImGui::GetIO();
    io.KeysDown[static_cast<int>(key)] = (Window::kDown_InputState == state);
    return io.WantCaptureKeyboard;
}

bool ImGuiLayer::onChar(SkUnichar c, uint32_t modifiers) {
    ImGuiIO& io = ImGui::GetIO();
    if (io.WantTextInput) {
        if (c > 0 && c < 0x10000) {
            io.AddInputCharacter(c);
        }
        return true;
    }
    return false;
}
<|endoftext|>


<commit_before>#include "UserCode/diall/interface/genParticleProducer.h"
#include "UserCode/diall/interface/hiEventProducer.h"
#include "UserCode/diall/interface/lwMuonProducer.h"
#include "UserCode/diall/interface/pfParticleProducer.h"
#include "UserCode/diall/interface/LWJetProducer.h"
#include "UserCode/diall/interface/lwJetContainer.h"
#include "UserCode/diall/interface/lwJetFromForestProducer.h"
#include "UserCode/diall/interface/anaBaseTask.h"
#include "UserCode/diall/interface/anaJetEnergyScale.h"
#include "UserCode/diall/interface/anaJetMatching.h"
#include "UserCode/diall/interface/anaJetQA.h"
#include "UserCode/diall/interface/anaRhoProducer.h"
#include "UserCode/diall/interface/anaMET.h"
#include "UserCode/diall/interface/anaMuonIsolation.h"
#include "UserCode/diall/interface/anaMuonMatcher.h"
#include "UserCode/diall/interface/anaPuppiProducer.h"
#include "UserCode/diall/interface/anaPuppiParticles.h"
#include "UserCode/diall/interface/anaZToMuMu.h"

#include <TList.h>
#include <TChain.h>
#include <TFile.h>

//#include "CollectFiles.C"

#include <iostream>

using namespace std;

bool doPuppi         = true;
bool doJetFinding    = false;
bool useMetric2      = false;
bool storeTree       = true;//false;

void analyzePuppi(std::vector<std::string> urls, const char *outname = "eventObjects.root", Long64_t nentries = 20, Int_t firstF = -1, Int_t lastF = -1, Int_t firstEvent = 0, int ptminType = 0, int jetSignalType = 0) {

  /*
    ptminType: minimum raw pt for particles used by puppi
    0 : 0 GeV
    1 : 1 GeV
    2 : 2 GeV

    jetSignalType: jets used to select jetty region in events
    0 : detector-level jets (akPu4PF)
    1 : particle-level jets (gen jets)
   */

  double ptMinPuppi = 0.;
  if(ptminType==0) ptMinPuppi = 0.;
  else if(ptminType==1) ptMinPuppi = 1.;
  else if(ptminType==2) ptMinPuppi = 2.;

  TString signalJets = "aktPUR040";
  if(jetSignalType==0) signalJets = "aktPUR040";
  else if(jetSignalType==1) signalJets = "akt4Gen";
  std::cout << "signalJets: " << signalJets << std::endl;

  // std::vector<std::string> urls = CollectFiles(list);

  // Printf("anaFile: %d",anaFile);

  std::cout << "nfiles: " << urls.size() << std::endl;
  for (auto i = urls.begin(); i != urls.end(); ++i)
    std::cout << *i << std::endl;

  size_t firstFile = 0;
  size_t lastFile = urls.size();

  if(firstF>-1) {
    firstFile = (size_t)firstF;
    lastFile = (size_t)lastF;
  }
  std::cout << "firstFile: " << firstFile << "  lastFile: " << lastFile << std::endl;

  Int_t lastEvent = nentries;
  if(firstEvent>0) {
    lastEvent = firstEvent + nentries;
  }
  std::cout << "firstEvent: " << firstEvent << std::endl;

  //add files to chain
  TChain *chain = NULL;
  chain = new TChain("hiEvtAnalyzer/HiTree");
  for(size_t i=firstFile; i<lastFile; i++) chain->Add(urls[i].c_str());
  Printf("hiTree done");

  TChain *pfTree = new TChain("pfcandAnalyzer/pfTree");
  for(size_t i=firstFile; i<lastFile; i++) pfTree->Add(urls[i].c_str());
  chain->AddFriend(pfTree);
  Printf("pfTree done");

  // TChain *muTree = new TChain("hltMuTree/HLTMuTree");
  // for(size_t i=firstFile; i<lastFile; i++) muTree->Add(urls[i].c_str());
  // chain->AddFriend(muTree);
  // Printf("muTree done");

  TChain *jetTree = new TChain("akPu4PFJetAnalyzer/t");
  for(size_t i=firstFile; i<lastFile; i++) jetTree->Add(urls[i].c_str());
  chain->AddFriend(jetTree);
  Printf("jetTree done");

  TChain *genTree = new TChain("HiGenParticleAna/hi");
  for(size_t i=firstFile; i<lastFile; i++) genTree->Add(urls[i].c_str());
  chain->AddFriend(genTree);
  Printf("genTree done");

  TList *fEventObjects = new TList();

  //---------------------------------------------------------------
  // producers
  //
  hiEventProducer *p_evt = new hiEventProducer("hiEvtProd");
  p_evt->SetInput(chain);
  p_evt->SetHIEventContName("hiEventContainer");
  p_evt->SetEventObjects(fEventObjects);

  pfParticleProducer *p_pf = new pfParticleProducer("pfPartProd");
  p_pf->SetInput(chain);
  p_pf->SetpfParticlesName("pfParticles");
  p_pf->SetEventObjects(fEventObjects);

  genParticleProducer *p_gen = new genParticleProducer("genParticleProd");
  p_gen->SetInput(chain);
  p_gen->SetGenParticlesName("genParticles");
  p_gen->SetEventObjects(fEventObjects);

  lwJetFromForestProducer *p_PUJet = new lwJetFromForestProducer("lwJetForestProd");
  p_PUJet->SetInput(chain);
  p_PUJet->SetJetContName("aktPUR040");
  p_PUJet->SetGenJetContName("akt4Gen");
  p_PUJet->SetEventObjects(fEventObjects);
  p_PUJet->SetRadius(0.4);

  //---------------------------------------------------------------
  //analysis modules
  //

  //handler to which all modules will be added
  anaBaseTask *handler = new anaBaseTask("handler","handler");

  //analysis modules which also produce
  anaPuppiProducer *pupProd = new anaPuppiProducer("pupProd","pupProd");
  pupProd->ConnectEventObject(fEventObjects);
  pupProd->SetHiEvtName("hiEventContainer");
  pupProd->SetPFPartName("pfParticles");
  pupProd->SetPuppiPartName("puppiParticles");
  pupProd->SetJetsName(signalJets);
  //pupProd->SetAddMetricType(anaPuppiProducer::kMass);
  pupProd->SetPtMinParticle(ptMinPuppi);//1.);
  pupProd->SetStoreTree(storeTree);
  pupProd->SetConeRadius(0.2);
  pupProd->SetPuppiWeightType(anaPuppiProducer::kMeanPt);
  if(doPuppi) handler->Add(pupProd);

  //anti-kt jet finder on reconstructed PUPPI particles ptmin=0
  LWJetProducer *lwjakt = new LWJetProducer("LWJetProducerAKTR040Puppi","LWJetProducerAKTR040Puppi");
  lwjakt->ConnectEventObject(fEventObjects);
  lwjakt->SetJetType(LWJetProducer::kAKT);
  lwjakt->SetRadius(0.4);
  lwjakt->SetGhostArea(0.005);
  lwjakt->SetPtMinConst(ptMinPuppi);//0.);
  lwjakt->SetParticlesName("puppiParticles");
  lwjakt->SetJetContName("JetsAKTR040Puppi");
  if(doJetFinding) handler->Add(lwjakt);

  //anti-kt jet finder on generated particles
  LWJetProducer *lwjaktGen = new LWJetProducer("LWGenJetProducerAKTR040","LWGenJetProducerAKTR040");
  lwjaktGen->ConnectEventObject(fEventObjects);
  lwjaktGen->SetJetType(LWJetProducer::kAKT);
  lwjaktGen->SetRadius(0.4);
  lwjaktGen->SetGhostArea(0.005);
  lwjaktGen->SetPtMinConst(0.);
  lwjaktGen->SetParticlesName("genParticles");
  lwjaktGen->SetJetContName("GenJetsAKTR040");
  if(doJetFinding) handler->Add(lwjaktGen);

  //Initialization of all analysis modules
  anaPuppiParticles *pupAna = new anaPuppiParticles("pupAna","pupAna");
  pupAna->ConnectEventObject(fEventObjects);
  pupAna->SetHiEvtName("hiEventContainer");
  pupAna->SetParticlesName("puppiParticles");
  pupAna->SetJetsName(signalJets);//"aktPUR040");
  if(doPuppi) handler->Add(pupAna);

  //particle-detector-level jet matching
  anaJetMatching *match = new anaJetMatching("jetMatching","jetMatching");
  match->ConnectEventObject(fEventObjects);
  match->SetHiEvtName("hiEventContainer");
  match->SetJetsNameBase("JetsAKTR040Puppi");
  match->SetJetsNameTag("akt4Gen");//GenJetsAKTR040");
  if(doJetFinding) handler->Add(match);

  anaJetEnergyScale *anajes = new anaJetEnergyScale("anaJES","anaJES");
  anajes->ConnectEventObject(fEventObjects);
  anajes->SetHiEvtName("hiEventContainer");
  anajes->SetGenJetsName("akt4Gen");//GenJetsAKTR040");
  anajes->SetRecJetsName("JetsAKTR040Puppi");
  anajes->SetNCentBins(4);
  if(doJetFinding) handler->Add(anajes);

  anaJetMatching *matchGen = new anaJetMatching("jetMatchingGenGen","jetMatchingGenGen");
  matchGen->ConnectEventObject(fEventObjects);
  matchGen->SetHiEvtName("hiEventContainer");
  matchGen->SetJetsNameBase("GenJetsAKTR040");
  matchGen->SetJetsNameTag("akt4Gen");
  if(doJetFinding) handler->Add(matchGen);

  anaJetEnergyScale *anajesgen = new anaJetEnergyScale("anajesgen","anajesgen");
  anajesgen->ConnectEventObject(fEventObjects);
  anajesgen->SetHiEvtName("hiEventContainer");
  anajesgen->SetGenJetsName("akt4Gen");
  anajesgen->SetRecJetsName("GenJetsAKTR040");
  anajesgen->SetNCentBins(4);
  if(doJetFinding) handler->Add(anajesgen);

  //---------------------------------------------------------------
  //Event loop
  //---------------------------------------------------------------
  Long64_t entries_tot =  chain->GetEntriesFast(); //93064
  if(nentries<0) lastEvent = chain->GetEntries();
  Printf("nentries: %lld  tot: %lld",nentries,entries_tot);
  for (Long64_t jentry=firstEvent; jentry<lastEvent; ++jentry) {
    if(jentry%10000==0) cout << "entry: "<< jentry << endl;
    //Run producers
    //Printf("produce hiEvent");
    p_evt->Run(jentry);   //hi event properties
    //Printf("produce pf particles");
    p_pf->Run(jentry);    //pf particles
    //Printf("produce gen particles");
    p_gen->Run(jentry);   //generated particles
    //Printf("produce PU jets");
    p_PUJet->Run(jentry); //forest jets

    //Execute all analysis tasks
    handler->ExecuteTask();
  }

  fEventObjects->Print();

  TFile *out = new TFile(outname,"RECREATE");
  TList *tasks = handler->GetListOfTasks();
  TIter next(tasks);
  anaBaseTask *obj;
  while ((obj = dynamic_cast<anaBaseTask*>(next()) ))
    if(obj->GetOutput()) obj->GetOutput()->Write(obj->GetName(),TObject::kSingleKey);

  out->Write();
  out->Close();

}
<commit_msg>add possibility to run CS jets<commit_after>#include "UserCode/diall/interface/genParticleProducer.h"
#include "UserCode/diall/interface/hiEventProducer.h"
#include "UserCode/diall/interface/lwMuonProducer.h"
#include "UserCode/diall/interface/pfParticleProducer.h"
#include "UserCode/diall/interface/LWJetProducer.h"
#include "UserCode/diall/interface/lwJetContainer.h"
#include "UserCode/diall/interface/lwJetFromForestProducer.h"
#include "UserCode/diall/interface/anaBaseTask.h"
#include "UserCode/diall/interface/anaJetEnergyScale.h"
#include "UserCode/diall/interface/anaJetMatching.h"
#include "UserCode/diall/interface/anaJetQA.h"
#include "UserCode/diall/interface/anaRhoProducer.h"
#include "UserCode/diall/interface/anaMET.h"
#include "UserCode/diall/interface/anaMuonIsolation.h"
#include "UserCode/diall/interface/anaMuonMatcher.h"
#include "UserCode/diall/interface/anaPuppiProducer.h"
#include "UserCode/diall/interface/anaPuppiParticles.h"
#include "UserCode/diall/interface/anaZToMuMu.h"

#include <TList.h>
#include <TChain.h>
#include <TFile.h>

//#include "CollectFiles.C"

#include <iostream>

using namespace std;

bool doPuppi         = true;
bool doJetFinding    = true;
bool useMetric2      = false;
bool storeTree       = false;
bool doCSJets        = true;

void analyzePuppi(std::vector<std::string> urls, const char *outname = "eventObjects.root", Long64_t nentries = 20, Int_t firstF = -1, Int_t lastF = -1, Int_t firstEvent = 0, int ptminType = 0, int jetSignalType = 0) {

  /*
    ptminType: minimum raw pt for particles used by puppi
    0 : 0 GeV
    1 : 1 GeV
    2 : 2 GeV

    jetSignalType: jets used to select jetty region in events
    0 : detector-level jets (akPu4PF)
    1 : particle-level jets (gen jets)
   */

  double ptMinPuppi = 0.;
  if(ptminType==0) ptMinPuppi = 1e-4;
  else if(ptminType==1) ptMinPuppi = 1.;
  else if(ptminType==2) ptMinPuppi = 2.;

  TString signalJets = "aktPUR040";
  if(jetSignalType==0) signalJets = "aktPUR040";
  else if(jetSignalType==1) signalJets = "akt4Gen";
  std::cout << "signalJets: " << signalJets << std::endl;

  // std::vector<std::string> urls = CollectFiles(list);

  // Printf("anaFile: %d",anaFile);

  std::cout << "nfiles: " << urls.size() << std::endl;
  for (auto i = urls.begin(); i != urls.end(); ++i)
    std::cout << *i << std::endl;

  size_t firstFile = 0;
  size_t lastFile = urls.size();

  if(firstF>-1) {
    firstFile = (size_t)firstF;
    lastFile = (size_t)lastF;
  }
  std::cout << "firstFile: " << firstFile << "  lastFile: " << lastFile << std::endl;

  Int_t lastEvent = nentries;
  if(firstEvent>0) {
    lastEvent = firstEvent + nentries;
  }
  std::cout << "firstEvent: " << firstEvent << std::endl;

  //add files to chain
  TChain *chain = NULL;
  chain = new TChain("hiEvtAnalyzer/HiTree");
  for(size_t i=firstFile; i<lastFile; i++) chain->Add(urls[i].c_str());
  Printf("hiTree done");

  TChain *pfTree = new TChain("pfcandAnalyzer/pfTree");
  for(size_t i=firstFile; i<lastFile; i++) pfTree->Add(urls[i].c_str());
  chain->AddFriend(pfTree);
  Printf("pfTree done");

  // TChain *muTree = new TChain("hltMuTree/HLTMuTree");
  // for(size_t i=firstFile; i<lastFile; i++) muTree->Add(urls[i].c_str());
  // chain->AddFriend(muTree);
  // Printf("muTree done");

  TChain *jetTree = new TChain("akPu4PFJetAnalyzer/t");
  for(size_t i=firstFile; i<lastFile; i++) jetTree->Add(urls[i].c_str());
  chain->AddFriend(jetTree);
  Printf("jetTree done");

  TChain *genTree = new TChain("HiGenParticleAna/hi");
  for(size_t i=firstFile; i<lastFile; i++) genTree->Add(urls[i].c_str());
  chain->AddFriend(genTree);
  Printf("genTree done");

  TList *fEventObjects = new TList();

  //---------------------------------------------------------------
  // producers
  //
  hiEventProducer *p_evt = new hiEventProducer("hiEvtProd");
  p_evt->SetInput(chain);
  p_evt->SetHIEventContName("hiEventContainer");
  p_evt->SetEventObjects(fEventObjects);

  pfParticleProducer *p_pf = new pfParticleProducer("pfPartProd");
  p_pf->SetInput(chain);
  p_pf->SetpfParticlesName("pfParticles");
  p_pf->SetEventObjects(fEventObjects);

  genParticleProducer *p_gen = new genParticleProducer("genParticleProd");
  p_gen->SetInput(chain);
  p_gen->SetGenParticlesName("genParticles");
  p_gen->SetEventObjects(fEventObjects);

  lwJetFromForestProducer *p_PUJet = new lwJetFromForestProducer("lwJetForestProd");
  p_PUJet->SetInput(chain);
  p_PUJet->SetJetContName("aktPUR040");
  p_PUJet->SetGenJetContName("akt4Gen");
  p_PUJet->SetEventObjects(fEventObjects);
  p_PUJet->SetRadius(0.4);

  //---------------------------------------------------------------
  //analysis modules
  //

  //handler to which all modules will be added
  anaBaseTask *handler = new anaBaseTask("handler","handler");

  //analysis modules which also produce
  anaPuppiProducer *pupProd = new anaPuppiProducer("pupProd","pupProd");
  pupProd->ConnectEventObject(fEventObjects);
  pupProd->SetHiEvtName("hiEventContainer");
  pupProd->SetPFPartName("pfParticles");
  pupProd->SetPuppiPartName("puppiParticles");
  pupProd->SetJetsName(signalJets);
  //pupProd->SetAddMetricType(anaPuppiProducer::kMass);
  pupProd->SetPtMinParticle(ptMinPuppi);//1.);
  pupProd->SetStoreTree(storeTree);
  pupProd->SetConeRadius(0.2);
  pupProd->SetPuppiWeightType(anaPuppiProducer::kAlpha);//kMeanPt);
  if(doPuppi) handler->Add(pupProd);

  //anti-kt jet finder on reconstructed PUPPI particles ptmin=0
  LWJetProducer *lwjakt = new LWJetProducer("LWJetProducerAKTR040Puppi","LWJetProducerAKTR040Puppi");
  lwjakt->ConnectEventObject(fEventObjects);
  lwjakt->SetJetType(LWJetProducer::kAKT);
  lwjakt->SetRadius(0.4);
  lwjakt->SetGhostArea(0.005);
  lwjakt->SetPtMinConst(ptMinPuppi);//0.);
  lwjakt->SetParticlesName("puppiParticles");
  lwjakt->SetJetContName("JetsAKTR040Puppi");
  if(doPuppi && doJetFinding) handler->Add(lwjakt);

  //anti-kt jet finder on generated particles
  LWJetProducer *lwjaktGen = new LWJetProducer("LWGenJetProducerAKTR040","LWGenJetProducerAKTR040");
  lwjaktGen->ConnectEventObject(fEventObjects);
  lwjaktGen->SetJetType(LWJetProducer::kAKT);
  lwjaktGen->SetRadius(0.4);
  lwjaktGen->SetGhostArea(0.005);
  lwjaktGen->SetPtMinConst(0.);
  lwjaktGen->SetParticlesName("genParticles");
  lwjaktGen->SetJetContName("GenJetsAKTR040");
  if(doJetFinding) handler->Add(lwjaktGen);

  //Initialization of all analysis modules
  anaPuppiParticles *pupAna = new anaPuppiParticles("pupAna","pupAna");
  pupAna->ConnectEventObject(fEventObjects);
  pupAna->SetHiEvtName("hiEventContainer");
  pupAna->SetParticlesName("puppiParticles");
  pupAna->SetJetsName(signalJets);//"aktPUR040");
  if(doPuppi) handler->Add(pupAna);

  //particle-detector-level jet matching
  anaJetMatching *match = new anaJetMatching("jetMatching","jetMatching");
  match->ConnectEventObject(fEventObjects);
  match->SetHiEvtName("hiEventContainer");
  match->SetJetsNameBase("JetsAKTR040Puppi");
  match->SetJetsNameTag("akt4Gen");//GenJetsAKTR040");
  if(doPuppi && doJetFinding) handler->Add(match);

  anaJetEnergyScale *anajes = new anaJetEnergyScale("anaJES","anaJES");
  anajes->ConnectEventObject(fEventObjects);
  anajes->SetHiEvtName("hiEventContainer");
  anajes->SetGenJetsName("akt4Gen");//GenJetsAKTR040");
  anajes->SetRecJetsName("JetsAKTR040Puppi");
  anajes->SetNCentBins(4);
  if(doPuppi && doJetFinding) handler->Add(anajes);

  anaJetMatching *matchGen = new anaJetMatching("jetMatchingGenGen","jetMatchingGenGen");
  matchGen->ConnectEventObject(fEventObjects);
  matchGen->SetHiEvtName("hiEventContainer");
  matchGen->SetJetsNameBase("GenJetsAKTR040"); //gen jets from gen particles
  matchGen->SetJetsNameTag("akt4Gen");         //forest gen jets
  if(doJetFinding) handler->Add(matchGen);

  anaJetEnergyScale *anajesgen = new anaJetEnergyScale("anajesgen","anajesgen");
  anajesgen->ConnectEventObject(fEventObjects);
  anajesgen->SetHiEvtName("hiEventContainer");
  anajesgen->SetGenJetsName("akt4Gen");
  anajesgen->SetRecJetsName("GenJetsAKTR040");
  anajesgen->SetNCentBins(4);
  if(doJetFinding) handler->Add(anajesgen);

  if(doCSJets) {
    //kt jet finder
    LWJetProducer *lwjkt = new LWJetProducer("LWJetProducerKTR020","LWJetProducerKTR020");
    lwjkt->ConnectEventObject(fEventObjects);
    lwjkt->SetJetType(LWJetProducer::kKT);
    lwjkt->SetRadius(0.2);
    lwjkt->SetGhostArea(0.005);
    lwjkt->SetPtMinConst(0.);
    lwjkt->SetParticlesName("pfParticles");
    lwjkt->SetJetContName("JetsKTR020");
    lwjkt->SetDoConstituentSubtraction(kFALSE);
    handler->Add(lwjkt);

    anaRhoProducer *rhoProd = new anaRhoProducer("anaRhoProducerKTR020","anaRhoProducerKTR020");
    rhoProd->ConnectEventObject(fEventObjects);
    rhoProd->SetJetsName("JetsKTR020");
    rhoProd->SetHiEvtName("hiEventContainer");
    rhoProd->SetNExcl(2);
    rhoProd->SetEtaRangeAll(-5.+0.2,5.-0.2);
    handler->Add(rhoProd);

    //anti-kt jet finder on reconstructed pf candidates
    LWJetProducer *lwjaktCS = new LWJetProducer("LWCSJetProducerAKTR040","LWCSJetProducerAKTR040");
    lwjaktCS->ConnectEventObject(fEventObjects);
    lwjaktCS->SetJetType(LWJetProducer::kAKT);
    lwjaktCS->SetRadius(0.4);
    lwjaktCS->SetGhostArea(0.005);
    lwjaktCS->SetPtMinConst(0.);
    lwjaktCS->SetParticlesName("pfParticles");
    lwjaktCS->SetJetContName("JetsAKTR040");
    lwjaktCS->SetCSJetContName("JetsAKTR040CS");
    lwjaktCS->SetDoConstituentSubtraction(kTRUE);
    lwjaktCS->SetRhoMapName("rhoMap");
    lwjaktCS->SetRhoMMapName("rhoMMap");
    handler->Add(lwjaktCS);

    anaJetMatching *matchCS = new anaJetMatching("jetMatchingCS","jetMatchingCS");
    matchCS->ConnectEventObject(fEventObjects);
    matchCS->SetHiEvtName("hiEventContainer");
    matchCS->SetJetsNameBase("JetsAKTR040CS");
    matchCS->SetJetsNameTag("akt4Gen");//GenJetsAKTR040");
    handler->Add(matchCS);

    anaJetEnergyScale *anajesCS = new anaJetEnergyScale("anajesCS","anajesCS");
    anajesCS->ConnectEventObject(fEventObjects);
    anajesCS->SetHiEvtName("hiEventContainer");
    anajesCS->SetGenJetsName("akt4Gen");//GenJetsAKTR040");
    anajesCS->SetRecJetsName("JetsAKTR040CS");
    anajesCS->SetNCentBins(4);
    handler->Add(anajesCS);

    anaJetEnergyScale *anajesRaw = new anaJetEnergyScale("anajesRaw","anajesRaw");
    anajesRaw->ConnectEventObject(fEventObjects);
    anajesRaw->SetHiEvtName("hiEventContainer");
    anajesRaw->SetGenJetsName("akt4Gen");//GenJetsAKTR040");
    anajesRaw->SetRecJetsName("JetsAKTR040");
    anajesRaw->SetNCentBins(4);
    handler->Add(anajesRaw);
  }

  //---------------------------------------------------------------
  //Event loop
  //---------------------------------------------------------------
  Long64_t entries_tot =  chain->GetEntriesFast(); //93064
  if(nentries<0) lastEvent = chain->GetEntries();
  Printf("nentries: %lld  tot: %lld",nentries,entries_tot);
  for (Long64_t jentry=firstEvent; jentry<lastEvent; ++jentry) {
    if(jentry%10000==0) cout << "entry: "<< jentry << endl;
    //Run producers
    //Printf("produce hiEvent");
    p_evt->Run(jentry);   //hi event properties
    //Printf("produce pf particles");
    p_pf->Run(jentry);    //pf particles
    //Printf("produce gen particles");
    p_gen->Run(jentry);   //generated particles
    //Printf("produce PU jets");
    p_PUJet->Run(jentry); //forest jets

    //Execute all analysis tasks
    handler->ExecuteTask();
  }

  fEventObjects->Print();

  TFile *out = new TFile(outname,"RECREATE");
  TList *tasks = handler->GetListOfTasks();
  TIter next(tasks);
  anaBaseTask *obj;
  while ((obj = dynamic_cast<anaBaseTask*>(next()) ))
    if(obj->GetOutput()) obj->GetOutput()->Write(obj->GetName(),TObject::kSingleKey);

  out->Write();
  out->Close();

}
<|endoftext|>