<commit_before>/*
*/

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdint.h>
#include <unistd.h>
#include <sched.h>
#include <stdio.h>
#include <time.h>
#include <sched.h>
#include <sys/mman.h>
#include <string.h>
#include <math.h>
/****************************************************************************/
extern "C"{
    #include "ecrt.h"
    #include <pthread.h>
}

#include <node.h>
#include <node_buffer.h>

using namespace v8;

/****************************************************************************/

#define CONFIGURE_PDOS  1
#define SDO_ACCESS      0
#define LOOP_PERIOD_NS 1000000

/****************************************************************************/

// EtherCAT
static ec_master_t *master = NULL;
static ec_master_state_t master_state ;

static ec_domain_t *domain1 = NULL;
static ec_domain_state_t domain1_state ;

/*static ec_slave_config_t *sc_ana_in = NULL;
static ec_slave_config_state_t sc_ana_in_state = {};

static ec_slave_config_t *sc_rta_x = NULL;
static ec_slave_config_state_t sc_rta_x_state = {};*/

/****************************************************************************/

// process data
static uint8_t *domain1_pd = NULL;

#define BusCouplerPos  0, 0
#define DigOutSlavePos 0, 2
#define AnaInSlavePos  0, 3
#define AnaOutSlavePos 0, 4

#define Beckhoff_EK1100 0x00000002, 0x044c2c52
#define Beckhoff_EL2004 0x00000002, 0x07d43052
#define Beckhoff_EL2032 0x00000002, 0x07f03052
#define Beckhoff_EL3152 0x00000002, 0x0c503052
#define Beckhoff_EL3102 0x00000002, 0x0c1e3052
#define Beckhoff_EL4102 0x00000002, 0x10063052
#define RTA_X_PLUS   0x0000017f,0x00000014

#define KNUMDRIVES 2

ec_slave_config_t *slave_config[KNUMDRIVES];
static ec_slave_config_state_t sc_state[KNUMDRIVES];

typedef struct slave_data_t{
    unsigned int offControlWord;
    unsigned int offTargetPosition;
    unsigned int offStatusWord;
    unsigned int offActualPosition;
    uint16_t controlWord;
    int32_t targetPosition;
    uint16_t statusWord;
    int32_t actualPosition;
    bool active; // si está activo o no
    bool oldActive; // si está activo o no

    int moveType; // 0 --> en velocidad, 1 senoidal

    unsigned int period; // ciclos por periodo de 360 grados
    unsigned int startCycle; //  tick donde se inició la senoidal
    float fStartPos; // Posición donde se inició la onda
    float fAmplitude; // amplitud del movimiento

    double fSpeed;
    double fTargetPos; // Target position en flotante
}slave_data_t;

slave_data_t slave_data[KNUMDRIVES];

// OJO. NO DEPENDE DE KNUMDRIVES!!!

/*const static ec_pdo_entry_reg_t domain1_regs[] = {
    {0,0,RTA_X_PLUS,0x6040, 0x00, &(slave_data[0].offControlWord)}, // Control Word
    {0,0,RTA_X_PLUS,0x6060, 0x00, &(slave_data[0].offModesOfOperation)}, // Modes of Operation
    {0,0,RTA_X_PLUS,0x607a, 0x00, &(slave_data[0].offTargetPosition)}, // Target Position
    {0,0,RTA_X_PLUS,0x6041, 0x00, &(slave_data[0].offStatusWord)}, // Status Word
    {0,0,RTA_X_PLUS,0x6061, 0x00, &(slave_data[0].offModesOfOperationDisplay)}, // Modes of Operation Display
    {0,0,RTA_X_PLUS,0x6064, 0x00, &(slave_data[0].offActualPosition)}, // Position Actual Value
    {0,1,RTA_X_PLUS,0x6040, 0x00, &(slave_data[1].offControlWord)}, // Control Word
    {0,1,RTA_X_PLUS,0x6060, 0x00, &(slave_data[1].offModesOfOperation)}, // Modes of Operation
    {0,1,RTA_X_PLUS,0x607a, 0x00, &(slave_data[1].offTargetPosition)}, // Target Position
    {0,1,RTA_X_PLUS,0x6041, 0x00, &(slave_data[1].offStatusWord)}, // Status Word
    {0,1,RTA_X_PLUS,0x6061, 0x00, &(slave_data[1].offModesOfOperationDisplay)}, // Modes of Operation Display
    {0,1,RTA_X_PLUS,0x6064, 0x00, &(slave_data[1].offActualPosition)}, // Position Actual Value
   {}
};*/

const static ec_pdo_entry_reg_t domain1_regs[] = {
    {0,0,RTA_X_PLUS,0x6040, 0x00, &(slave_data[0].offControlWord)}, // Control Word
    {0,0,RTA_X_PLUS,0x607a, 0x00, &(slave_data[0].offTargetPosition)}, // Target Position
    {0,0,RTA_X_PLUS,0x6041, 0x00, &(slave_data[0].offStatusWord)}, // Status Word
    {0,0,RTA_X_PLUS,0x6064, 0x00, &(slave_data[0].offActualPosition)}, // Position Actual Value
    {0,1,RTA_X_PLUS,0x6040, 0x00, &(slave_data[1].offControlWord)}, // Control Word
    {0,1,RTA_X_PLUS,0x607a, 0x00, &(slave_data[1].offTargetPosition)}, // Target Position
    {0,1,RTA_X_PLUS,0x6041, 0x00, &(slave_data[1].offStatusWord)}, // Status Word
    {0,1,RTA_X_PLUS,0x6064, 0x00, &(slave_data[1].offActualPosition)}, // Position Actual Value
   {}
};

/*****************************************************************************/

// RTA

ec_pdo_entry_info_t rta_x_plus_pdo_entries[] = {
    {0x6040, 0x00, 16}, // Control Word
    {0x607a, 0x00, 32}, // Target Position
    {0x6041, 0x00, 16}, // Status Word
    {0x6064, 0x00, 32}, // Position Actual Value
};

ec_pdo_info_t rta_x_plus_pdos[] = {
    {0x1601, 2, rta_x_plus_pdo_entries + 0}, // RxPDO100
    {0x1A01, 2, rta_x_plus_pdo_entries + 2}, // TxPDO100
};

ec_sync_info_t rta_x_plus_syncs[] = {
/*    {0, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE},
    {1, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE},*/
    {2, EC_DIR_OUTPUT, 1, rta_x_plus_pdos + 0, EC_WD_DISABLE},
    {3, EC_DIR_INPUT, 1, rta_x_plus_pdos + 1, EC_WD_DISABLE},
    {0xff}
};

/*****************************************************************************/

#if SDO_ACCESS
static ec_sdo_request_t *sdo;
#endif

/*****************************************************************************/

void check_domain1_state(void)
{
    ec_domain_state_t ds;

    ecrt_domain_state(domain1, &ds);

    #ifdef DEBUG
        if (ds.working_counter != domain1_state.working_counter)
            printf("Domain1: WC %u.\n", ds.working_counter);
        if (ds.wc_state != domain1_state.wc_state)
            printf("Domain1: State %u.\n", ds.wc_state);
    #endif
    domain1_state = ds;
}

/*****************************************************************************/

void check_master_state(void)
{
    ec_master_state_t ms;

    ecrt_master_state(master, &ms);

    #ifdef DEBUG
        if (ms.slaves_responding != master_state.slaves_responding)
            printf("%u slave(s).\n", ms.slaves_responding);
        if (ms.al_states != master_state.al_states)
            printf("AL states: 0x%02X.\n", ms.al_states);
        if (ms.link_up != master_state.link_up)
            printf("Link is %s.\n", ms.link_up ? "up" : "down");
    #endif
    master_state = ms;
}

/*****************************************************************************/

void check_slave_config_states(void)
{
    #ifdef DEBUG

    int i;
    int allOperational;
    ec_slave_config_t *current;

    allOperational=0;
    for (i=0; i<KNUMDRIVES; i++){
        current=slave_config[i];
        ecrt_slave_config_state(current,&(sc_state[i]));
        if (sc_state[i].al_state&0x8){
           allOperational=1;
        }
    }
        static int beforeAllOperational=0;
        if (allOperational!=beforeAllOperational){
            printf("All operational now is: %s\n",allOperational?"true":"false");

        }
        beforeAllOperational=allOperational;
    #endif
}

/*****************************************************************************/

#if SDO_ACCESS
void read_sdo(void)
{
    switch (ecrt_sdo_request_state(sdo)) {
        case EC_REQUEST_UNUSED: // request was not used yet
            ecrt_sdo_request_read(sdo); // trigger first read
            break;
        case EC_REQUEST_BUSY:
            fprintf(stderr, "Still busy...\n");
            break;
        case EC_REQUEST_SUCCESS:
            fprintf(stderr, "SDO value: 0x%04X\n",
                    EC_READ_U16(ecrt_sdo_request_data(sdo)));
            ecrt_sdo_request_read(sdo); // trigger next read
            break;
        case EC_REQUEST_ERROR:
            fprintf(stderr, "Failed to read SDO!\n");
            ecrt_sdo_request_read(sdo); // retry reading
            break;
    }
}
#endif

#define NSEC_PER_SEC    (1000000000) /* The number of nsecs per sec. */

#define EC_NEWTIMEVAL2NANO(TV) \
(((TV).tv_sec - 946684800ULL) * 1000000000ULL + (TV).tv_nsec)

static int _cycles=0;
int cycleStatus=0;
timespec cur_time;
timespec wait_time = {
        0,
        0
};

void _cycle_start(){
        _cycles++;

        ecrt_master_send(master);

        clock_gettime(CLOCK_REALTIME, &cur_time);
        ecrt_master_application_time(master, EC_NEWTIMEVAL2NANO(cur_time));
        if (_cycles<=2){
/*           for (int i=0; i<KNUMDRIVES; i++){
            clock_gettime(CLOCK_REALTIME, &cur_time);
            ecrt_slave_config_dc(slave_config[i], 0x0300, LOOP_PERIOD_NS,LOOP_PERIOD_NS - (cur_time.tv_nsec % LOOP_PERIOD_NS), 0, 0);
           }*/
        }
        ecrt_master_sync_reference_clock(master);
        ecrt_master_sync_slave_clocks(master);
        ecrt_master_receive(master);

//            ecrt_domain_process(domain1);

}

void _cycle_end(char *hal){
    int i;
    unsigned int controlWord;
    unsigned int sinCycles;
    double u;
    double pos;
    clock_gettime(CLOCK_REALTIME, &cur_time);
    check_master_state();
    if (master_state.al_states&0x8){
       for (i=0; i<KNUMDRIVES; i++){
            slave_data[i].statusWord=EC_READ_U16(domain1_pd+slave_data[i].offStatusWord);
            slave_data[i].actualPosition=EC_READ_S32(domain1_pd+slave_data[i].offActualPosition);
            controlWord=slave_data[i].controlWord;
            if (slave_data[i].active){
            //    if (!(slave_data[i].statusWord&0x400)  || !slave_data[i].oldActive){
                        slave_data[i].targetPosition=slave_data[i].fTargetPos;
            //    }
            }else{
                slave_data[i].targetPosition=slave_data[i].actualPosition;
            }
            if (slave_data[i].moveType==0){
                slave_data[i].fTargetPos+=slave_data[i].fSpeed;
                slave_data[i].startCycle=0;
            }else{
                if (slave_data[i].startCycle==0){
                   slave_data[i].startCycle=_cycles;
                   slave_data[i].fStartPos=slave_data[i].fTargetPos;
                }
                sinCycles=(_cycles-slave_data[i].startCycle)%slave_data[i].period;
                u=((double)sinCycles)/slave_data[i].period;
                pos=slave_data[i].fAmplitude*sin(u*M_PI*2);
                pos+=slave_data[i].fStartPos;
                slave_data[i].fTargetPos=pos;
            }
            EC_WRITE_U16(domain1_pd+slave_data[i].offControlWord,controlWord);
            EC_WRITE_S32(domain1_pd+slave_data[i].offTargetPosition,slave_data[i].targetPosition);
            slave_data[i].oldActive=slave_data[i].active;
        }
    }
    ecrt_domain_process(domain1);
    ecrt_domain_queue(domain1);

/*
    ecrt_master_receive(master);
    ecrt_domain_process(domain1);*/
}

/****************************************************************************/

int _start()
{
    int i;

    printf("Requesting master 0\n");
    master = ecrt_request_master(0);
    if (!master)
        return -1;
    printf("Master 0 obtained\n");
    domain1 = ecrt_master_create_domain(master);
    if (!domain1)
        return -1;

    printf("Configuring PDOs...\n");

    for (i=0; i<KNUMDRIVES; i++){

        slave_data[i].controlWord=0;
        slave_data[i].targetPosition=0;

        sc_state[i].online=0;
        sc_state[i].operational=0;
        sc_state[i].al_state=1;
        slave_data[i].fSpeed=0;
        slave_data[i].fTargetPos=0;
        slave_data[i].startCycle=0;
        slave_data[i].period=1000; // 1 segundo
        slave_data[i].fAmplitude=10000; // casi una vuelta
        slave_data[i].fStartPos=0;
        slave_data[i].moveType=0;
        slave_data[i].active=false;
        slave_data[i].oldActive=false;

        if (!(slave_config[i] = ecrt_master_slave_config(
                        master, 0,i, RTA_X_PLUS))) {
            fprintf(stderr, "Failed to get slave configuration.\n");
            return -1;
        }

//20151224 --> idea

/*

slaveConfig:{
    pdos:[
         {index:0x6040,value:0x0,size:16,pinName:"offControlWord0"},
         {index:0x607a,value:0x0,size:32,pinName:"targetPosition0"},
         {index:0x6041,value:0x0,size:16,pinName:"statusWord0"},
         {index:0x6064,value:0x0,size:32,pinName:"actualPosition0"}
    ],
    rxPdo:{
        index:0x1601,
        records:[0,1]
    },
    txPdo:{
       index:0x1A01,
       records:[2,3]
    },
    syncs:[
      {index:2,
       dir:"output",
       value:1,
       records:[0,1],
       wd:"EC_WD_DISABLE"
      },
      {index:2,
       dir:"input",
       value:1,
       records:[2,3],
       wd:"EC_WD_DISABLE"
    ]
}

   ethercat.addSlave({
        position:[0,i], // donde están en el bus
        ids:[0x0000017f,0x00000014], // cuál es el id del dispositivo
        config:{
                   pdos:[
                        {index:0x6040,value:0x0,size:16,pinName:"offControlWord0"},
                        {index:0x607a,value:0x0,size:32,pinName:"targetPosition0"},
                        {index:0x6041,value:0x0,size:16,pinName:"statusWord0"},
                        {index:0x6064,value:0x0,size:32,pinName:"actualPosition0"}
                   ],
                   rxPdo:{
                       index:0x1601,
                       records:[0,1]
                   },
                   txPdo:{
                      index:0x1A01,
                      records:[2,3]
                   },
                   syncs:[
                     {index:2,
                      dir:"output",
                      value:1,
                      records:[0,1],
                      wd:"EC_WD_DISABLE"
                     },
                     {index:2,
                      dir:"input",
                      value:1,
                      records:[2,3],
                      wd:"EC_WD_DISABLE"
                   ]
               }
   });

const static ec_pdo_entry_reg_t domain1_regs[] = {
    {0,0,RTA_X_PLUS,0x6040, 0x00, &(slave_data[0].offControlWord)}, // Control Word
    {0,0,RTA_X_PLUS,0x607a, 0x00, &(slave_data[0].offTargetPosition)}, // Target Position
    {0,0,RTA_X_PLUS,0x6041, 0x00, &(slave_data[0].offStatusWord)}, // Status Word
    {0,0,RTA_X_PLUS,0x6064, 0x00, &(slave_data[0].offActualPosition)}, // Position Actual Value
    {0,1,RTA_X_PLUS,0x6040, 0x00, &(slave_data[1].offControlWord)}, // Control Word
    {0,1,RTA_X_PLUS,0x607a, 0x00, &(slave_data[1].offTargetPosition)}, // Target Position
    {0,1,RTA_X_PLUS,0x6041, 0x00, &(slave_data[1].offStatusWord)}, // Status Word
    {0,1,RTA_X_PLUS,0x6064, 0x00, &(slave_data[1].offActualPosition)}, // Position Actual Value
   {}
};

ec_pdo_entry_info_t rta_x_plus_pdo_entries[] = {
    {0x6040, 0x00, 16}, // Control Word
    {0x607a, 0x00, 32}, // Target Position
    {0x6041, 0x00, 16}, // Status Word
    {0x6064, 0x00, 32}, // Position Actual Value
};

ec_pdo_info_t rta_x_plus_pdos[] = {
    {0x1601, 2, rta_x_plus_pdo_entries + 0}, // RxPDO100
    {0x1A01, 2, rta_x_plus_pdo_entries + 2}, // TxPDO100
};

*/
        //printf("Configuring mode for slave: %i in 0x6060 as 8\n",i);
        ecrt_slave_config_sdo8(slave_config[i],0x6060,0,8);
        ecrt_slave_config_sdo8(slave_config[i],0x3206,0,1);
        ecrt_slave_config_sdo32(slave_config[i],0x6081,0,400);

        if (ecrt_slave_config_pdos(slave_config[i] , EC_END, rta_x_plus_syncs)) {
                fprintf(stderr, "Failed to configure PDOs.\n");
                return -1;
            }

        //LOOP_PERIOD_NS. OJO. HAY QUE PASARSELO AQUI, LEYENDOLO DEL PIN DE LA HAL DESDE JAVASCRIPT
        ecrt_slave_config_dc(slave_config[i], 0x0300, LOOP_PERIOD_NS, 200000, 0, 0);
        //ecrt_slave_config_dc(slave_config[i], 0x0300, LOOP_PERIOD_NS, 0, 0, 0);

    }

    printf("PDOs configured\n");

    if (ecrt_domain_reg_pdo_entry_list(domain1, domain1_regs)) {
        fprintf(stderr, "PDO entry registration failed!\n");
        return -1;
    }

        printf("CheckPoint 5 \n");

    printf("Activating master...\n");
    if (ecrt_master_activate(master))
        return -1;

    if (!(domain1_pd = ecrt_domain_data(domain1))) {
        return -1;
    }

    printf("Started 2.\n");
    return 0;
}

void start(const FunctionCallbackInfo<Value>& args) {

    // Vamos a recuperar los parámetros
    Isolate *isolate=Isolate::GetCurrent();
    HandleScope scope(isolate);

    _start();
/*  Local<Object> bufferObj = args[0]->ToObject();
  char * bufferData=node::Buffer::Data(bufferObj);
  size_t bufferLength=node::Buffer::Length(bufferObj);
  Isolate* isolate = Isolate::GetCurrent();
  HandleScope scope(isolate);

//  printf("%s: %d\n",bufferData,(int)bufferLength);
  if (bufferLength!=GLOBAL_SIZE){
    isolate->ThrowException(Exception::TypeError(
        String::NewFromUtf8(isolate, "Buffer size does not match shared memory size")));
    return;
  }else
    memcpy(bufferData,k->globals,GLOBAL_SIZE);
  //strcpy(bufferData,"Hello from C++");
  //bufferData[0]='K';*/

}

void setSpeed(const FunctionCallbackInfo<Value> &args){
    Isolate *isolate=Isolate::GetCurrent();
    HandleScope scope(isolate);
    if (args.Length()<2){
        isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate,"Wrong number of arguments. Specify slaveId and target pos")));
        return;
    }
    if (!args[0]->IsNumber() || !args[1]->IsNumber()){
        isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate,"Please specify slaveId and target pos as numeric values")));
        return;
    }
    int slaveId=args[0]->NumberValue();
    double fSpeed=args[1]->NumberValue();
//    printf("setting target position for drive %d to: %d\n",slaveId,targetPosition);
    if (slaveId<0 || slaveId>=KNUMDRIVES){
        isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate,"Invalid drive id")));
        return;
    }
    slave_data[slaveId].fSpeed=fSpeed;
    slave_data[slaveId].moveType=0;
}

unsigned char testAddr[8];

void init(Handle<Object> exports) {
                         /* the defined mask, i.e. only 7. */
  NODE_SET_METHOD(exports, "start", start);
}

NODE_MODULE(ethercatNative, init)

/****************************************************************************/
<commit_msg>Some cleaning<commit_after>/*
*/

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdint.h>
#include <unistd.h>
#include <sched.h>
#include <time.h>
#include <sched.h>
#include <sys/mman.h>
#include <string.h>
#include <math.h>
/****************************************************************************/
extern "C"{
    #include "ecrt.h"
    #include <pthread.h>
}

#include <node.h>
#include <node_buffer.h>

using namespace v8;

/****************************************************************************/

#define LOOP_PERIOD_NS 1000000

/****************************************************************************/

// EtherCAT
static ec_master_t *master = NULL;
static ec_master_state_t master_state ;

static ec_domain_t *domain1 = NULL;
static ec_domain_state_t domain1_state ;
static bool initialised=false;

/*static ec_slave_config_t *sc_ana_in = NULL;
static ec_slave_config_state_t sc_ana_in_state = {};

static ec_slave_config_t *sc_rta_x = NULL;
static ec_slave_config_state_t sc_rta_x_state = {};*/

/****************************************************************************/

// process data
static uint8_t *domain1_pd = NULL;

void check_domain1_state(void)
{
    ec_domain_state_t ds;

    ecrt_domain_state(domain1, &ds);

    #ifdef DEBUG
        if (ds.working_counter != domain1_state.working_counter)
            printf("Domain1: WC %u.\n", ds.working_counter);
        if (ds.wc_state != domain1_state.wc_state)
            printf("Domain1: State %u.\n", ds.wc_state);
    #endif
    domain1_state = ds;
}

/*****************************************************************************/

void check_master_state(void)
{
    ec_master_state_t ms;

    ecrt_master_state(master, &ms);

    #ifdef DEBUG
        if (ms.slaves_responding != master_state.slaves_responding)
            printf("%u slave(s).\n", ms.slaves_responding);
        if (ms.al_states != master_state.al_states)
            printf("AL states: 0x%02X.\n", ms.al_states);
        if (ms.link_up != master_state.link_up)
            printf("Link is %s.\n", ms.link_up ? "up" : "down");
    #endif
    master_state = ms;
}

/*****************************************************************************/

#define NSEC_PER_SEC    (1000000000) /* The number of nsecs per sec. */

#define EC_NEWTIMEVAL2NANO(TV) \
(((TV).tv_sec - 946684800ULL) * 1000000000ULL + (TV).tv_nsec)

static int _cycles=0;
int cycleStatus=0;
timespec cur_time;

void _cycle_start(){
        _cycles++;

        ecrt_master_send(master);

        clock_gettime(CLOCK_REALTIME, &cur_time);
        ecrt_master_application_time(master, EC_NEWTIMEVAL2NANO(cur_time));
        ecrt_master_sync_reference_clock(master);
        ecrt_master_sync_slave_clocks(master);
        ecrt_master_receive(master);
}

void _cycle_end(char *hal){
    clock_gettime(CLOCK_REALTIME, &cur_time);
    check_master_state();
    ecrt_domain_process(domain1);
    ecrt_domain_queue(domain1);
}

/****************************************************************************/

int _start()
{
    printf("Requesting master 0\n");
    master = ecrt_request_master(0);
    if (!master)
        return -1;
    printf("Master 0 obtained\n");
    domain1 = ecrt_master_create_domain(master);
    if (!domain1)
        return -1;

    printf("Configuring PDOs...\n");
    printf("PDOs configured\n");
    printf("CheckPoint 5 \n");
    printf("Activating master...\n");
    if (ecrt_master_activate(master))
        return -1;
    if (!(domain1_pd = ecrt_domain_data(domain1))) {
        return -1;
    }
    printf("Started 2.\n");
    return 0;
}

void start(const FunctionCallbackInfo<Value>& args) {

    // Vamos a recuperar los parámetros
    Isolate *isolate=Isolate::GetCurrent();
    HandleScope scope(isolate);
    _start();

}

void addSlave(const FunctionCallbackInfo<Value>&args){
    Isolate *isolate=Isolate::GetCurrent();
    HandleScope scope(isolate);

}

void init(Handle<Object> exports) {
                         /* the defined mask, i.e. only 7. */

  NODE_SET_METHOD(exports,"addSlave",addSlave);
  NODE_SET_METHOD(exports, "start", start);

}

NODE_MODULE(ethercatNative, init)

/****************************************************************************/
<|endoftext|>


<commit_before><commit_msg>add TPC event caliblation<commit_after><|endoftext|>


<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

  =========================================================================*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbImageToLuminanceImageFilter.h"
#include "otbLuminanceToReflectanceImageFilter.h"
#include "otbReflectanceToSurfaceReflectanceImageFilter.h"
#include "otbMultiplyByScalarImageFilter.h"

namespace otb
{

  enum
    {
      Level_TOA,
      Level_TOC
    };

  enum
    {
      Aerosol_NoAerosol,
      Aerosol_Continental,
      Aerosol_Maritime,
      Aerosol_Urban,
      Aerosol_Desertic,
    };

  namespace Wrapper
  {

    class OpticalCalibration : public Application
    {

    public:
      /** Standard class typedefs. */
      typedef OpticalCalibration            Self;
      typedef Application                   Superclass;
      typedef itk::SmartPointer<Self>       Pointer;
      typedef itk::SmartPointer<const Self> ConstPointer;

      /** Standard macro */
      itkNewMacro(Self);

      itkTypeMacro(OpticalCalibration, Application);

      typedef ImageToLuminanceImageFilter<UInt16VectorImageType,
					  DoubleVectorImageType>              ImageToLuminanceImageFilterType;

      typedef LuminanceToReflectanceImageFilter<DoubleVectorImageType,
						DoubleVectorImageType>        LuminanceToReflectanceImageFilterType;

      typedef otb::MultiplyByScalarImageFilter<DoubleVectorImageType,
					       DoubleVectorImageType>         ScaleFilterType;

      typedef ReflectanceToSurfaceReflectanceImageFilter<DoubleVectorImageType,
							 DoubleVectorImageType>         ReflectanceToSurfaceReflectanceImageFilterType;
      typedef ReflectanceToSurfaceReflectanceImageFilterType::FilterFunctionValuesType  FilterFunctionValuesType;
      typedef FilterFunctionValuesType::ValuesVectorType                                ValuesVectorType;
      typedef AtmosphericCorrectionParameters                                           AtmosphericCorrectionParametersType;
      typedef AtmosphericCorrectionParametersType::AerosolModelType                     AerosolModelType;

    private:
      void DoInit()
      {
	SetName("OpticalCalibration");
	SetDescription("Perform optical calibration TOA/TOC (Top Of Atmosphere/Top Of Canopy). Supported sensors: QuickBird, Ikonos, WorldView2, Formosat, Spot5");
	// Documentation
	SetDocName("Optical calibration");
	SetDocLongDescription("The application allows to convert pixel values from DN (for Digital Numbers) to physically interpretable and comparable values. Calibrated values are called surface reflectivity and its values lie in the range [0, 1].\nThe first level is called Top Of Atmosphere (TOA) reflectivity. It takes into account the sensor gain, sensor spectral response and the solar illumination.\nThe second level is called Top Of Canopy (TOC) reflectivity. In addition to sensor gain and solar illumination, it takes into account the optical thickness of the atmosphere, the atmospheric pressure, the water vapor amount, the ozone amount, as well as the composition and amount of aerosol gasses.\nIt is also possible to indicate an AERONET file which contains atmospheric parameters (version 1 and version 2 of Aeronet file are supported.");
	SetDocLimitations("None");
	SetDocAuthors("OTB-Team");
	SetDocSeeAlso("The OTB CookBook");

	AddDocTag(Tags::Calibration);

	AddParameter(ParameterType_InputImage,  "in",  "Input");
	SetParameterDescription("in", "Input image filename (values in DN)");

	AddParameter(ParameterType_OutputImage, "out", "Output");
	SetParameterDescription("out","Output calibrated image filename");

	AddRAMParameter();

	AddParameter(ParameterType_Choice,   "level", "Calibration Level");
	AddChoice("level.toa",     "TOA : Top Of Atmosphere");
	AddChoice("level.toc",     "TOC : Top Of Canopy (EXPERIMENTAL)");
	SetParameterString("level", "toa");

	AddParameter(ParameterType_Empty, "milli", "Convert to milli reflectance");
	SetParameterDescription("milli", "Flag to use milli-reflectance instead of reflectance.\n"
				"This allows to save the image with integer pixel type (in the range [0, 1000]  instead of floating point in the range [0, 1]. In order to do that, use this option and set the output pixel type (-out filename uint16 for example)");
	DisableParameter("milli");
	MandatoryOff("milli");

	AddParameter(ParameterType_InputFilename, "rsr", "Relative Spectral Response File");
	std::ostringstream oss;
	oss << "Sensor relative spectral response file"<<std::endl;
	oss << "By default the application gets these informations in the metadata";
	SetParameterDescription("rsr", oss.str());
	MandatoryOff("rsr");

	AddParameter(ParameterType_Group,"atmo","Atmospheric parameters");
	SetParameterDescription("atmo","This group allows to set the atmospheric parameters.");
	AddParameter(ParameterType_Choice,   "atmo.aerosol", "Aerosol Model");
	AddChoice("atmo.aerosol.noaersol",    "No Aerosol Model");
	AddChoice("atmo.aerosol.continental", "Continental");
	AddChoice("atmo.aerosol.maritime",    "Maritime");
	AddChoice("atmo.aerosol.urban",       "Urban");
	AddChoice("atmo.aerosol.desertic",    "Desertic");

	AddParameter(ParameterType_Float, "atmo.oz",   "Ozone Amount");
	SetParameterDescription("atmo.oz", "Ozone Amount");

	AddParameter(ParameterType_Float, "atmo.wa",   "Water Vapor Amount");
	SetParameterDescription("atmo.wa", "Water Vapor Amount (in saturation fraction of water)");

	AddParameter(ParameterType_Float, "atmo.pressure", "Atmospheric Pressure");
	SetParameterDescription("atmo.pressure", "Atmospheric Pressure (in hPa)");

	AddParameter(ParameterType_Float, "atmo.opt",  "Aerosol Optical Thickness");
	SetParameterDescription("atmo.opt", "Aerosol Optical Thickness");

	SetDefaultParameterFloat("atmo.oz", 0.);
	SetDefaultParameterFloat("atmo.wa",  2.5);
	SetDefaultParameterFloat("atmo.pressure", 1030.);

	SetDefaultParameterFloat("atmo.opt", 0.2);
	MandatoryOff("atmo.oz");
	MandatoryOff("atmo.wa");
	MandatoryOff("atmo.pressure");
	MandatoryOff("atmo.opt");

	AddParameter(ParameterType_InputFilename, "atmo.aeronet", "Aeronet File");
	SetParameterDescription("atmo.aeronet","Aeronet file containing atmospheric parameters");
	MandatoryOff("atmo.aeronet");

	// Doc example parameter settings
	SetDocExampleParameterValue("in", "QB_1_ortho.tif");
	SetDocExampleParameterValue("level", "toa");
	SetDocExampleParameterValue("out", "OpticalCalibration.tif");
      }

      void DoUpdateParameters()
      {
	// Nothing to update
      }

      void DoExecute()
      {
	UInt16VectorImageType::Pointer inImage = GetParameterUInt16VectorImage("in");

	//Check if valid metadata informations are available to compute ImageToLuminance and LuminanceToReflectance
	itk::MetaDataDictionary             dict = inImage->GetMetaDataDictionary();
	OpticalImageMetadataInterface::Pointer lImageMetadataInterface = OpticalImageMetadataInterfaceFactory::CreateIMI(dict);

	// Test if needed data are available : an exception will be thrown
	// if one the following Get* return failure. the exception is then
	// caught in the Wrapper::Application class which redirect it to
	// the logger
	// ImageToLuminance
	lImageMetadataInterface->GetPhysicalGain();
	lImageMetadataInterface->GetPhysicalBias();

	// LuminanceToReflectance
	lImageMetadataInterface->GetDay();
	lImageMetadataInterface->GetMonth();

	lImageMetadataInterface->GetSolarIrradiance();
	lImageMetadataInterface->GetSunElevation();

	m_ImageToLuminanceFilter                = ImageToLuminanceImageFilterType::New();
	m_LuminanceToReflectanceFilter          = LuminanceToReflectanceImageFilterType::New();
	m_ReflectanceToSurfaceReflectanceFilter = ReflectanceToSurfaceReflectanceImageFilterType::New();

	m_ImageToLuminanceFilter->SetInput(inImage);
	m_LuminanceToReflectanceFilter->SetInput(m_ImageToLuminanceFilter->GetOutput());
	m_ReflectanceToSurfaceReflectanceFilter->SetInput(m_LuminanceToReflectanceFilter->GetOutput());

	m_ScaleFilter = ScaleFilterType::New();
	m_ScaleFilter->InPlaceOn();

	switch ( GetParameterInt("level") )
	  {
	  case Level_TOA:
	    {
	      m_LuminanceToReflectanceFilter->UpdateOutputInformation();
	      m_ScaleFilter->SetInput(m_LuminanceToReflectanceFilter->GetOutput());
	    }
	    break;
	  case Level_TOC:
	    {std::cout << "toc" << std::endl;
	      m_AtmosphericParam = m_ReflectanceToSurfaceReflectanceFilter->GetCorrectionParameters();
	      //AerosolModelType aeroMod = AtmosphericCorrectionParametersType::NO_AEROSOL;

	      switch ( GetParameterInt("atmo.aerosol") )
		{
		case Aerosol_Desertic:
		  {
		    // Aerosol_Desertic correspond to 4 in the enum but actually in
		    // the class atmosphericParam it is known as parameter 5
		    m_AtmosphericParam->SetAerosolModel(static_cast<AerosolModelType>(5));
		  }
		  break;
		default:
		  {
		    m_AtmosphericParam->SetAerosolModel(static_cast<AerosolModelType>(GetParameterInt("atmo.aerosol")));
		  }
		  break;
		}
	      // Set the atmospheric param
	      m_AtmosphericParam->SetOzoneAmount(GetParameterFloat("atmo.oz"));
	      m_AtmosphericParam->SetWaterVaporAmount(GetParameterFloat("atmo.wa"));
	      m_AtmosphericParam->SetAtmosphericPressure(GetParameterFloat("atmo.pressure"));
	      m_AtmosphericParam->SetAerosolOptical(GetParameterFloat("atmo.opt"));

	      // Relative Spectral Response File
	      if (IsParameterEnabled("rsr"))
		{
		  m_ReflectanceToSurfaceReflectanceFilter->SetFilterFunctionValuesFileName(GetParameterString("rsr"));
		}
	      else
		{
		  m_ReflectanceToSurfaceReflectanceFilter->SetFilterFunctionCoef(lImageMetadataInterface->GetSpectralSensitivity());
		}

	      // Aeronet file
	      if (IsParameterEnabled("atmo.aeronet"))
		{
		  m_ReflectanceToSurfaceReflectanceFilter->SetAeronetFileName(GetParameterString("atmo.aeronet"));
		}

	      //
	      AtmosphericRadiativeTerms::Pointer radTerms = AtmosphericRadiativeTerms::New();
	      radTerms->ValuesInitialization(inImage->GetNumberOfComponentsPerPixel());
	      m_ReflectanceToSurfaceReflectanceFilter->SetAtmosphericRadiativeTerms(radTerms);
	      m_ReflectanceToSurfaceReflectanceFilter->SetIsSetAtmosphericRadiativeTerms(false);
	      //m_ReflectanceToSurfaceReflectanceFilter->GenerateAtmosphericRadiativeTerms();
	      //m_ReflectanceToSurfaceReflectanceFilter->GenerateParameters();
	      m_ReflectanceToSurfaceReflectanceFilter->SetUseGenerateParameters(true);
	      m_ReflectanceToSurfaceReflectanceFilter->UpdateOutputInformation();
	      m_ReflectanceToSurfaceReflectanceFilter->SetUseGenerateParameters(false);
	      //m_ReflectanceToSurfaceReflectanceFilter->SetUseGenerateParameters(false);

	      m_ReflectanceToSurfaceReflectanceFilter->SetIsSetAtmosphericRadiativeTerms(false);
	      m_ReflectanceToSurfaceReflectanceFilter->SetUseGenerateParameters(true);
	      m_ReflectanceToSurfaceReflectanceFilter->GenerateParameters();
	      m_ReflectanceToSurfaceReflectanceFilter->SetUseGenerateParameters(false);

	      // AtmosphericCorrectionParameters::Pointer atmoPar =  m_ReflectanceToSurfaceReflectanceFilter->GetCorrectionParameters();
	      // itk::OStringStream oss;
	      // oss.str("");
	      // oss << atmoPar;
	      // std::cout << oss.str() << std::endl;

	      //rescale the surface reflectance in milli-reflectance
	      m_ReflectanceToSurfaceReflectanceFilter->UpdateOutputInformation();
	      m_ScaleFilter->SetInput(m_ReflectanceToSurfaceReflectanceFilter->GetOutput());
	    }
	    break;
	  }

	// Output Image
	const double scale = IsParameterEnabled("milli") ? 1000.0 : 1.0;
	m_ScaleFilter->SetCoef(scale);

	SetParameterOutputImage("out", m_ScaleFilter->GetOutput());
      }

      ImageToLuminanceImageFilterType ::Pointer               m_ImageToLuminanceFilter;
      LuminanceToReflectanceImageFilterType::Pointer          m_LuminanceToReflectanceFilter;
      ReflectanceToSurfaceReflectanceImageFilterType::Pointer m_ReflectanceToSurfaceReflectanceFilter;
      ScaleFilterType::Pointer                                m_ScaleFilter;
      AtmosphericCorrectionParametersType::Pointer            m_AtmosphericParam;
    };

  }// namespace Wrapper
} // namespace otb

OTB_APPLICATION_EXPORT(otb::Wrapper::OpticalCalibration)
<commit_msg>BUG:radiative terms are not computed in the TOC computation<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

  =========================================================================*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbImageToLuminanceImageFilter.h"
#include "otbLuminanceToReflectanceImageFilter.h"
#include "otbReflectanceToSurfaceReflectanceImageFilter.h"
#include "otbMultiplyByScalarImageFilter.h"

namespace otb
{

  enum
    {
      Level_TOA,
      Level_TOC
    };

  enum
    {
      Aerosol_NoAerosol,
      Aerosol_Continental,
      Aerosol_Maritime,
      Aerosol_Urban,
      Aerosol_Desertic,
    };

  namespace Wrapper
  {

    class OpticalCalibration : public Application
    {

    public:
      /** Standard class typedefs. */
      typedef OpticalCalibration            Self;
      typedef Application                   Superclass;
      typedef itk::SmartPointer<Self>       Pointer;
      typedef itk::SmartPointer<const Self> ConstPointer;

      /** Standard macro */
      itkNewMacro(Self);

      itkTypeMacro(OpticalCalibration, Application);

      typedef ImageToLuminanceImageFilter<UInt16VectorImageType,
					  DoubleVectorImageType>              ImageToLuminanceImageFilterType;

      typedef LuminanceToReflectanceImageFilter<DoubleVectorImageType,
						DoubleVectorImageType>        LuminanceToReflectanceImageFilterType;

      typedef otb::MultiplyByScalarImageFilter<DoubleVectorImageType,
					       DoubleVectorImageType>         ScaleFilterType;

      typedef ReflectanceToSurfaceReflectanceImageFilter<DoubleVectorImageType,
							 DoubleVectorImageType>         ReflectanceToSurfaceReflectanceImageFilterType;
      typedef ReflectanceToSurfaceReflectanceImageFilterType::FilterFunctionValuesType  FilterFunctionValuesType;
      typedef FilterFunctionValuesType::ValuesVectorType                                ValuesVectorType;
      typedef AtmosphericCorrectionParameters                                           AtmosphericCorrectionParametersType;
      typedef AtmosphericCorrectionParametersType::AerosolModelType                     AerosolModelType;

    private:
      void DoInit()
      {
	SetName("OpticalCalibration");
	SetDescription("Perform optical calibration TOA/TOC (Top Of Atmosphere/Top Of Canopy). Supported sensors: QuickBird, Ikonos, WorldView2, Formosat, Spot5");
	// Documentation
	SetDocName("Optical calibration");
	SetDocLongDescription("The application allows to convert pixel values from DN (for Digital Numbers) to physically interpretable and comparable values. Calibrated values are called surface reflectivity and its values lie in the range [0, 1].\nThe first level is called Top Of Atmosphere (TOA) reflectivity. It takes into account the sensor gain, sensor spectral response and the solar illumination.\nThe second level is called Top Of Canopy (TOC) reflectivity. In addition to sensor gain and solar illumination, it takes into account the optical thickness of the atmosphere, the atmospheric pressure, the water vapor amount, the ozone amount, as well as the composition and amount of aerosol gasses.\nIt is also possible to indicate an AERONET file which contains atmospheric parameters (version 1 and version 2 of Aeronet file are supported.");
	SetDocLimitations("None");
	SetDocAuthors("OTB-Team");
	SetDocSeeAlso("The OTB CookBook");

	AddDocTag(Tags::Calibration);

	AddParameter(ParameterType_InputImage,  "in",  "Input");
	SetParameterDescription("in", "Input image filename (values in DN)");

	AddParameter(ParameterType_OutputImage, "out", "Output");
	SetParameterDescription("out","Output calibrated image filename");

	AddRAMParameter();

	AddParameter(ParameterType_Choice,   "level", "Calibration Level");
	AddChoice("level.toa",     "TOA : Top Of Atmosphere");
	AddChoice("level.toc",     "TOC : Top Of Canopy (EXPERIMENTAL)");
	SetParameterString("level", "toa");

	AddParameter(ParameterType_Empty, "milli", "Convert to milli reflectance");
	SetParameterDescription("milli", "Flag to use milli-reflectance instead of reflectance.\n"
				"This allows to save the image with integer pixel type (in the range [0, 1000]  instead of floating point in the range [0, 1]. In order to do that, use this option and set the output pixel type (-out filename uint16 for example)");
	DisableParameter("milli");
	MandatoryOff("milli");

	AddParameter(ParameterType_InputFilename, "rsr", "Relative Spectral Response File");
	std::ostringstream oss;
	oss << "Sensor relative spectral response file"<<std::endl;
	oss << "By default the application gets these informations in the metadata";
	SetParameterDescription("rsr", oss.str());
	MandatoryOff("rsr");

	AddParameter(ParameterType_Group,"atmo","Atmospheric parameters");
	SetParameterDescription("atmo","This group allows to set the atmospheric parameters.");
	AddParameter(ParameterType_Choice,   "atmo.aerosol", "Aerosol Model");
	AddChoice("atmo.aerosol.noaersol",    "No Aerosol Model");
	AddChoice("atmo.aerosol.continental", "Continental");
	AddChoice("atmo.aerosol.maritime",    "Maritime");
	AddChoice("atmo.aerosol.urban",       "Urban");
	AddChoice("atmo.aerosol.desertic",    "Desertic");

	AddParameter(ParameterType_Float, "atmo.oz",   "Ozone Amount");
	SetParameterDescription("atmo.oz", "Ozone Amount");

	AddParameter(ParameterType_Float, "atmo.wa",   "Water Vapor Amount");
	SetParameterDescription("atmo.wa", "Water Vapor Amount (in saturation fraction of water)");

	AddParameter(ParameterType_Float, "atmo.pressure", "Atmospheric Pressure");
	SetParameterDescription("atmo.pressure", "Atmospheric Pressure (in hPa)");

	AddParameter(ParameterType_Float, "atmo.opt",  "Aerosol Optical Thickness");
	SetParameterDescription("atmo.opt", "Aerosol Optical Thickness");

	SetDefaultParameterFloat("atmo.oz", 0.);
	SetDefaultParameterFloat("atmo.wa",  2.5);
	SetDefaultParameterFloat("atmo.pressure", 1030.);

	SetDefaultParameterFloat("atmo.opt", 0.2);
	MandatoryOff("atmo.oz");
	MandatoryOff("atmo.wa");
	MandatoryOff("atmo.pressure");
	MandatoryOff("atmo.opt");

	AddParameter(ParameterType_InputFilename, "atmo.aeronet", "Aeronet File");
	SetParameterDescription("atmo.aeronet","Aeronet file containing atmospheric parameters");
	MandatoryOff("atmo.aeronet");

	// Doc example parameter settings
	SetDocExampleParameterValue("in", "QB_1_ortho.tif");
	SetDocExampleParameterValue("level", "toa");
	SetDocExampleParameterValue("out", "OpticalCalibration.tif");
      }

      void DoUpdateParameters()
      {
	// Nothing to update
      }

      void DoExecute()
      {
	UInt16VectorImageType::Pointer inImage = GetParameterUInt16VectorImage("in");

	//Check if valid metadata informations are available to compute ImageToLuminance and LuminanceToReflectance
	itk::MetaDataDictionary             dict = inImage->GetMetaDataDictionary();
	OpticalImageMetadataInterface::Pointer lImageMetadataInterface = OpticalImageMetadataInterfaceFactory::CreateIMI(dict);

	// Test if needed data are available : an exception will be thrown
	// if one the following Get* return failure. the exception is then
	// caught in the Wrapper::Application class which redirect it to
	// the logger
	// ImageToLuminance
	lImageMetadataInterface->GetPhysicalGain();
	lImageMetadataInterface->GetPhysicalBias();

	// LuminanceToReflectance
	lImageMetadataInterface->GetDay();
	lImageMetadataInterface->GetMonth();

	lImageMetadataInterface->GetSolarIrradiance();
	lImageMetadataInterface->GetSunElevation();

	m_ImageToLuminanceFilter                = ImageToLuminanceImageFilterType::New();
	m_LuminanceToReflectanceFilter          = LuminanceToReflectanceImageFilterType::New();
	m_ReflectanceToSurfaceReflectanceFilter = ReflectanceToSurfaceReflectanceImageFilterType::New();

	m_ImageToLuminanceFilter->SetInput(inImage);
	m_LuminanceToReflectanceFilter->SetInput(m_ImageToLuminanceFilter->GetOutput());
	m_ReflectanceToSurfaceReflectanceFilter->SetInput(m_LuminanceToReflectanceFilter->GetOutput());

	m_ScaleFilter = ScaleFilterType::New();
	m_ScaleFilter->InPlaceOn();

	switch ( GetParameterInt("level") )
	  {
	  case Level_TOA:
	    {
	      m_LuminanceToReflectanceFilter->UpdateOutputInformation();
	      m_ScaleFilter->SetInput(m_LuminanceToReflectanceFilter->GetOutput());
	    }
	    break;
	  case Level_TOC:
	    {
	      m_ReflectanceToSurfaceReflectanceFilter->SetIsSetAtmosphericRadiativeTerms(false);
	      m_ReflectanceToSurfaceReflectanceFilter->SetUseGenerateParameters(true);
	      m_ReflectanceToSurfaceReflectanceFilter->UpdateOutputInformation();
	      m_ReflectanceToSurfaceReflectanceFilter->SetUseGenerateParameters(false);

	      m_AtmosphericParam = m_ReflectanceToSurfaceReflectanceFilter->GetCorrectionParameters();
	      //AerosolModelType aeroMod = AtmosphericCorrectionParametersType::NO_AEROSOL;

	      switch ( GetParameterInt("atmo.aerosol") )
		{
		case Aerosol_Desertic:
		  {
		    // Aerosol_Desertic correspond to 4 in the enum but actually in
		    // the class atmosphericParam it is known as parameter 5
		    m_AtmosphericParam->SetAerosolModel(static_cast<AerosolModelType>(5));
		  }
		  break;
		default:
		  {
		    m_AtmosphericParam->SetAerosolModel(static_cast<AerosolModelType>(GetParameterInt("atmo.aerosol")));
		  }
		  break;
		}
	      // Set the atmospheric param
	      m_AtmosphericParam->SetOzoneAmount(GetParameterFloat("atmo.oz"));
	      m_AtmosphericParam->SetWaterVaporAmount(GetParameterFloat("atmo.wa"));
	      m_AtmosphericParam->SetAtmosphericPressure(GetParameterFloat("atmo.pressure"));
	      m_AtmosphericParam->SetAerosolOptical(GetParameterFloat("atmo.opt"));

	      // Relative Spectral Response File
	      if (IsParameterEnabled("rsr"))
		{
		  m_ReflectanceToSurfaceReflectanceFilter->SetFilterFunctionValuesFileName(GetParameterString("rsr"));
		}
	      else
		{
		  m_ReflectanceToSurfaceReflectanceFilter->SetFilterFunctionCoef(lImageMetadataInterface->GetSpectralSensitivity());
		}

	      // Aeronet file
	      if (IsParameterEnabled("atmo.aeronet"))
		{
		  m_ReflectanceToSurfaceReflectanceFilter->SetAeronetFileName(GetParameterString("atmo.aeronet"));
		}

	      m_ReflectanceToSurfaceReflectanceFilter->SetIsSetAtmosphericRadiativeTerms(false);
	      m_ReflectanceToSurfaceReflectanceFilter->SetUseGenerateParameters(true);
	      m_ReflectanceToSurfaceReflectanceFilter->GenerateParameters();
	      m_ReflectanceToSurfaceReflectanceFilter->UpdateOutputInformation();
	      m_ReflectanceToSurfaceReflectanceFilter->SetUseGenerateParameters(false);

	      //itk::OStringStream oss;
	      // oss.str("");
	      // oss << m_AtmosphericParam;
	      // //	      std::cout << oss.str() << std::endl;

	      // AtmosphericRadiativeTerms::Pointer atmoTerms =  m_ReflectanceToSurfaceReflectanceFilter->GetAtmosphericRadiativeTerms();
	      // oss << std::endl << atmoTerms;
	      // std::cout << oss.str() << std::endl;

	      //rescale the surface reflectance in milli-reflectance

	      m_ReflectanceToSurfaceReflectanceFilter->UpdateOutputInformation();
	      m_ScaleFilter->SetInput(m_ReflectanceToSurfaceReflectanceFilter->GetOutput());
	    }
	    break;
	  }

	// Output Image
	const double scale = IsParameterEnabled("milli") ? 1000.0 : 1.0;
	m_ScaleFilter->SetCoef(scale);

	SetParameterOutputImage("out", m_ScaleFilter->GetOutput());
      }

      ImageToLuminanceImageFilterType ::Pointer               m_ImageToLuminanceFilter;
      LuminanceToReflectanceImageFilterType::Pointer          m_LuminanceToReflectanceFilter;
      ReflectanceToSurfaceReflectanceImageFilterType::Pointer m_ReflectanceToSurfaceReflectanceFilter;
      ScaleFilterType::Pointer                                m_ScaleFilter;
      AtmosphericCorrectionParametersType::Pointer            m_AtmosphericParam;
    };

  }// namespace Wrapper
} // namespace otb

OTB_APPLICATION_EXPORT(otb::Wrapper::OpticalCalibration)
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2007-2008 Vojtech Franc
 * Written (W) 2007-2009 Soeren Sonnenburg
 * Copyright (C) 2007-2009 Fraunhofer Institute FIRST and Max-Planck-Society
 */

#include <shogun/labels/Labels.h>
#include <shogun/mathematics/Math.h>
#include <shogun/lib/Time.h>
#include <shogun/base/Parameter.h>
#include <shogun/base/Parallel.h>
#include <shogun/machine/LinearMachine.h>
#include <shogun/classifier/svm/SVMOcas.h>
#include <shogun/features/DotFeatures.h>
#include <shogun/labels/Labels.h>
#include <shogun/labels/BinaryLabels.h>

using namespace shogun;

CSVMOcas::CSVMOcas()
: CLinearMachine()
{
	init();
}

CSVMOcas::CSVMOcas(E_SVM_TYPE type)
: CLinearMachine()
{
	init();
	method=type;
}

CSVMOcas::CSVMOcas(
	float64_t C, CDotFeatures* traindat, CLabels* trainlab)
: CLinearMachine()
{
	init();
	C1=C;
	C2=C;

	set_features(traindat);
	set_labels(trainlab);
}

CSVMOcas::~CSVMOcas()
{
}

bool CSVMOcas::train_machine(CFeatures* data)
{
	SG_INFO("C=%f, epsilon=%f, bufsize=%d\n", get_C1(), get_epsilon(), bufsize);
	SG_DEBUG("use_bias = %i\n", get_bias_enabled()) ;

	ASSERT(m_labels);
	ASSERT(m_labels->get_label_type() == LT_BINARY);
	if (data)
	{
		if (!data->has_property(FP_DOT))
			SG_ERROR("Specified features are not of type CDotFeatures\n");
		set_features((CDotFeatures*) data);
	}
	ASSERT(features);

	lab=((CBinaryLabels*) m_labels)->get_labels();
	w=SGVector<float64_t>(features->get_dim_feature_space());
	w.zero();
	int32_t num_vec=features->get_num_vectors();

	if (num_vec!=lab.vlen || num_vec<=0)
		SG_ERROR("num_vec=%d num_train_labels=%d\n", num_vec, lab.vlen);

	SG_FREE(old_w);
	old_w=SG_CALLOC(float64_t, w.vlen);
	bias=0;
	old_bias=0;

	tmp_a_buf=SG_CALLOC(float64_t, w.vlen);
	cp_value=SG_CALLOC(float64_t*, bufsize);
	cp_index=SG_CALLOC(uint32_t*, bufsize);
	cp_nz_dims=SG_CALLOC(uint32_t, bufsize);
	cp_bias=SG_CALLOC(float64_t, bufsize);

	float64_t TolAbs=0;
	float64_t QPBound=0;
	int32_t Method=0;
	if (method == SVM_OCAS)
		Method = 1;
	ocas_return_value_T result = svm_ocas_solver( get_C1(), num_vec, get_epsilon(),
			TolAbs, QPBound, get_max_train_time(), bufsize, Method,
			&CSVMOcas::compute_W,
			&CSVMOcas::update_W,
			&CSVMOcas::add_new_cut,
			&CSVMOcas::compute_output,
			&CSVMOcas::sort,
			&CSVMOcas::print,
			this);

	SG_INFO("Ocas Converged after %d iterations\n"
			"==================================\n"
			"timing statistics:\n"
			"output_time: %f s\n"
			"sort_time: %f s\n"
			"add_time: %f s\n"
			"w_time: %f s\n"
			"solver_time %f s\n"
			"ocas_time %f s\n\n", result.nIter, result.output_time, result.sort_time,
			result.add_time, result.w_time, result.qp_solver_time, result.ocas_time);

	SG_FREE(tmp_a_buf);

	uint32_t num_cut_planes = result.nCutPlanes;

	SG_DEBUG("num_cut_planes=%d\n", num_cut_planes);
	for (uint32_t i=0; i<num_cut_planes; i++)
	{
		SG_DEBUG("cp_value[%d]=%p\n", i, cp_value);
		SG_FREE(cp_value[i]);
		SG_DEBUG("cp_index[%d]=%p\n", i, cp_index);
		SG_FREE(cp_index[i]);
	}

	SG_FREE(cp_value);
	cp_value=NULL;
	SG_FREE(cp_index);
	cp_index=NULL;
	SG_FREE(cp_nz_dims);
	cp_nz_dims=NULL;
	SG_FREE(cp_bias);
	cp_bias=NULL;

	SG_FREE(old_w);
	old_w=NULL;

	return true;
}

/*----------------------------------------------------------------------------------
  sq_norm_W = sparse_update_W( t ) does the following:

  W = oldW*(1-t) + t*W;
  sq_norm_W = W'*W;

  ---------------------------------------------------------------------------------*/
float64_t CSVMOcas::update_W( float64_t t, void* ptr )
{
  float64_t sq_norm_W = 0;
  CSVMOcas* o = (CSVMOcas*) ptr;
  uint32_t nDim = (uint32_t) o->w.vlen;
  float64_t* W=o->w.vector;
  float64_t* oldW=o->old_w;

  for(uint32_t j=0; j <nDim; j++)
  {
	  W[j] = oldW[j]*(1-t) + t*W[j];
	  sq_norm_W += W[j]*W[j];
  }
  o->bias=o->old_bias*(1-t) + t*o->bias;
  sq_norm_W += CMath::sq(o->bias);

  return( sq_norm_W );
}

/*----------------------------------------------------------------------------------
  sparse_add_new_cut( new_col_H, new_cut, cut_length, nSel ) does the following:

    new_a = sum(data_X(:,find(new_cut ~=0 )),2);
    new_col_H = [sparse_A(:,1:nSel)'*new_a ; new_a'*new_a];
    sparse_A(:,nSel+1) = new_a;

  ---------------------------------------------------------------------------------*/
int CSVMOcas::add_new_cut(
	float64_t *new_col_H, uint32_t *new_cut, uint32_t cut_length,
	uint32_t nSel, void* ptr)
{
	CSVMOcas* o = (CSVMOcas*) ptr;
	CDotFeatures* f = o->features;
	uint32_t nDim=(uint32_t) o->w.vlen;
	float64_t* y = o->lab.vector;

	float64_t** c_val = o->cp_value;
	uint32_t** c_idx = o->cp_index;
	uint32_t* c_nzd = o->cp_nz_dims;
	float64_t* c_bias = o->cp_bias;

	float64_t sq_norm_a;
	uint32_t i, j, nz_dims;

	/* temporary vector */
	float64_t* new_a = o->tmp_a_buf;
	memset(new_a, 0, sizeof(float64_t)*nDim);

	for(i=0; i < cut_length; i++)
	{
		f->add_to_dense_vec(y[new_cut[i]], new_cut[i], new_a, nDim);

		if (o->use_bias)
			c_bias[nSel]+=y[new_cut[i]];
	}

	/* compute new_a'*new_a and count number of non-zerou dimensions */
	nz_dims = 0;
	sq_norm_a = CMath::sq(c_bias[nSel]);
	for(j=0; j < nDim; j++ ) {
		if(new_a[j] != 0) {
			nz_dims++;
			sq_norm_a += new_a[j]*new_a[j];
		}
	}

	/* sparsify new_a and insert it to the last column of sparse_A */
	c_nzd[nSel] = nz_dims;
	c_idx[nSel]=NULL;
	c_val[nSel]=NULL;

	if(nz_dims > 0)
	{
		c_idx[nSel]=SG_MALLOC(uint32_t, nz_dims);
		c_val[nSel]=SG_MALLOC(float64_t, nz_dims);

		uint32_t idx=0;
		for(j=0; j < nDim; j++ )
		{
			if(new_a[j] != 0)
			{
				c_idx[nSel][idx] = j;
				c_val[nSel][idx++] = new_a[j];
			}
		}
	}

	new_col_H[nSel] = sq_norm_a;

	for(i=0; i < nSel; i++)
	{
		float64_t tmp = c_bias[nSel]*c_bias[i];
		for(j=0; j < c_nzd[i]; j++)
			tmp += new_a[c_idx[i][j]]*c_val[i][j];

		new_col_H[i] = tmp;
	}
	//CMath::display_vector(new_col_H, nSel+1, "new_col_H");
	//CMath::display_vector((int32_t*) c_idx[nSel], (int32_t) nz_dims, "c_idx");
	//CMath::display_vector((float64_t*) c_val[nSel], nz_dims, "c_val");
	return 0;
}

int CSVMOcas::sort(float64_t* vals, float64_t* data, uint32_t size)
{
	CMath::qsort_index(vals, data, size);
	return 0;
}

/*----------------------------------------------------------------------
  sparse_compute_output( output ) does the follwing:

  output = data_X'*W;
  ----------------------------------------------------------------------*/
int CSVMOcas::compute_output(float64_t *output, void* ptr)
{
	CSVMOcas* o = (CSVMOcas*) ptr;
	CDotFeatures* f=o->features;
	int32_t nData=f->get_num_vectors();

	float64_t* y = o->lab.vector;

	f->dense_dot_range(output, 0, nData, y, o->w.vector, o->w.vlen, 0.0);

	for (int32_t i=0; i<nData; i++)
		output[i]+=y[i]*o->bias;
	//CMath::display_vector(o->w, o->w.vlen, "w");
	//CMath::display_vector(output, nData, "out");
	return 0;
}

/*----------------------------------------------------------------------
  sq_norm_W = compute_W( alpha, nSel ) does the following:

  oldW = W;
  W = sparse_A(:,1:nSel)'*alpha;
  sq_norm_W = W'*W;
  dp_WoldW = W'*oldW';

  ----------------------------------------------------------------------*/
void CSVMOcas::compute_W(
	float64_t *sq_norm_W, float64_t *dp_WoldW, float64_t *alpha, uint32_t nSel,
	void* ptr )
{
	CSVMOcas* o = (CSVMOcas*) ptr;
	uint32_t nDim= (uint32_t) o->w.vlen;
	CMath::swap(o->w.vector, o->old_w);
	float64_t* W=o->w.vector;
	float64_t* oldW=o->old_w;
	memset(W, 0, sizeof(float64_t)*nDim);
	float64_t old_bias=o->bias;
	float64_t bias=0;

	float64_t** c_val = o->cp_value;
	uint32_t** c_idx = o->cp_index;
	uint32_t* c_nzd = o->cp_nz_dims;
	float64_t* c_bias = o->cp_bias;

	for(uint32_t i=0; i<nSel; i++)
	{
		uint32_t nz_dims = c_nzd[i];

		if(nz_dims > 0 && alpha[i] > 0)
		{
			for(uint32_t j=0; j < nz_dims; j++)
				W[c_idx[i][j]] += alpha[i]*c_val[i][j];
		}
		bias += c_bias[i]*alpha[i];
	}

	*sq_norm_W = CMath::dot(W,W, nDim) + CMath::sq(bias);
	*dp_WoldW = CMath::dot(W,oldW, nDim) + bias*old_bias;
	//SG_PRINT("nSel=%d sq_norm_W=%f dp_WoldW=%f\n", nSel, *sq_norm_W, *dp_WoldW);

	o->bias = bias;
	o->old_bias = old_bias;
}

void CSVMOcas::init()
{
	use_bias=true;
	bufsize=3000;
	C1=1;
	C2=1;

	epsilon=1e-3;
	method=SVM_OCAS;
	old_w=NULL;
	tmp_a_buf=NULL;
	cp_value=NULL;
	cp_index=NULL;
	cp_nz_dims=NULL;
	cp_bias=NULL;

    m_parameters->add(&C1, "C1",  "Cost constant 1.");
    m_parameters->add(&C2, "C2",  "Cost constant 2.");
    m_parameters->add(&use_bias, "use_bias",
			"Indicates if bias is used.");
    m_parameters->add(&epsilon, "epsilon", "Convergence precision.");
    m_parameters->add(&bufsize, "bufsize", "Maximum number of cutting planes.");
    m_parameters->add((machine_int_t*) &method, "method",
			"SVMOcas solver type.");
}
<commit_msg>Made SVMOcas support subsets<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2007-2008 Vojtech Franc
 * Written (W) 2007-2009 Soeren Sonnenburg
 * Copyright (C) 2007-2009 Fraunhofer Institute FIRST and Max-Planck-Society
 */

#include <shogun/labels/Labels.h>
#include <shogun/mathematics/Math.h>
#include <shogun/lib/Time.h>
#include <shogun/base/Parameter.h>
#include <shogun/base/Parallel.h>
#include <shogun/machine/LinearMachine.h>
#include <shogun/classifier/svm/SVMOcas.h>
#include <shogun/features/DotFeatures.h>
#include <shogun/labels/Labels.h>
#include <shogun/labels/BinaryLabels.h>

using namespace shogun;

CSVMOcas::CSVMOcas()
: CLinearMachine()
{
	init();
}

CSVMOcas::CSVMOcas(E_SVM_TYPE type)
: CLinearMachine()
{
	init();
	method=type;
}

CSVMOcas::CSVMOcas(
	float64_t C, CDotFeatures* traindat, CLabels* trainlab)
: CLinearMachine()
{
	init();
	C1=C;
	C2=C;

	set_features(traindat);
	set_labels(trainlab);
}

CSVMOcas::~CSVMOcas()
{
}

bool CSVMOcas::train_machine(CFeatures* data)
{
	SG_INFO("C=%f, epsilon=%f, bufsize=%d\n", get_C1(), get_epsilon(), bufsize);
	SG_DEBUG("use_bias = %i\n", get_bias_enabled()) ;

	ASSERT(m_labels);
	ASSERT(m_labels->get_label_type() == LT_BINARY);
	if (data)
	{
		if (!data->has_property(FP_DOT))
			SG_ERROR("Specified features are not of type CDotFeatures\n");
		set_features((CDotFeatures*) data);
	}
	ASSERT(features);

	int32_t num_vec=features->get_num_vectors();
	lab = SGVector<float64_t>(num_vec);
	for (int32_t i=0; i<num_vec; i++)
		lab[i] = ((CBinaryLabels*)m_labels)->get_label(i);

	w=SGVector<float64_t>(features->get_dim_feature_space());
	w.zero();

	if (num_vec!=lab.vlen || num_vec<=0)
		SG_ERROR("num_vec=%d num_train_labels=%d\n", num_vec, lab.vlen);

	SG_FREE(old_w);
	old_w=SG_CALLOC(float64_t, w.vlen);
	bias=0;
	old_bias=0;

	tmp_a_buf=SG_CALLOC(float64_t, w.vlen);
	cp_value=SG_CALLOC(float64_t*, bufsize);
	cp_index=SG_CALLOC(uint32_t*, bufsize);
	cp_nz_dims=SG_CALLOC(uint32_t, bufsize);
	cp_bias=SG_CALLOC(float64_t, bufsize);

	float64_t TolAbs=0;
	float64_t QPBound=0;
	int32_t Method=0;
	if (method == SVM_OCAS)
		Method = 1;
	ocas_return_value_T result = svm_ocas_solver( get_C1(), num_vec, get_epsilon(),
			TolAbs, QPBound, get_max_train_time(), bufsize, Method,
			&CSVMOcas::compute_W,
			&CSVMOcas::update_W,
			&CSVMOcas::add_new_cut,
			&CSVMOcas::compute_output,
			&CSVMOcas::sort,
			&CSVMOcas::print,
			this);

	SG_INFO("Ocas Converged after %d iterations\n"
			"==================================\n"
			"timing statistics:\n"
			"output_time: %f s\n"
			"sort_time: %f s\n"
			"add_time: %f s\n"
			"w_time: %f s\n"
			"solver_time %f s\n"
			"ocas_time %f s\n\n", result.nIter, result.output_time, result.sort_time,
			result.add_time, result.w_time, result.qp_solver_time, result.ocas_time);

	SG_FREE(tmp_a_buf);

	uint32_t num_cut_planes = result.nCutPlanes;

	SG_DEBUG("num_cut_planes=%d\n", num_cut_planes);
	for (uint32_t i=0; i<num_cut_planes; i++)
	{
		SG_DEBUG("cp_value[%d]=%p\n", i, cp_value);
		SG_FREE(cp_value[i]);
		SG_DEBUG("cp_index[%d]=%p\n", i, cp_index);
		SG_FREE(cp_index[i]);
	}

	SG_FREE(cp_value);
	cp_value=NULL;
	SG_FREE(cp_index);
	cp_index=NULL;
	SG_FREE(cp_nz_dims);
	cp_nz_dims=NULL;
	SG_FREE(cp_bias);
	cp_bias=NULL;

	SG_FREE(old_w);
	old_w=NULL;

	return true;
}

/*----------------------------------------------------------------------------------
  sq_norm_W = sparse_update_W( t ) does the following:

  W = oldW*(1-t) + t*W;
  sq_norm_W = W'*W;

  ---------------------------------------------------------------------------------*/
float64_t CSVMOcas::update_W( float64_t t, void* ptr )
{
  float64_t sq_norm_W = 0;
  CSVMOcas* o = (CSVMOcas*) ptr;
  uint32_t nDim = (uint32_t) o->w.vlen;
  float64_t* W=o->w.vector;
  float64_t* oldW=o->old_w;

  for(uint32_t j=0; j <nDim; j++)
  {
	  W[j] = oldW[j]*(1-t) + t*W[j];
	  sq_norm_W += W[j]*W[j];
  }
  o->bias=o->old_bias*(1-t) + t*o->bias;
  sq_norm_W += CMath::sq(o->bias);

  return( sq_norm_W );
}

/*----------------------------------------------------------------------------------
  sparse_add_new_cut( new_col_H, new_cut, cut_length, nSel ) does the following:

    new_a = sum(data_X(:,find(new_cut ~=0 )),2);
    new_col_H = [sparse_A(:,1:nSel)'*new_a ; new_a'*new_a];
    sparse_A(:,nSel+1) = new_a;

  ---------------------------------------------------------------------------------*/
int CSVMOcas::add_new_cut(
	float64_t *new_col_H, uint32_t *new_cut, uint32_t cut_length,
	uint32_t nSel, void* ptr)
{
	CSVMOcas* o = (CSVMOcas*) ptr;
	CDotFeatures* f = o->features;
	uint32_t nDim=(uint32_t) o->w.vlen;
	float64_t* y = o->lab.vector;

	float64_t** c_val = o->cp_value;
	uint32_t** c_idx = o->cp_index;
	uint32_t* c_nzd = o->cp_nz_dims;
	float64_t* c_bias = o->cp_bias;

	float64_t sq_norm_a;
	uint32_t i, j, nz_dims;

	/* temporary vector */
	float64_t* new_a = o->tmp_a_buf;
	memset(new_a, 0, sizeof(float64_t)*nDim);

	for(i=0; i < cut_length; i++)
	{
		f->add_to_dense_vec(y[new_cut[i]], new_cut[i], new_a, nDim);

		if (o->use_bias)
			c_bias[nSel]+=y[new_cut[i]];
	}

	/* compute new_a'*new_a and count number of non-zerou dimensions */
	nz_dims = 0;
	sq_norm_a = CMath::sq(c_bias[nSel]);
	for(j=0; j < nDim; j++ ) {
		if(new_a[j] != 0) {
			nz_dims++;
			sq_norm_a += new_a[j]*new_a[j];
		}
	}

	/* sparsify new_a and insert it to the last column of sparse_A */
	c_nzd[nSel] = nz_dims;
	c_idx[nSel]=NULL;
	c_val[nSel]=NULL;

	if(nz_dims > 0)
	{
		c_idx[nSel]=SG_MALLOC(uint32_t, nz_dims);
		c_val[nSel]=SG_MALLOC(float64_t, nz_dims);

		uint32_t idx=0;
		for(j=0; j < nDim; j++ )
		{
			if(new_a[j] != 0)
			{
				c_idx[nSel][idx] = j;
				c_val[nSel][idx++] = new_a[j];
			}
		}
	}

	new_col_H[nSel] = sq_norm_a;

	for(i=0; i < nSel; i++)
	{
		float64_t tmp = c_bias[nSel]*c_bias[i];
		for(j=0; j < c_nzd[i]; j++)
			tmp += new_a[c_idx[i][j]]*c_val[i][j];

		new_col_H[i] = tmp;
	}
	//CMath::display_vector(new_col_H, nSel+1, "new_col_H");
	//CMath::display_vector((int32_t*) c_idx[nSel], (int32_t) nz_dims, "c_idx");
	//CMath::display_vector((float64_t*) c_val[nSel], nz_dims, "c_val");
	return 0;
}

int CSVMOcas::sort(float64_t* vals, float64_t* data, uint32_t size)
{
	CMath::qsort_index(vals, data, size);
	return 0;
}

/*----------------------------------------------------------------------
  sparse_compute_output( output ) does the follwing:

  output = data_X'*W;
  ----------------------------------------------------------------------*/
int CSVMOcas::compute_output(float64_t *output, void* ptr)
{
	CSVMOcas* o = (CSVMOcas*) ptr;
	CDotFeatures* f=o->features;
	int32_t nData=f->get_num_vectors();

	float64_t* y = o->lab.vector;

	f->dense_dot_range(output, 0, nData, y, o->w.vector, o->w.vlen, 0.0);

	for (int32_t i=0; i<nData; i++)
		output[i]+=y[i]*o->bias;
	//CMath::display_vector(o->w, o->w.vlen, "w");
	//CMath::display_vector(output, nData, "out");
	return 0;
}

/*----------------------------------------------------------------------
  sq_norm_W = compute_W( alpha, nSel ) does the following:

  oldW = W;
  W = sparse_A(:,1:nSel)'*alpha;
  sq_norm_W = W'*W;
  dp_WoldW = W'*oldW';

  ----------------------------------------------------------------------*/
void CSVMOcas::compute_W(
	float64_t *sq_norm_W, float64_t *dp_WoldW, float64_t *alpha, uint32_t nSel,
	void* ptr )
{
	CSVMOcas* o = (CSVMOcas*) ptr;
	uint32_t nDim= (uint32_t) o->w.vlen;
	CMath::swap(o->w.vector, o->old_w);
	float64_t* W=o->w.vector;
	float64_t* oldW=o->old_w;
	memset(W, 0, sizeof(float64_t)*nDim);
	float64_t old_bias=o->bias;
	float64_t bias=0;

	float64_t** c_val = o->cp_value;
	uint32_t** c_idx = o->cp_index;
	uint32_t* c_nzd = o->cp_nz_dims;
	float64_t* c_bias = o->cp_bias;

	for(uint32_t i=0; i<nSel; i++)
	{
		uint32_t nz_dims = c_nzd[i];

		if(nz_dims > 0 && alpha[i] > 0)
		{
			for(uint32_t j=0; j < nz_dims; j++)
				W[c_idx[i][j]] += alpha[i]*c_val[i][j];
		}
		bias += c_bias[i]*alpha[i];
	}

	*sq_norm_W = CMath::dot(W,W, nDim) + CMath::sq(bias);
	*dp_WoldW = CMath::dot(W,oldW, nDim) + bias*old_bias;
	//SG_PRINT("nSel=%d sq_norm_W=%f dp_WoldW=%f\n", nSel, *sq_norm_W, *dp_WoldW);

	o->bias = bias;
	o->old_bias = old_bias;
}

void CSVMOcas::init()
{
	use_bias=true;
	bufsize=3000;
	C1=1;
	C2=1;

	epsilon=1e-3;
	method=SVM_OCAS;
	old_w=NULL;
	tmp_a_buf=NULL;
	cp_value=NULL;
	cp_index=NULL;
	cp_nz_dims=NULL;
	cp_bias=NULL;

    m_parameters->add(&C1, "C1",  "Cost constant 1.");
    m_parameters->add(&C2, "C2",  "Cost constant 2.");
    m_parameters->add(&use_bias, "use_bias",
			"Indicates if bias is used.");
    m_parameters->add(&epsilon, "epsilon", "Convergence precision.");
    m_parameters->add(&bufsize, "bufsize", "Maximum number of cutting planes.");
    m_parameters->add((machine_int_t*) &method, "method",
			"SVMOcas solver type.");
}
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2011 Soeren Sonnenburg
 * Copyright (C) 2011 Berlin Institute of Technology
 */

#include <shogun/preprocessor/KernelPCA.h>
#ifdef HAVE_LAPACK
#include <shogun/lib/config.h>
#include <shogun/mathematics/Math.h>

#include <string.h>
#include <stdlib.h>

#include <shogun/mathematics/lapack.h>
#include <shogun/lib/common.h>
#include <shogun/kernel/Kernel.h>
#include <shogun/preprocessor/DimensionReductionPreprocessor.h>
#include <shogun/features/Features.h>
#include <shogun/io/SGIO.h>

using namespace shogun;

CKernelPCA::CKernelPCA() : CDimensionReductionPreprocessor()
{
	init();
}

CKernelPCA::CKernelPCA(CKernel* k) : CDimensionReductionPreprocessor()
{
	init();
	set_kernel(k);
}

void CKernelPCA::init()
{
	m_initialized = false;
	m_init_features = NULL;
	m_transformation_matrix = SGMatrix<float64_t>(NULL, 0, 0, false);
	m_bias_vector = SGVector<float64_t>(NULL, 0, false);

	SG_ADD(&m_transformation_matrix, "transformation_matrix",
      "matrix used to transform data", MS_NOT_AVAILABLE);
	SG_ADD(&m_bias_vector, "bias_vector",
      "bias vector used to transform data", MS_NOT_AVAILABLE);
}

void CKernelPCA::cleanup()
{
	m_transformation_matrix = SGMatrix<float64_t>();

	if (m_init_features)
		SG_UNREF(m_init_features);

	m_initialized = false;
}

CKernelPCA::~CKernelPCA()
{
	if (m_init_features)
		SG_UNREF(m_init_features);
}

bool CKernelPCA::init(CFeatures* features)
{
	if (!m_initialized && m_kernel)
	{
		SG_REF(features);
		m_init_features = features;

		m_kernel->init(features,features);
		SGMatrix<float64_t> kernel_matrix = m_kernel->get_kernel_matrix();
		m_kernel->cleanup();
		int32_t n = kernel_matrix.num_cols;
		int32_t m = kernel_matrix.num_rows;
		ASSERT(n==m)

		float64_t* bias_tmp = SGMatrix<float64_t>::get_column_sum(kernel_matrix.matrix, n,n);
		SGVector<float64_t>::scale_vector(-1.0/n, bias_tmp, n);
		float64_t s = SGVector<float64_t>::sum(bias_tmp, n)/n;
		SGVector<float64_t>::add_scalar(-s, bias_tmp, n);

		SGMatrix<float64_t>::center_matrix(kernel_matrix.matrix, n, m);

		float64_t* eigenvalues=SGMatrix<float64_t>::compute_eigenvectors(kernel_matrix.matrix, n, n);

		for (int32_t i=0; i<n; i++)
		{
			//normalize and trap divide by zero and negative eigenvalues
			for (int32_t j=0; j<n; j++)
				kernel_matrix.matrix[i*n+j]/=CMath::sqrt(CMath::max(1e-16,eigenvalues[i]));
		}

		SG_FREE(eigenvalues);

		m_transformation_matrix = SGMatrix<float64_t>(kernel_matrix.matrix,n,n);
		kernel_matrix.matrix = NULL;
		m_bias_vector = SGVector<float64_t>(n);
		SGVector<float64_t>::fill_vector(m_bias_vector.vector, m_bias_vector.vlen, 0.0);

		cblas_dgemv(CblasColMajor, CblasTrans,
				n, n, 1.0, m_transformation_matrix.matrix, n,
				bias_tmp, 1, 0.0, m_bias_vector.vector, 1);

		float64_t* rowsum = SGMatrix<float64_t>::get_row_sum(m_transformation_matrix.matrix, n, n);
		SGVector<float64_t>::scale_vector(1.0/n, rowsum, n);

		for (int32_t i=0; i<n; i++)
		{
			for (int32_t j=0; j<n; j++)
				m_transformation_matrix.matrix[j+n*i] -= rowsum[i];
		}
		SG_FREE(rowsum);
		SG_FREE(bias_tmp);

		m_initialized=true;
		SG_INFO("Done\n")
		return true;
	}
	return false;
}

SGMatrix<float64_t> CKernelPCA::apply_to_feature_matrix(CFeatures* features)
{
	ASSERT(m_initialized)
	CDenseFeatures<float64_t>* simple_features = (CDenseFeatures<float64_t>*)features;

	int32_t num_vectors = simple_features->get_num_vectors();
	int32_t i,j,k;
	int32_t n = m_transformation_matrix.num_cols;

	m_kernel->init(features,m_init_features);

	float64_t* new_feature_matrix = SG_MALLOC(float64_t, m_target_dim*num_vectors);

	for (i=0; i<num_vectors; i++)
	{
		for (j=0; j<m_target_dim; j++)
			new_feature_matrix[i*m_target_dim+j] = m_bias_vector.vector[j];

		for (j=0; j<n; j++)
		{
			float64_t kij = m_kernel->kernel(i,j);

			for (k=0; k<m_target_dim; k++)
				new_feature_matrix[k+i*m_target_dim] += kij*m_transformation_matrix.matrix[(n-k-1)*n+j];
		}
	}

	m_kernel->cleanup();
	simple_features->set_feature_matrix(SGMatrix<float64_t>(new_feature_matrix,m_target_dim,num_vectors));
	return ((CDenseFeatures<float64_t>*)features)->get_feature_matrix();
}

SGVector<float64_t> CKernelPCA::apply_to_feature_vector(SGVector<float64_t> vector)
{
	ASSERT(m_initialized)
	SGVector<float64_t> result = SGVector<float64_t>(m_target_dim);
	m_kernel->init(new CDenseFeatures<float64_t>(SGMatrix<float64_t>(vector.vector,vector.vlen,1)),
	               m_init_features);

	int32_t j,k;
	int32_t n = m_transformation_matrix.num_cols;

	for (j=0; j<m_target_dim; j++)
		result.vector[j] = m_bias_vector.vector[j];

	for (j=0; j<n; j++)
	{
		float64_t kj = m_kernel->kernel(0,j);

		for (k=0; k<m_target_dim; k++)
			result.vector[k] += kj*m_transformation_matrix.matrix[(n-k-1)*n+j];
	}

	m_kernel->cleanup();
	return result;
}

CDenseFeatures<float64_t>* CKernelPCA::apply_to_string_features(CFeatures* features)
{
	ASSERT(m_initialized)

	int32_t num_vectors = features->get_num_vectors();
	int32_t i,j,k;
	int32_t n = m_transformation_matrix.num_cols;

	m_kernel->init(features,m_init_features);

	float64_t* new_feature_matrix = SG_MALLOC(float64_t, m_target_dim*num_vectors);

	for (i=0; i<num_vectors; i++)
	{
		for (j=0; j<m_target_dim; j++)
			new_feature_matrix[i*m_target_dim+j] = m_bias_vector.vector[j];

		for (j=0; j<n; j++)
		{
			float64_t kij = m_kernel->kernel(i,j);

			for (k=0; k<m_target_dim; k++)
				new_feature_matrix[k+i*m_target_dim] += kij*m_transformation_matrix.matrix[(n-k-1)*n+j];
		}
	}

	m_kernel->cleanup();

	return new CDenseFeatures<float64_t>(SGMatrix<float64_t>(new_feature_matrix,m_target_dim,num_vectors));
}

#endif
<commit_msg>Fix memory leak in KernelPCA constructor.<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2011 Soeren Sonnenburg
 * Copyright (C) 2011 Berlin Institute of Technology
 */

#include <shogun/preprocessor/KernelPCA.h>
#ifdef HAVE_LAPACK
#include <shogun/lib/config.h>
#include <shogun/mathematics/Math.h>

#include <string.h>
#include <stdlib.h>

#include <shogun/mathematics/lapack.h>
#include <shogun/lib/common.h>
#include <shogun/kernel/Kernel.h>
#include <shogun/preprocessor/DimensionReductionPreprocessor.h>
#include <shogun/features/Features.h>
#include <shogun/io/SGIO.h>

using namespace shogun;

CKernelPCA::CKernelPCA() : CDimensionReductionPreprocessor()
{
	init();
}

CKernelPCA::CKernelPCA(CKernel* k) : CDimensionReductionPreprocessor()
{
	init();
	set_kernel(k);
}

void CKernelPCA::init()
{
	m_initialized = false;
	m_init_features = NULL;
	m_transformation_matrix = SGMatrix<float64_t>();
	m_bias_vector = SGVector<float64_t>();

	SG_ADD(&m_transformation_matrix, "transformation_matrix",
		"matrix used to transform data", MS_NOT_AVAILABLE);
	SG_ADD(&m_bias_vector, "bias_vector",
		"bias vector used to transform data", MS_NOT_AVAILABLE);
}

void CKernelPCA::cleanup()
{
	m_transformation_matrix = SGMatrix<float64_t>();
	m_bias_vector = SGVector<float64_t>();

	if (m_init_features)
		SG_UNREF(m_init_features);

	m_initialized = false;
}

CKernelPCA::~CKernelPCA()
{
	if (m_init_features)
		SG_UNREF(m_init_features);
}

bool CKernelPCA::init(CFeatures* features)
{
	if (!m_initialized && m_kernel)
	{
		SG_REF(features);
		m_init_features = features;

		m_kernel->init(features,features);
		SGMatrix<float64_t> kernel_matrix = m_kernel->get_kernel_matrix();
		m_kernel->cleanup();
		int32_t n = kernel_matrix.num_cols;
		int32_t m = kernel_matrix.num_rows;
		ASSERT(n==m)

		float64_t* bias_tmp = SGMatrix<float64_t>::get_column_sum(kernel_matrix.matrix, n,n);
		SGVector<float64_t>::scale_vector(-1.0/n, bias_tmp, n);
		float64_t s = SGVector<float64_t>::sum(bias_tmp, n)/n;
		SGVector<float64_t>::add_scalar(-s, bias_tmp, n);

		SGMatrix<float64_t>::center_matrix(kernel_matrix.matrix, n, m);

		float64_t* eigenvalues=SGMatrix<float64_t>::compute_eigenvectors(kernel_matrix.matrix, n, n);

		for (int32_t i=0; i<n; i++)
		{
			//normalize and trap divide by zero and negative eigenvalues
			for (int32_t j=0; j<n; j++)
				kernel_matrix.matrix[i*n+j]/=CMath::sqrt(CMath::max(1e-16,eigenvalues[i]));
		}

		SG_FREE(eigenvalues);

		m_transformation_matrix = SGMatrix<float64_t>(kernel_matrix.matrix,n,n);
		kernel_matrix.matrix = NULL;
		m_bias_vector = SGVector<float64_t>(n);
		SGVector<float64_t>::fill_vector(m_bias_vector.vector, m_bias_vector.vlen, 0.0);

		cblas_dgemv(CblasColMajor, CblasTrans,
				n, n, 1.0, m_transformation_matrix.matrix, n,
				bias_tmp, 1, 0.0, m_bias_vector.vector, 1);

		float64_t* rowsum = SGMatrix<float64_t>::get_row_sum(m_transformation_matrix.matrix, n, n);
		SGVector<float64_t>::scale_vector(1.0/n, rowsum, n);

		for (int32_t i=0; i<n; i++)
		{
			for (int32_t j=0; j<n; j++)
				m_transformation_matrix.matrix[j+n*i] -= rowsum[i];
		}
		SG_FREE(rowsum);
		SG_FREE(bias_tmp);

		m_initialized=true;
		SG_INFO("Done\n")
		return true;
	}
	return false;
}

SGMatrix<float64_t> CKernelPCA::apply_to_feature_matrix(CFeatures* features)
{
	ASSERT(m_initialized)
	CDenseFeatures<float64_t>* simple_features = (CDenseFeatures<float64_t>*)features;

	int32_t num_vectors = simple_features->get_num_vectors();
	int32_t i,j,k;
	int32_t n = m_transformation_matrix.num_cols;

	m_kernel->init(features,m_init_features);

	float64_t* new_feature_matrix = SG_MALLOC(float64_t, m_target_dim*num_vectors);

	for (i=0; i<num_vectors; i++)
	{
		for (j=0; j<m_target_dim; j++)
			new_feature_matrix[i*m_target_dim+j] = m_bias_vector.vector[j];

		for (j=0; j<n; j++)
		{
			float64_t kij = m_kernel->kernel(i,j);

			for (k=0; k<m_target_dim; k++)
				new_feature_matrix[k+i*m_target_dim] += kij*m_transformation_matrix.matrix[(n-k-1)*n+j];
		}
	}

	m_kernel->cleanup();
	simple_features->set_feature_matrix(SGMatrix<float64_t>(new_feature_matrix,m_target_dim,num_vectors));
	return ((CDenseFeatures<float64_t>*)features)->get_feature_matrix();
}

SGVector<float64_t> CKernelPCA::apply_to_feature_vector(SGVector<float64_t> vector)
{
	ASSERT(m_initialized)
	SGVector<float64_t> result = SGVector<float64_t>(m_target_dim);
	m_kernel->init(new CDenseFeatures<float64_t>(SGMatrix<float64_t>(vector.vector,vector.vlen,1)),
	               m_init_features);

	int32_t j,k;
	int32_t n = m_transformation_matrix.num_cols;

	for (j=0; j<m_target_dim; j++)
		result.vector[j] = m_bias_vector.vector[j];

	for (j=0; j<n; j++)
	{
		float64_t kj = m_kernel->kernel(0,j);

		for (k=0; k<m_target_dim; k++)
			result.vector[k] += kj*m_transformation_matrix.matrix[(n-k-1)*n+j];
	}

	m_kernel->cleanup();
	return result;
}

CDenseFeatures<float64_t>* CKernelPCA::apply_to_string_features(CFeatures* features)
{
	ASSERT(m_initialized)

	int32_t num_vectors = features->get_num_vectors();
	int32_t i,j,k;
	int32_t n = m_transformation_matrix.num_cols;

	m_kernel->init(features,m_init_features);

	float64_t* new_feature_matrix = SG_MALLOC(float64_t, m_target_dim*num_vectors);

	for (i=0; i<num_vectors; i++)
	{
		for (j=0; j<m_target_dim; j++)
			new_feature_matrix[i*m_target_dim+j] = m_bias_vector.vector[j];

		for (j=0; j<n; j++)
		{
			float64_t kij = m_kernel->kernel(i,j);

			for (k=0; k<m_target_dim; k++)
				new_feature_matrix[k+i*m_target_dim] += kij*m_transformation_matrix.matrix[(n-k-1)*n+j];
		}
	}

	m_kernel->cleanup();

	return new CDenseFeatures<float64_t>(SGMatrix<float64_t>(new_feature_matrix,m_target_dim,num_vectors));
}

#endif
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd

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 "OgreD3D11Device.h"
#include "OgreD3D11HardwareBufferManager.h"
#include "OgreD3D11RenderToVertexBuffer.h"
#include "OgreHardwareBufferManager.h"
#include "OgreD3D11HardwareVertexBuffer.h"
#include "OgreRenderable.h"
#include "OgreSceneManager.h"
#include "OgreRoot.h"
#include "OgreRenderSystem.h"
#include "OgreStringConverter.h"
#include "OgreD3D11RenderSystem.h"
#include "OgreD3D11HLSLProgram.h"

namespace Ogre {

	D3D11RenderToVertexBuffer::D3D11RenderToVertexBuffer(D3D11Device & device,
														 D3D11HardwareBufferManagerBase * bufManager)
		: mDevice(device),  mFrontBufferIndex(-1), mBufManager(bufManager)
	{
		mVertexBuffers[0].setNull();
		mVertexBuffers[1].setNull();
	}

	D3D11RenderToVertexBuffer::~D3D11RenderToVertexBuffer(void)
	{
	}
	void D3D11RenderToVertexBuffer::getRenderOperation(RenderOperation& op)
	{
		op.operationType = mOperationType;
		op.useIndexes = false;
		op.vertexData = mVertexData;
	}
	void D3D11RenderToVertexBuffer::update(SceneManager* sceneMgr)
	{
		size_t bufSize = mVertexData->vertexDeclaration->getVertexSize(0) * mMaxVertexCount;
		if (mVertexBuffers[0].isNull() || mVertexBuffers[0]->getSizeInBytes() != bufSize)
		{
			//Buffers don't match. Need to reallocate.
			mResetRequested = true;
		}

		//Single pass only for now
		Ogre::Pass* r2vbPass = mMaterial->getBestTechnique()->getPass(0);
		//Set pass before binding buffers to activate the GPU programs
		sceneMgr->_setPass(r2vbPass);

		RenderOperation renderOp;
		size_t targetBufferIndex;
		if (mResetRequested || mResetsEveryUpdate)
		{
			//Use source data to render to first buffer
			mSourceRenderable->getRenderOperation(renderOp);
			targetBufferIndex = 0;
		}
		else
		{
			//Use current front buffer to render to back buffer
			this->getRenderOperation(renderOp);
			targetBufferIndex = 1 - mFrontBufferIndex;
		}

		if (mVertexBuffers[targetBufferIndex].isNull() ||
			mVertexBuffers[targetBufferIndex]->getSizeInBytes() != bufSize)
		{
			reallocateBuffer(targetBufferIndex);
		}

		const D3D11HardwareVertexBuffer* d3d11buf =
			static_cast<const D3D11HardwareVertexBuffer*>(mVertexBuffers[targetBufferIndex].getPointer());

		ID3D11Buffer * pVertexBuffers = d3d11buf->getD3DVertexBuffer();

		mDevice.GetImmediateContext()->SOSetTargets(1, &pVertexBuffers, 0);
		if (mDevice.isError())
		{
			String errorDescription = mDevice.getErrorDescription();
			OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
				"D3D11 device cannot set vertex buffer\nError Description:" + errorDescription,
				"D3D11RenderToVertexBuffer::getRenderOperation");
		}

		D3D11RenderSystem* targetRenderSystem = (D3D11RenderSystem*)Root::getSingleton().getRenderSystem();

		D3D11HLSLProgram* originalVertexProgram = targetRenderSystem->_getBoundVertexProgram();
		targetRenderSystem->bindGpuProgram(r2vbPass->getVertexProgram().getPointer());
		targetRenderSystem->bindGpuProgramParameters(GPT_VERTEX_PROGRAM,
			r2vbPass->getVertexProgramParameters(), GPV_ALL);

		D3D11HLSLProgram* originalGeometryProgram = targetRenderSystem->_getBoundGeometryProgram();
		targetRenderSystem->bindGpuProgram(r2vbPass->getGeometryProgram().getPointer());
		targetRenderSystem->bindGpuProgramParameters(GPT_GEOMETRY_PROGRAM,
			r2vbPass->getGeometryProgramParameters(), GPV_ALL);

		// no fragment program!
		mDevice.GetImmediateContext()->PSSetShader(NULL, NULL, 0);
		if (mDevice.isError())
		{
			String errorDescription = mDevice.getErrorDescription();
			OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
				"D3D11 device cannot set vertex buffer to NULL\nError Description:" + errorDescription,
				"D3D11RenderToVertexBuffer::getRenderOperation");
		}

		// save depth buffer check value
		bool depthBufferCheckValue = targetRenderSystem->_getDepthBufferCheckEnabled();

		// disable depth test
		targetRenderSystem->_setDepthBufferCheckEnabled(false);

		targetRenderSystem->_render(renderOp);

		mVertexData->vertexCount = -1; // -1 means we will use DrawAuto later when rendering...

		//Switch the vertex binding if necessary
		if (targetBufferIndex != mFrontBufferIndex)
		{
			mVertexData->vertexBufferBinding->unsetAllBindings();
			mVertexData->vertexBufferBinding->setBinding(0, mVertexBuffers[targetBufferIndex]);
			mFrontBufferIndex = targetBufferIndex;
		}

		// get back to the original value
		targetRenderSystem->_setDepthBufferCheckEnabled(depthBufferCheckValue);

		// go back to the original shaders
		targetRenderSystem->bindGpuProgram(originalVertexProgram);
		targetRenderSystem->bindGpuProgram(originalGeometryProgram);

		// get back to normal render
		ID3D11Buffer* dummyBuffer = NULL;
		mDevice.GetImmediateContext()->SOSetTargets(1, &dummyBuffer, 0);
		if (mDevice.isError())
		{
			String errorDescription = mDevice.getErrorDescription();
			OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
				"D3D11 device cannot set vertex buffer to NULL\nError Description:" + errorDescription,
				"D3D11RenderToVertexBuffer::getRenderOperation");
		}

		//Clear the reset flag
		mResetRequested = false;

	}
	//-----------------------------------------------------------------------------
	void D3D11RenderToVertexBuffer::reallocateBuffer(size_t index)
	{
		assert(index == 0 || index == 1);
		if (!mVertexBuffers[index].isNull())
		{
			mVertexBuffers[index].setNull();
		}

		mVertexBuffers[index] = mBufManager->createStreamOutputVertexBuffer(
			mVertexData->vertexDeclaration->getVertexSize(0), mMaxVertexCount,
			HardwareBuffer::HBU_STATIC_WRITE_ONLY
			);
	}
}
<commit_msg>D3D11 render system: Improved a comment.<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd

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 "OgreD3D11Device.h"
#include "OgreD3D11HardwareBufferManager.h"
#include "OgreD3D11RenderToVertexBuffer.h"
#include "OgreHardwareBufferManager.h"
#include "OgreD3D11HardwareVertexBuffer.h"
#include "OgreRenderable.h"
#include "OgreSceneManager.h"
#include "OgreRoot.h"
#include "OgreRenderSystem.h"
#include "OgreStringConverter.h"
#include "OgreD3D11RenderSystem.h"
#include "OgreD3D11HLSLProgram.h"

namespace Ogre {

	D3D11RenderToVertexBuffer::D3D11RenderToVertexBuffer(D3D11Device & device,
														 D3D11HardwareBufferManagerBase * bufManager)
		: mDevice(device),  mFrontBufferIndex(-1), mBufManager(bufManager)
	{
		mVertexBuffers[0].setNull();
		mVertexBuffers[1].setNull();
	}

	D3D11RenderToVertexBuffer::~D3D11RenderToVertexBuffer(void)
	{
	}
	void D3D11RenderToVertexBuffer::getRenderOperation(RenderOperation& op)
	{
		op.operationType = mOperationType;
		op.useIndexes = false;
		op.vertexData = mVertexData;
	}
	void D3D11RenderToVertexBuffer::update(SceneManager* sceneMgr)
	{
		size_t bufSize = mVertexData->vertexDeclaration->getVertexSize(0) * mMaxVertexCount;
		if (mVertexBuffers[0].isNull() || mVertexBuffers[0]->getSizeInBytes() != bufSize)
		{
			//Buffers don't match. Need to reallocate.
			mResetRequested = true;
		}

		//Single pass only for now
		Ogre::Pass* r2vbPass = mMaterial->getBestTechnique()->getPass(0);
		//Set pass before binding buffers to activate the GPU programs
		sceneMgr->_setPass(r2vbPass);

		RenderOperation renderOp;
		size_t targetBufferIndex;
		if (mResetRequested || mResetsEveryUpdate)
		{
			//Use source data to render to first buffer
			mSourceRenderable->getRenderOperation(renderOp);
			targetBufferIndex = 0;
		}
		else
		{
			//Use current front buffer to render to back buffer
			this->getRenderOperation(renderOp);
			targetBufferIndex = 1 - mFrontBufferIndex;
		}

		if (mVertexBuffers[targetBufferIndex].isNull() ||
			mVertexBuffers[targetBufferIndex]->getSizeInBytes() != bufSize)
		{
			reallocateBuffer(targetBufferIndex);
		}

		const D3D11HardwareVertexBuffer* d3d11buf =
			static_cast<const D3D11HardwareVertexBuffer*>(mVertexBuffers[targetBufferIndex].getPointer());

		ID3D11Buffer * pVertexBuffers = d3d11buf->getD3DVertexBuffer();

		mDevice.GetImmediateContext()->SOSetTargets(1, &pVertexBuffers, 0);
		if (mDevice.isError())
		{
			String errorDescription = mDevice.getErrorDescription();
			OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
				"D3D11 device cannot set vertex buffer\nError Description:" + errorDescription,
				"D3D11RenderToVertexBuffer::getRenderOperation");
		}

		D3D11RenderSystem* targetRenderSystem = (D3D11RenderSystem*)Root::getSingleton().getRenderSystem();

		D3D11HLSLProgram* originalVertexProgram = targetRenderSystem->_getBoundVertexProgram();
		targetRenderSystem->bindGpuProgram(r2vbPass->getVertexProgram().getPointer());
		targetRenderSystem->bindGpuProgramParameters(GPT_VERTEX_PROGRAM,
			r2vbPass->getVertexProgramParameters(), GPV_ALL);

		D3D11HLSLProgram* originalGeometryProgram = targetRenderSystem->_getBoundGeometryProgram();
		targetRenderSystem->bindGpuProgram(r2vbPass->getGeometryProgram().getPointer());
		targetRenderSystem->bindGpuProgramParameters(GPT_GEOMETRY_PROGRAM,
			r2vbPass->getGeometryProgramParameters(), GPV_ALL);

		// no fragment program!
		mDevice.GetImmediateContext()->PSSetShader(NULL, NULL, 0);
		if (mDevice.isError())
		{
			String errorDescription = mDevice.getErrorDescription();
			OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
				"D3D11 device cannot set Stream-Output Stage to NULL\nError Description:" + errorDescription,
				"D3D11RenderToVertexBuffer::getRenderOperation");
		}

		// save depth buffer check value
		bool depthBufferCheckValue = targetRenderSystem->_getDepthBufferCheckEnabled();

		// disable depth test
		targetRenderSystem->_setDepthBufferCheckEnabled(false);

		targetRenderSystem->_render(renderOp);

		mVertexData->vertexCount = -1; // -1 means we will use DrawAuto later when rendering...

		//Switch the vertex binding if necessary
		if (targetBufferIndex != mFrontBufferIndex)
		{
			mVertexData->vertexBufferBinding->unsetAllBindings();
			mVertexData->vertexBufferBinding->setBinding(0, mVertexBuffers[targetBufferIndex]);
			mFrontBufferIndex = targetBufferIndex;
		}

		// get back to the original value
		targetRenderSystem->_setDepthBufferCheckEnabled(depthBufferCheckValue);

		// go back to the original shaders
		targetRenderSystem->bindGpuProgram(originalVertexProgram);
		targetRenderSystem->bindGpuProgram(originalGeometryProgram);

		// get back to normal render
		ID3D11Buffer* dummyBuffer = NULL;
		mDevice.GetImmediateContext()->SOSetTargets(1, &dummyBuffer, 0);
		if (mDevice.isError())
		{
			String errorDescription = mDevice.getErrorDescription();
			OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
				"D3D11 device cannot set vertex buffer output to NULL\nError Description:" + errorDescription,
				"D3D11RenderToVertexBuffer::getRenderOperation");
		}

		//Clear the reset flag
		mResetRequested = false;

	}
	//-----------------------------------------------------------------------------
	void D3D11RenderToVertexBuffer::reallocateBuffer(size_t index)
	{
		assert(index == 0 || index == 1);
		if (!mVertexBuffers[index].isNull())
		{
			mVertexBuffers[index].setNull();
		}

		mVertexBuffers[index] = mBufManager->createStreamOutputVertexBuffer(
			mVertexData->vertexDeclaration->getVertexSize(0), mMaxVertexCount,
			HardwareBuffer::HBU_STATIC_WRITE_ONLY
			);
	}
}
<|endoftext|>


<commit_before>/**
 * @file base.hpp
 * @author Vahid Bastani
 *
 * Base class for resampling method
 *
 * J. D. Hol, T. B. Schon and F. Gustafsson, "On Resampling Algorithms for
 * Particle Filters," Nonlinear Statistical Signal Processing Workshop, 2006
 * IEEE, Cambridge, UK, 2006, pp. 79-82
 */
#ifndef SSMPACK_FILTER_RESAMPLER_BASE
#define SSMPACK_FILTER_RESAMPLER_BASE

#include <armadillo>

namespace ssmpack {
namespace filter {
namespace resampler {

/** Base resampling class
 */
template<class T>
class BaseResampler;

template <template <class> class Method, class Criterion>
class BaseResampler<Method<Criterion>> {
  protected:
  Criterion criterion_;

  public:
   BaseResampler(Criterion criterion) : criterion_{criterion} {}

   template <class Particles, class Weights>
   void operator()(Particles &pars, Weights &w) {
     // return if resampling criterion is false
     if (!criterion_(w))
       return;

     // generate ordered numbers
     auto u = static_cast<Method<Criterion> *>(this)
                  ->generateOrderedNumbers(w.n_rows);

     auto ws = arma::cumsum(w);
     auto u_it = u.begin();

     Particles old_pars = pars;

     pars.each_col([&u_it, &old_pars,
                    &ws](arma::Col<typename Particles::elem_type> &col) {
       col = old_pars.col(
           static_cast<arma::uvec>(arma::find(ws > *u_it++, 1, "first"))(0));
     });

     w.fill(1.0 / w.n_rows);
   }
};

} // namespace resampler
} // namespace filter
} // namespace ssmpack
#endif //SSMPACK_FILTER_RESAMPLER_IDENTITY
<commit_msg>correcting criterion initialization in resampling base class<commit_after>/**
 * @file base.hpp
 * @author Vahid Bastani
 *
 * Base class for resampling method
 *
 * J. D. Hol, T. B. Schon and F. Gustafsson, "On Resampling Algorithms for
 * Particle Filters," Nonlinear Statistical Signal Processing Workshop, 2006
 * IEEE, Cambridge, UK, 2006, pp. 79-82
 */
#ifndef SSMPACK_FILTER_RESAMPLER_BASE
#define SSMPACK_FILTER_RESAMPLER_BASE

#include <armadillo>

namespace ssmpack {
namespace filter {
namespace resampler {

/** Base resampling class
 */
template<class T>
class BaseResampler;

template <template <class> class Method, class Criterion>
class BaseResampler<Method<Criterion>> {
  protected:
  Criterion criterion_;

  public:
   BaseResampler(Criterion criterion) : criterion_(std::move(criterion)) {}

   template <class Particles, class Weights>
   void operator()(Particles &pars, Weights &w) {
     // return if resampling criterion is false
     if (!criterion_(w))
       return;

     // generate ordered numbers
     auto u = static_cast<Method<Criterion> *>(this)
                  ->generateOrderedNumbers(w.n_rows);

     auto ws = arma::cumsum(w);
     auto u_it = u.begin();

     Particles old_pars = pars;

     pars.each_col([&u_it, &old_pars,
                    &ws](arma::Col<typename Particles::elem_type> &col) {
       col = old_pars.col(
           static_cast<arma::uvec>(arma::find(ws > *u_it++, 1, "first"))(0));
     });

     w.fill(1.0 / w.n_rows);
   }
};

} // namespace resampler
} // namespace filter
} // namespace ssmpack
#endif //SSMPACK_FILTER_RESAMPLER_IDENTITY
<|endoftext|>