text:
lang: en
layout: post
title: "Python Object Oriented Programming"
date: 2019-09-19 22:07:39 -0700
category: Python_Programming
img: /static/IMG/python_snake.jpg
color: green
theme_color: "#4CAF50"
prism: true
tags:
- Python
- Tutorial
---

# Python Object Oriented Programming
As we all know Python is Object Oriented Programming language. But you won't believe we are using Python OOP from our first program itself. For example if you try following snippet you will get what I am saying.

x = 2
print(type(x))

It will give you following result: ```<class 'int'>```

**You can see this in any data item like list, tuple, dictionary sets ...etc**. That is each datatype is belongs to a class. For example **append** is a method within the class named list. We will discuss what is method in this post later.

{% include MyNote.html note_type="success" span_note="Important:" text="In Python, all data items are objects, and each object is an instance of a class. The importance of classes is: by defining your own class, you define a fundamental new data type." %}

## How do we create simple class?
Using class keyword we can create new class. The syntax of class is given below:

class class_name:
	method_definitions

Let us create our own class,

class Employee:
	pass

{% include MyNote.html note_type="info" span_note="Info: " text="The keyword pass is a kind of placeholder. It says, "There's nothing more to do here for now; I'll come back and add things later." Or, you might just use it as a permanent no-op (no operation). Occasionally this is needed because Python has no statement terminator; therefore, it has no way to specify a blank statement other than pass." %}

Let us create a new objects of our class Employee:

employee1 = Employee()
employee2 = Employee()

Let us check whether we are created instances of class Employee successfully:

print(type(employee1))

This will give you something like ```<class '__main__.Employee'>```. Then it is perfect.

Now it is the time to create instance variables. Instance variables are used for attach data to individual objects. Using these instance variable we can attach data field directly to at runtime. Instances are written outside class.

employee1.firstName = 'Arun'
employee1.lastName = 'Soman'
employee1.email = employee1.firstName + employee1.lastName+'@company.com'

employee2.firstName = 'Anuja'
employee2.lastName = 'Soman'
employee2.email = employee2.firstName + employee2.lastName+'@company.com'

print(employee1.email)
print(employee2.email)

Our primary concern is to reduce number of lines in the program. So it is not a good way to write program. In next post we will discuss about ***self obsession***  and how to reduce number of lines in the program using Python **default constructor** called *__init__* .

## Writing Methods Inside Class
Writing a method is how we give objects of a class the ability to respond to
messages; another way of saying this is that methods give objects of a class
behavior.

{% include MyNote.html note_type="info" span_note="Info: " text="In Python, as elsewhere, methods are functions defined inside class definitions-even though they may be called through an object (an "instance method")." %}

Python supports following types of methods
1. Regular Methods
2. Class Methods and
3. Static Methods

We will discuss about all of the above methods in upcoming blog posts. Let us create a regular method by extending our previous program.

class Employee:
	def fullName(firstName, lastName):
		return firstName + ' '+  lastName

# instances or objects
employee1 = Employee()
employee2 = Employee()

# instance variables of employee1
employee1.firstName = 'Arun'
employee1.lastName = 'Soman'

# instance variables of employee2
employee2.firstName = 'Anuja'
employee2.lastName = 'Soman'

# calling method in the class
print(Employee.fullName(employee1.firstName,employee1.lastName))

# calling method in the class
print(Employee.fullName(employee2.firstName,employee2.lastName))

In the program given above, we created an Employee class. In the main program we can see instances of Employee class. Using those instances we created new instance variables called firstname and lastname. Next we wrote a method called fullname in the class in order to concatenate firstname and lastname. In the last two print statement the method fullname is called. As I mentioned earlier, we cooked up this program by writing instance variable over and over again which is not a good idea. How to eradicate this problem? See our next post for solution.

Reference:


text:
package me.manuelp.siftj;

import static fj.data.List.iterableList;

import fj.F2;
import java.util.List;

/**
 * Defines some generic filtering functions on {@link Filter}s.
 */
public class Filters {
  /**
   * Generic type-safe filtering higher-order function to apply a single {@link Filter} to a list of values.
   *
   * @param filter {@link Filter} to apply to every single value
   * @param values List of values
   * @param <T> Type of values to be filtered
   * @return Filtered list of the original values that satisfies the given filter predicate
   */
  public static <T> List<T> filter(Filter<T> filter, List<T> values) {
    return iterableList(values).filter(filter).toJavaList();
  }

  /**
   * Creates an AND combinator for two {@link Filter}s on the same type.
   *
   * @param <T> Type parameter of {@link Filter}s to combine
   * @return AND combinator
   */
  public static <T> F2<Filter<T>, Filter<T>, Filter<T>> andCombinator() {
    return new F2<Filter<T>, Filter<T>, Filter<T>>() {
      @Override
      public Filter<T> f(final Filter<T> x, final Filter<T> y) {
        return new Filter<T>() {
          @Override
          public Boolean f(T v) {
            return x.f(v) && y.f(v);
          }
        };
      }
    };
  }

  /**
   * Compose in AND multiple filters on the same type in a single filter.
   *
   * @param filters Filters to combine (in AND).
   * @param <T> Type of values that filters can match against.
   * @return Filter obtained by composing in AND all input filters
   */
  public static <T> Filter<T> and(final List<Filter<T>> filters) {
    return new Filter<T>() {
      @Override
      public Boolean f(T t) {
        return iterableList(filters).foldLeft(Filters.<T> andCombinator(), NonFilter.<T> nonFilter(true)).f(t);
      }
    };
  }

  /**
   * Creates an OR combinator for two {@link Filter}s on the same type.
   *
   * @param <T> Type parameter of {@link Filter}s to combine
   * @return OR combinator
   */
  public static <T> F2<Filter<T>, Filter<T>, Filter<T>> orCombinator() {
    return new F2<Filter<T>, Filter<T>, Filter<T>>() {
      @Override
      public Filter<T> f(final Filter<T> x, final Filter<T> y) {
        return new Filter<T>() {
          @Override
          public Boolean f(T v) {
            return x.f(v) || y.f(v);
          }
        };
      }
    };
  }

  /**
   * Compose in OR multiple filters on the same type in a single filter.
   *
   * @param filters Filters to combine (in OR).
   * @param <T> Type of values that filters can match against.
   * @return Filter obtained by composing in OR all input filters
   */
  public static <T> Filter<T> or(final List<Filter<T>> filters) {
    if (filters.isEmpty())
      return NonFilter.<T> nonFilter(true);

    return new Filter<T>() {
      @Override
      public Boolean f(T t) {
        return iterableList(filters).foldLeft(Filters.<T> orCombinator(), NonFilter.<T> nonFilter(false)).f(t);
      }
    };
  }

  /**
   * Generic type-safe filtering functions to apply a list of {@link Filter filters} in AND to a list of values.
   *
   * @param filters List of {@link Filter filters} combined with {@link #andCombinator()} to apply to every value
   * @param values List of values
   * @param <T> Type of the values to filter
   * @return List of values that satisfy all given filter predicates
   */
  public static <T> List<T> filter(List<Filter<T>> filters, List<T> values) {
    return filter(and(filters), values);
  }
}

redpajama_set_name: RedPajamaGithub


text:
using namespace arangodb::cache;

const uint64_t Cache::minSize = 16384;
const uint64_t Cache::minLogSize = 14;

uint64_t Cache::_findStatsCapacity = 16384;

Cache::ConstructionGuard::ConstructionGuard() {}

Cache::Cache(ConstructionGuard guard, Manager* manager, uint64_t id,
             Metadata&& metadata, std::shared_ptr<Table> table, bool enableWindowedStats,
             std::function<Table::BucketClearer(Metadata*)> bucketClearer, size_t slotsPerBucket)
    : _taskLock(),
      _shutdown(false),
      _enableWindowedStats(enableWindowedStats),
      _findStats(nullptr),
      _findHits(),
      _findMisses(),
      _manager(manager),
      _id(id),
      _metadata(std::move(metadata)),
      _tableShrdPtr(std::move(table)),
      _table(_tableShrdPtr.get()),
      _bucketClearer(bucketClearer(&_metadata)),
      _slotsPerBucket(slotsPerBucket),
      _insertsTotal(),
      _insertEvictions(),
      _migrateRequestTime(std::chrono::steady_clock::now().time_since_epoch().count()),
      _resizeRequestTime(std::chrono::steady_clock::now().time_since_epoch().count()) {
  _tableShrdPtr->setTypeSpecifics(_bucketClearer, _slotsPerBucket);
  _tableShrdPtr->enable();
  if (_enableWindowedStats) {
    try {
      _findStats.reset(new StatBuffer(_findStatsCapacity));
    } catch (std::bad_alloc const&) {
      _findStats.reset(nullptr);
      _enableWindowedStats = false;
    }
  }
}

uint64_t Cache::size() const {
  if (isShutdown()) {
    return 0;
  }

  _metadata.readLock();
  uint64_t size = _metadata.allocatedSize;
  _metadata.readUnlock();

  return size;
}

uint64_t Cache::usageLimit() const {
  if (isShutdown()) {
    return 0;
  }

  _metadata.readLock();
  uint64_t limit = _metadata.softUsageLimit;
  _metadata.readUnlock();

  return limit;
}

uint64_t Cache::usage() const {
  if (isShutdown()) {
    return false;
  }

  _metadata.readLock();
  uint64_t usage = _metadata.usage;
  _metadata.readUnlock();

  return usage;
}

void Cache::sizeHint(uint64_t numElements) {
  if (isShutdown()) {
    return;
  }

  uint64_t numBuckets = static_cast<uint64_t>(
      static_cast<double>(numElements) /
      (static_cast<double>(_slotsPerBucket) * Table::idealUpperRatio));
  uint32_t requestedLogSize = 0;
  for (; (static_cast<uint64_t>(1) << requestedLogSize) < numBuckets; requestedLogSize++) {
  }
  requestMigrate(requestedLogSize);
}

std::pair<double, double> Cache::hitRates() {
  double lifetimeRate = std::nan("");
  double windowedRate = std::nan("");

  uint64_t currentMisses = _findMisses.value(std::memory_order_relaxed);
  uint64_t currentHits = _findHits.value(std::memory_order_relaxed);
  if (currentMisses + currentHits > 0) {
    lifetimeRate = 100 * (static_cast<double>(currentHits) /
                          static_cast<double>(currentHits + currentMisses));
  }

  if (_enableWindowedStats && _findStats) {
    auto stats = _findStats->getFrequencies();
    if (stats.size() == 1) {
      if (stats[0].first == static_cast<uint8_t>(Stat::findHit)) {
        windowedRate = 100.0;
      } else {
        windowedRate = 0.0;
      }
    } else if (stats.size() == 2) {
      if (stats[0].first == static_cast<uint8_t>(Stat::findHit)) {
        currentHits = stats[0].second;
        currentMisses = stats[1].second;
      } else {
        currentHits = stats[1].second;
        currentMisses = stats[0].second;
      }
      if (currentHits + currentMisses > 0) {
        windowedRate = 100 * (static_cast<double>(currentHits) /
                              static_cast<double>(currentHits + currentMisses));
      }
    }
  }

  return std::pair<double, double>(lifetimeRate, windowedRate);
}

bool Cache::isResizing() {
  if (isShutdown()) {
    return false;
  }

  _metadata.readLock();
  bool resizing = _metadata.isResizing();
  _metadata.readUnlock();

  return resizing;
}

bool Cache::isMigrating() {
  if (isShutdown()) {
    return false;
  }

  _metadata.readLock();
  bool migrating = _metadata.isMigrating();
  _metadata.readUnlock();

  return migrating;
}

bool Cache::isBusy() {
  if (isShutdown()) {
    return false;
  }

  _metadata.readLock();
  bool busy = _metadata.isResizing() || _metadata.isMigrating();
  _metadata.readUnlock();

  return busy;
}

void Cache::destroy(std::shared_ptr<Cache> cache) {
  if (cache) {
    cache->shutdown();
  }
}

void Cache::requestGrow() {
  // fail fast if inside banned window
  if (isShutdown() || std::chrono::steady_clock::now().time_since_epoch().count() <=
                          _resizeRequestTime.load()) {
    return;
  }

  if (_taskLock.writeLock(Cache::triesSlow)) {
    if (std::chrono::steady_clock::now().time_since_epoch().count() >
        _resizeRequestTime.load()) {
      _metadata.readLock();
      bool ok = !_metadata.isResizing();
      _metadata.readUnlock();
      if (ok) {
        auto result = _manager->requestGrow(this);
        _resizeRequestTime.store(result.second.time_since_epoch().count());
      }
    }
    _taskLock.writeUnlock();
  }
}

void Cache::requestMigrate(uint32_t requestedLogSize) {
  // fail fast if inside banned window
  if (isShutdown() || std::chrono::steady_clock::now().time_since_epoch().count() <=
                          _migrateRequestTime.load()) {
    return;
  }

  if (_taskLock.writeLock(Cache::triesGuarantee)) {
    if (std::chrono::steady_clock::now().time_since_epoch().count() >
        _migrateRequestTime.load()) {
      cache::Table* table = _table.load(std::memory_order_relaxed);
      TRI_ASSERT(table != nullptr);

      _metadata.readLock();
      bool ok = !_metadata.isMigrating() && (requestedLogSize != table->logSize());
      _metadata.readUnlock();
      if (ok) {
        auto result = _manager->requestMigrate(this, requestedLogSize);
        _migrateRequestTime.store(result.second.time_since_epoch().count());
      }
    }
    _taskLock.writeUnlock();
  }
}

void Cache::freeValue(CachedValue* value) {
  while (!value->isFreeable()) {
    std::this_thread::yield();
  }

  delete value;
}

bool Cache::reclaimMemory(uint64_t size) {
  _metadata.readLock();
  _metadata.adjustUsageIfAllowed(-static_cast<int64_t>(size));
  bool underLimit = (_metadata.softUsageLimit >= _metadata.usage);
  _metadata.readUnlock();

  return underLimit;
}

uint32_t Cache::hashKey(void const* key, size_t keySize) const {
  return (std::max)(static_cast<uint32_t>(1), fasthash32(key, keySize, 0xdeadbeefUL));
}

void Cache::recordStat(Stat stat) {
  if ((basics::SharedPRNG::rand() & static_cast<unsigned long>(7)) != 0) {
    return;
  }

  switch (stat) {
    case Stat::findHit: {
      _findHits.add(1, std::memory_order_relaxed);
      if (_enableWindowedStats && _findStats) {
        _findStats->insertRecord(static_cast<uint8_t>(Stat::findHit));
      }
      _manager->reportHitStat(Stat::findHit);
      break;
    }
    case Stat::findMiss: {
      _findMisses.add(1, std::memory_order_relaxed);
      if (_enableWindowedStats && _findStats) {
        _findStats->insertRecord(static_cast<uint8_t>(Stat::findMiss));
      }
      _manager->reportHitStat(Stat::findMiss);
      break;
    }
    default: { break; }
  }
}

bool Cache::reportInsert(bool hadEviction) {
  bool shouldMigrate = false;
  if (hadEviction) {
    _insertEvictions.add(1, std::memory_order_relaxed);
  }
  _insertsTotal.add(1, std::memory_order_relaxed);
  if ((basics::SharedPRNG::rand() & _evictionMask) == 0) {
    uint64_t total = _insertsTotal.value(std::memory_order_relaxed);
    uint64_t evictions = _insertEvictions.value(std::memory_order_relaxed);
    if ((static_cast<double>(evictions) / static_cast<double>(total)) > _evictionRateThreshold) {
      shouldMigrate = true;
      cache::Table* table = _table.load(std::memory_order_relaxed);
      TRI_ASSERT(table != nullptr);
      table->signalEvictions();
    }
    _insertEvictions.reset(std::memory_order_relaxed);
    _insertsTotal.reset(std::memory_order_relaxed);
  }

  return shouldMigrate;
}

Metadata* Cache::metadata() { return &_metadata; }

std::shared_ptr<Table> Cache::table() const {
  return std::atomic_load(&_tableShrdPtr);
}

void Cache::shutdown() {
  _taskLock.writeLock();
  auto handle = shared_from_this();  // hold onto self-reference to prevent
                                     // pre-mature shared_ptr destruction
  TRI_ASSERT(handle.get() == this);
  if (!_shutdown.exchange(true)) {
    _metadata.readLock();
    while (true) {
      if (!_metadata.isMigrating() && !_metadata.isResizing()) {
        break;
      }
      _metadata.readUnlock();
      _taskLock.writeUnlock();
      std::this_thread::sleep_for(std::chrono::microseconds(10));
      _taskLock.writeLock();
      _metadata.readLock();
    }
    _metadata.readUnlock();

    cache::Table* table = _table.load(std::memory_order_relaxed);
    if (table != nullptr) {
      std::shared_ptr<Table> extra = table->setAuxiliary(std::shared_ptr<Table>(nullptr));
      if (extra) {
        extra->clear();
        _manager->reclaimTable(extra);
      }
      table->clear();
    }

    _manager->reclaimTable(std::atomic_load(&_tableShrdPtr));
    _metadata.writeLock();
    _metadata.changeTable(0);
    _metadata.writeUnlock();
    _manager->unregisterCache(_id);
    _table.store(nullptr, std::memory_order_relaxed);
  }

  _taskLock.writeUnlock();
}

bool Cache::canResize() {
  if (isShutdown()) {
    return false;
  }

  bool allowed = true;
  _metadata.readLock();
  if (_metadata.isResizing() || _metadata.isMigrating()) {
    allowed = false;
  }
  _metadata.readUnlock();

  return allowed;
}

bool Cache::canMigrate() {
  if (isShutdown()) {
    return false;
  }

  bool allowed = true;
  _metadata.readLock();
  if (_metadata.isMigrating()) {
    allowed = false;
  }
  _metadata.readUnlock();

  return allowed;
}

bool Cache::freeMemory() {
  if (isShutdown()) {
    return false;
  }

  bool underLimit = reclaimMemory(0ULL);
  uint64_t failures = 0;
  while (!underLimit) {
    // pick a random bucket
    uint32_t randomHash = RandomGenerator::interval(UINT32_MAX);
    uint64_t reclaimed = freeMemoryFrom(randomHash);

    if (reclaimed > 0) {
      failures = 0;
      underLimit = reclaimMemory(reclaimed);
    } else {
      failures++;
      if (failures > 100) {
        if (isShutdown()) {
          break;
        } else {
          failures = 0;
        }
      }
    }
  }

  return true;
}

bool Cache::migrate(std::shared_ptr<Table> newTable) {
  if (isShutdown()) {
    return false;
  }

  newTable->setTypeSpecifics(_bucketClearer, _slotsPerBucket);
  newTable->enable();

  cache::Table* table = _table.load(std::memory_order_relaxed);
  TRI_ASSERT(table != nullptr);
  table->setAuxiliary(newTable);

  // do the actual migration
  for (uint32_t i = 0; i < table->size(); i++) {
    migrateBucket(table->primaryBucket(i), table->auxiliaryBuckets(i), newTable);
  }

  // swap tables
  _taskLock.writeLock();
  _table.store(newTable.get(), std::memory_order_relaxed);
  std::shared_ptr<Table> oldTable = std::atomic_exchange(&_tableShrdPtr, newTable);
  std::shared_ptr<Table> confirm =
      oldTable->setAuxiliary(std::shared_ptr<Table>(nullptr));
  _taskLock.writeUnlock();

  // clear out old table and release it
  oldTable->clear();
  _manager->reclaimTable(oldTable);

  // unmarking migrating flag
  _metadata.writeLock();
  _metadata.changeTable(table->memoryUsage());
  _metadata.toggleMigrating();
  _metadata.writeUnlock();

  return true;
}


text:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.valid4j</groupId>
    <artifactId>json-path-matchers</artifactId>
    <version>1.2-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>${project.groupId}:${project.artifactId}</name>
    <url>https://github.com/valid4j/json-path-matchers</url>
    <description>Matchers to test your JSON using json path expressions (based on jayway.jsonpath)</description>
    <inceptionYear>2016</inceptionYear>

    <prerequisites>
        <maven>2.2.1</maven>
    </prerequisites>

    <licenses>
        <license>
            <name>Apache Software License, Version 2.0</name>
            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
            <distribution>repo</distribution>
        </license>
    </licenses>

    <organization>
        <name>valid4j</name>
        <url>http://valid4j.org</url>
    </organization>

    <developers>
        <developer>
            <id>helsing</id>
            <name>Patrik Helsing</name>
            <email>patrik@helsing.se</email>
        </developer>
        <developer>
            <id>guranxp</id>
            <name>Göran Persson</name>
            <email>guranxp@gmail.com</email>
        </developer>
    </developers>

    <scm>
        <connection>scm:git:git://github.com/valid4j/json-path-matchers.git</connection>
        <developerConnection>scm:git:git@github.com:valid4j/json-path-matchers.git</developerConnection>
        <url>http://github.com/valid4j/json-path-matchers/tree/master</url>
    </scm>

    <issueManagement>
        <system>github</system>
        <url>https://github.com/valid4j/json-path-matchers/issues</url>
    </issueManagement>

    <distributionManagement>
        <snapshotRepository>
            <id>ossrh</id>
            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
        </snapshotRepository>
        <repository>
            <id>ossrh</id>
            <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
        </repository>
    </distributionManagement>

    <properties>
        <github.global.server>github</github.global.server>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-library</artifactId>
            <version>1.3</version>
        </dependency>
        <dependency>
            <groupId>com.jayway.jsonpath</groupId>
            <artifactId>json-path</artifactId>
            <version>2.1.0</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <encoding>${project.build.sourceEncoding}</encoding>
                    <source>1.6</source>
                    <target>1.6</target>
                    <compilerVersion>1.6</compilerVersion>
                    <showDeprecation>true</showDeprecation>
                    <showWarnings>true</showWarnings>
                    <debug>false</debug>
                    <fork>false</fork>
                    <compilerArgument>-Xlint:-options</compilerArgument>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.17</version>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <id>release</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-source-plugin</artifactId>
                        <version>2.2.1</version>
                        <executions>
                            <execution>
                                <id>attach-sources</id>
                                <goals>
                                    <goal>jar-no-fork</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-javadoc-plugin</artifactId>
                        <version>2.9.1</version>
                        <configuration>
                            <quiet>true</quiet>
                        </configuration>
                        <executions>
                            <execution>
                                <id>attach-javadocs</id>
                                <goals>
                                    <goal>jar</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-gpg-plugin</artifactId>
                        <version>1.5</version>
                        <executions>
                            <execution>
                                <id>sign-artifacts</id>
                                <phase>verify</phase>
                                <goals>
                                    <goal>sign</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>

</project>


text:
#ifndef _MVNETA_BM_H_
#define _MVNETA_BM_H_

/* BM Configuration Register */
#define MVNETA_BM_CONFIG_REG			0x0
#define    MVNETA_BM_STATUS_MASK		0x30
#define    MVNETA_BM_ACTIVE_MASK		BIT(4)
#define    MVNETA_BM_MAX_IN_BURST_SIZE_MASK	0x60000
#define    MVNETA_BM_MAX_IN_BURST_SIZE_16BP	BIT(18)
#define    MVNETA_BM_EMPTY_LIMIT_MASK		BIT(19)

/* BM Activation Register */
#define MVNETA_BM_COMMAND_REG			0x4
#define    MVNETA_BM_START_MASK			BIT(0)
#define    MVNETA_BM_STOP_MASK			BIT(1)
#define    MVNETA_BM_PAUSE_MASK			BIT(2)

/* BM Xbar interface Register */
#define MVNETA_BM_XBAR_01_REG			0x8
#define MVNETA_BM_XBAR_23_REG			0xc
#define MVNETA_BM_XBAR_POOL_REG(pool)		\
		(((pool) < 2) ? MVNETA_BM_XBAR_01_REG : MVNETA_BM_XBAR_23_REG)
#define     MVNETA_BM_TARGET_ID_OFFS(pool)	(((pool) & 1) ? 16 : 0)
#define     MVNETA_BM_TARGET_ID_MASK(pool)	\
		(0xf << MVNETA_BM_TARGET_ID_OFFS(pool))
#define     MVNETA_BM_TARGET_ID_VAL(pool, id)	\
		((id) << MVNETA_BM_TARGET_ID_OFFS(pool))
#define     MVNETA_BM_XBAR_ATTR_OFFS(pool)	(((pool) & 1) ? 20 : 4)
#define     MVNETA_BM_XBAR_ATTR_MASK(pool)	\
		(0xff << MVNETA_BM_XBAR_ATTR_OFFS(pool))
#define     MVNETA_BM_XBAR_ATTR_VAL(pool, attr)	\
		((attr) << MVNETA_BM_XBAR_ATTR_OFFS(pool))

/* Address of External Buffer Pointers Pool Register */
#define MVNETA_BM_POOL_BASE_REG(pool)		(0x10 + ((pool) << 4))
#define     MVNETA_BM_POOL_ENABLE_MASK		BIT(0)

/* External Buffer Pointers Pool RD pointer Register */
#define MVNETA_BM_POOL_READ_PTR_REG(pool)	(0x14 + ((pool) << 4))
#define     MVNETA_BM_POOL_SET_READ_PTR_MASK	0xfffc
#define     MVNETA_BM_POOL_GET_READ_PTR_OFFS	16
#define     MVNETA_BM_POOL_GET_READ_PTR_MASK	0xfffc0000

/* External Buffer Pointers Pool WR pointer */
#define MVNETA_BM_POOL_WRITE_PTR_REG(pool)	(0x18 + ((pool) << 4))
#define     MVNETA_BM_POOL_SET_WRITE_PTR_OFFS	0
#define     MVNETA_BM_POOL_SET_WRITE_PTR_MASK	0xfffc
#define     MVNETA_BM_POOL_GET_WRITE_PTR_OFFS	16
#define     MVNETA_BM_POOL_GET_WRITE_PTR_MASK	0xfffc0000

/* External Buffer Pointers Pool Size Register */
#define MVNETA_BM_POOL_SIZE_REG(pool)		(0x1c + ((pool) << 4))
#define     MVNETA_BM_POOL_SIZE_MASK		0x3fff

/* BM Interrupt Cause Register */
#define MVNETA_BM_INTR_CAUSE_REG		(0x50)

/* BM interrupt Mask Register */
#define MVNETA_BM_INTR_MASK_REG			(0x54)

/* Other definitions */
#define MVNETA_BM_SHORT_PKT_SIZE		256
#define MVNETA_BM_POOLS_NUM			4
#define MVNETA_BM_POOL_CAP_MIN			128
#define MVNETA_BM_POOL_CAP_DEF			2048
#define MVNETA_BM_POOL_CAP_MAX			\
		(16 * 1024 - MVNETA_BM_POOL_CAP_ALIGN)
#define MVNETA_BM_POOL_CAP_ALIGN		32
#define MVNETA_BM_POOL_PTR_ALIGN		32

#define MVNETA_BM_POOL_ACCESS_OFFS		8

#define MVNETA_BM_BPPI_SIZE			0x100000

#define MVNETA_RX_BUF_SIZE(pkt_size)   ((pkt_size) + NET_SKB_PAD)

enum mvneta_bm_type {
	MVNETA_BM_FREE,
	MVNETA_BM_LONG,
	MVNETA_BM_SHORT
};

struct mvneta_bm {
	void __iomem *reg_base;
	struct clk *clk;
	struct platform_device *pdev;

	struct gen_pool *bppi_pool;
	/* BPPI virtual base address */
	void __iomem *bppi_virt_addr;
	/* BPPI physical base address */
	dma_addr_t bppi_phys_addr;

	/* BM pools */
	struct mvneta_bm_pool *bm_pools;
};

struct mvneta_bm_pool {
	struct hwbm_pool hwbm_pool;
	/* Pool number in the range 0-3 */
	u8 id;
	enum mvneta_bm_type type;

	/* Packet size */
	int pkt_size;
	/* Size of the buffer acces through DMA*/
	u32 buf_size;

	/* BPPE virtual base address */
	u32 *virt_addr;
	/* BPPE physical base address */
	dma_addr_t phys_addr;

	/* Ports using BM pool */
	u8 port_map;

	struct mvneta_bm *priv;
};

/* Declarations and definitions */
void *mvneta_frag_alloc(unsigned int frag_size);
void mvneta_frag_free(unsigned int frag_size, void *data);

#if defined(CONFIG_MVNETA_BM) || defined(CONFIG_MVNETA_BM_MODULE)
void mvneta_bm_pool_destroy(struct mvneta_bm *priv,
			    struct mvneta_bm_pool *bm_pool, u8 port_map);
void mvneta_bm_bufs_free(struct mvneta_bm *priv, struct mvneta_bm_pool *bm_pool,
			 u8 port_map);
int mvneta_bm_construct(struct hwbm_pool *hwbm_pool, void *buf);
int mvneta_bm_pool_refill(struct mvneta_bm *priv,
			  struct mvneta_bm_pool *bm_pool);
struct mvneta_bm_pool *mvneta_bm_pool_use(struct mvneta_bm *priv, u8 pool_id,
					  enum mvneta_bm_type type, u8 port_id,
					  int pkt_size);

static inline void mvneta_bm_pool_put_bp(struct mvneta_bm *priv,
					 struct mvneta_bm_pool *bm_pool,
					 dma_addr_t buf_phys_addr)
{
	writel_relaxed(buf_phys_addr, priv->bppi_virt_addr +
		       (bm_pool->id << MVNETA_BM_POOL_ACCESS_OFFS));
}

static inline u32 mvneta_bm_pool_get_bp(struct mvneta_bm *priv,
					struct mvneta_bm_pool *bm_pool)
{
	return readl_relaxed(priv->bppi_virt_addr +
			     (bm_pool->id << MVNETA_BM_POOL_ACCESS_OFFS));
}
#else
void mvneta_bm_pool_destroy(struct mvneta_bm *priv,
			    struct mvneta_bm_pool *bm_pool, u8 port_map) {}
void mvneta_bm_bufs_free(struct mvneta_bm *priv, struct mvneta_bm_pool *bm_pool,
			 u8 port_map) {}
int mvneta_bm_construct(struct hwbm_pool *hwbm_pool, void *buf) { return 0; }
int mvneta_bm_pool_refill(struct mvneta_bm *priv,
			  struct mvneta_bm_pool *bm_pool) {return 0; }
struct mvneta_bm_pool *mvneta_bm_pool_use(struct mvneta_bm *priv, u8 pool_id,
					  enum mvneta_bm_type type, u8 port_id,
					  int pkt_size) { return NULL; }

static inline void mvneta_bm_pool_put_bp(struct mvneta_bm *priv,
					 struct mvneta_bm_pool *bm_pool,
					 dma_addr_t buf_phys_addr) {}

static inline u32 mvneta_bm_pool_get_bp(struct mvneta_bm *priv,
					struct mvneta_bm_pool *bm_pool)
{ return 0; }
#endif /* CONFIG_MVNETA_BM */
#endif


text:
@import './mixins/responsive-utils';
@import './variables';

/* variables */
$xs-padding: 1.93rem;
$sm-padding-xs: 1.5rem 2rem;
$sm-padding-md: 2.5rem;
/* end */

.panel {
  background-color: $brand-lighter-grey;
  border-color: $brand-white;

  @include responsive(sm) {
    border-color: $brand-light-grey;
  }

  @include responsive(md) {
    background-color: $brand-white;
  }
}

.xs {
  padding: $xs-padding;
}

.sm {
  padding: $sm-padding-xs;

  @include responsive(md) {
    padding: $sm-padding-md;
  }
}


text:
// Code generated by go-swagger; DO NOT EDIT.

package cluster

// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command

import (
	"fmt"
	"io"

	"github.com/go-openapi/runtime"
	"github.com/go-openapi/strfmt"

	"github.com/netapp/trident/storage_drivers/ontap/api/rest/models"
)

// NodeGetReader is a Reader for the NodeGet structure.
type NodeGetReader struct {
	formats strfmt.Registry
}

// ReadResponse reads a server response into the received o.
func (o *NodeGetReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
	switch response.Code() {
	case 200:
		result := NewNodeGetOK()
		if err := result.readResponse(response, consumer, o.formats); err != nil {
			return nil, err
		}
		return result, nil
	default:
		result := NewNodeGetDefault(response.Code())
		if err := result.readResponse(response, consumer, o.formats); err != nil {
			return nil, err
		}
		if response.Code()/100 == 2 {
			return result, nil
		}
		return nil, result
	}
}

// NewNodeGetOK creates a NodeGetOK with default headers values
func NewNodeGetOK() *NodeGetOK {
	return &NodeGetOK{}
}

/*
NodeGetOK describes a response with status code 200, with default header values.

OK
*/
type NodeGetOK struct {
	Payload *models.Node
}

// IsSuccess returns true when this node get o k response has a 2xx status code
func (o *NodeGetOK) IsSuccess() bool {
	return true
}

// IsRedirect returns true when this node get o k response has a 3xx status code
func (o *NodeGetOK) IsRedirect() bool {
	return false
}

// IsClientError returns true when this node get o k response has a 4xx status code
func (o *NodeGetOK) IsClientError() bool {
	return false
}

// IsServerError returns true when this node get o k response has a 5xx status code
func (o *NodeGetOK) IsServerError() bool {
	return false
}

// IsCode returns true when this node get o k response a status code equal to that given
func (o *NodeGetOK) IsCode(code int) bool {
	return code == 200
}

func (o *NodeGetOK) Error() string {
	return fmt.Sprintf("[GET /cluster/nodes/{uuid}][%d] nodeGetOK  %+v", 200, o.Payload)
}

func (o *NodeGetOK) String() string {
	return fmt.Sprintf("[GET /cluster/nodes/{uuid}][%d] nodeGetOK  %+v", 200, o.Payload)
}

func (o *NodeGetOK) GetPayload() *models.Node {
	return o.Payload
}

func (o *NodeGetOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {

	o.Payload = new(models.Node)

	// response payload
	if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
		return err
	}

	return nil
}

// NewNodeGetDefault creates a NodeGetDefault with default headers values
func NewNodeGetDefault(code int) *NodeGetDefault {
	return &NodeGetDefault{
		_statusCode: code,
	}
}

/*
NodeGetDefault describes a response with status code -1, with default header values.

Error
*/
type NodeGetDefault struct {
	_statusCode int

	Payload *models.ErrorResponse
}

// Code gets the status code for the node get default response
func (o *NodeGetDefault) Code() int {
	return o._statusCode
}

// IsSuccess returns true when this node get default response has a 2xx status code
func (o *NodeGetDefault) IsSuccess() bool {
	return o._statusCode/100 == 2
}

// IsRedirect returns true when this node get default response has a 3xx status code
func (o *NodeGetDefault) IsRedirect() bool {
	return o._statusCode/100 == 3
}

// IsClientError returns true when this node get default response has a 4xx status code
func (o *NodeGetDefault) IsClientError() bool {
	return o._statusCode/100 == 4
}

// IsServerError returns true when this node get default response has a 5xx status code
func (o *NodeGetDefault) IsServerError() bool {
	return o._statusCode/100 == 5
}

// IsCode returns true when this node get default response a status code equal to that given
func (o *NodeGetDefault) IsCode(code int) bool {
	return o._statusCode == code
}

func (o *NodeGetDefault) Error() string {
	return fmt.Sprintf("[GET /cluster/nodes/{uuid}][%d] node_get default  %+v", o._statusCode, o.Payload)
}

func (o *NodeGetDefault) String() string {
	return fmt.Sprintf("[GET /cluster/nodes/{uuid}][%d] node_get default  %+v", o._statusCode, o.Payload)
}

func (o *NodeGetDefault) GetPayload() *models.ErrorResponse {
	return o.Payload
}

func (o *NodeGetDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {

	o.Payload = new(models.ErrorResponse)

	// response payload
	if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
		return err
	}

	return nil
}


text:
/**
 @file
 @author  Nicholas Gillian <ngillian@media.mit.edu>
 @version 1.0

 @brief This file contains the GestureRecognitionPipeline class.

 The GestureRecognitionPipeline is the core module of the Gesture Recognition Toolkit.
 You can use the GestureRecognitionPipeline to link the various GRT modules together, for instace you can link a PreProcessing module to a FeatureExtraction
 module to a Classification module and then to a PostProcessing module.

 @example Tutorials/MachineLearning101/MachineLearning101.cpp
 */

/**
 GRT MIT License
 Copyright (c) <2012> <Nicholas Gillian, Media Lab, MIT>

 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.
 */

#ifndef GRT_GESTURE_RECOGNITION_PIPELINE_HEADER
#define GRT_GESTURE_RECOGNITION_PIPELINE_HEADER

#include "PreProcessing.h"
#include "FeatureExtraction.h"
#include "Classifier.h"
#include "Regressifier.h"
#include "Clusterer.h"
#include "PostProcessing.h"
#include "Context.h"
#include "../DataStructures/TimeSeriesClassificationDataStream.h"
#include "../Util/ClassificationResult.h"
#include "../Util/TestResult.h"

namespace GRT{

#define INSERT_AT_END_INDEX 99999

class GestureRecognitionPipeline : public GRTBase
{
public:
	/**
     Default Constructor
	*/
	GestureRecognitionPipeline(void);

	/**
     Copy Constructor. Performs a depp copy of the data from the rhs pipeline into this pipeline.
	*/
	GestureRecognitionPipeline(const GestureRecognitionPipeline &rhs);

	/**
     Default Destructor
	*/
    virtual ~GestureRecognitionPipeline(void);

	/**
     Equals Constructor. Performs a depp copy of the data from the rhs pipeline into this pipeline.
	*/
	GestureRecognitionPipeline& operator=(const GestureRecognitionPipeline &rhs);

    /**
     This is the main training interface for training a Classifier with ClassificationData.  This function will pass the trainingData through
     any PreProcessing or FeatureExtraction modules that have been added to the GestureRecognitionPipeline, and then calls the training function of
     the Classification module that has been added to the GestureRecognitionPipeline.
     The function will return true if the classifier was trained successfully, false otherwise.

	@param ClassificationData trainingData: the labelled classification training data that will be used to train the classifier at the core of the pipeline
	@return bool returns true if the classifier was trained successfully, false otherwise
	*/
    bool train(const ClassificationData &trainingData);

	/**
     This is the main training interface for training a Classifier with ClassificationData using K-fold cross validation.  This function will pass
     the trainingData through any PreProcessing or FeatureExtraction modules that have been added to the GestureRecognitionPipeline, and then calls the
     training function of the Classification module that has been added to the GestureRecognitionPipeline.
     The function will return true if the classifier was trained successfully, false otherwise.

	@param const ClassificationData &trainingData: the labelled classification training data that will be used to train the classifier at the core of the pipeline
	@param const UINT kFoldValue: the number of cross validation folds, this should be a value between in the range of [1 M-1], where M is the number of training samples int the LabelledClassificationData
	@param const bool useStratifiedSampling: sets if stratified sampling should be used during the cross validation training
	@return bool returns true if the classifier was trained successfully, false otherwise
	*/
    bool train(const ClassificationData &trainingData,const UINT kFoldValue,const bool useStratifiedSampling = false );

	/**
     This is the main training interface for training a Classifier with TimeSeriesClassificationData.  This function will pass
     the trainingData through any PreProcessing or FeatureExtraction modules that have been added to the GestureRecognitionPipeline, and then calls the
     training function of the Classification module that has been added to the GestureRecognitionPipeline.
     The function will return true if the classifier was trained successfully, false otherwise.

    @param const TimeSeriesClassificationData &trainingData: the labelled time-series classification training data that will be used to train the classifier at the core of the pipeline
    @return bool returns true if the classifier was trained successfully, false otherwise
	*/
    bool train(const TimeSeriesClassificationData &trainingData);

    /**
     This is the main training interface for training a Classifier with TimeSeriesClassificationData using K-fold cross validation.
     This function will pass the trainingData through any PreProcessing or FeatureExtraction modules that have been added to the GestureRecognitionPipeline, and then calls the training function of the Classification module that has been added to the GestureRecognitionPipeline.
     The function will return true if the classifier was trained successfully, false otherwise.

     @param const TimeSeriesClassificationData &trainingData: the labelled time-series classification training data that will be used to train the classifier at the core of the pipeline
     @param const UINT kFoldValue: the number of cross validation folds, this should be a value between in the range of [1 M-1], where M is the number of training samples in the LabelledClassificationData
     @param const bool useStratifiedSampling: sets if stratified sampling should be used during the cross validation training
     @return bool returns true if the classifier was trained and tested successfully, false otherwise
     */
    bool train(const TimeSeriesClassificationData &trainingData,const UINT kFoldValue,const bool useStratifiedSampling = false);

	/**
     This is the main training interface for training a regression module with RegressionData.  This function will pass
     the trainingData through any PreProcessing or FeatureExtraction modules that have been added to the GestureRecognitionPipeline, and then calls the
     training function of the regression module that has been added to the GestureRecognitionPipeline.
     The function will return true if the classifier was trained successfully, false otherwise.

    @param const RegressionData &trainingData: the labelled regression training data that will be used to train the regression module at the core of the pipeline
    @return bool returns true if the regression module was trained successfully, false otherwise
	*/
    bool train(const RegressionData &trainingData);

    /**
     This is the main training interface for training a Regressifier with RegressionData using K-fold cross validation.  This function will pass
     the trainingData through any PreProcessing or FeatureExtraction modules that have been added to the GestureRecognitionPipeline, and then calls the
     training function of the Regression module that has been added to the GestureRecognitionPipeline.
     The function will return true if the regressifier was trained successfully, false otherwise.

     @param const RegressionData &trainingData: the labelled regression training data that will be used to train the regressifier at the core of the pipeline
     @param const UINT kFoldValue: the number of cross validation folds, this should be a value between in the range of [1 M-1], where M is the number of training samples in the LabelledRegressionData
     @return bool returns true if the regressifier was trained and tested successfully, false otherwise
     */
    bool train(const RegressionData &trainingData,const UINT kFoldValue);

    /**
     This is the main training interface for training a Clusterer with UnlabelledData using K-fold cross validation.  This function will pass
     the trainingData through any PreProcessing or FeatureExtraction modules that have been added to the GestureRecognitionPipeline, and then calls the
     training function of the Clusterer module that has been added to the GestureRecognitionPipeline.
     The function will return true if the regressifier was trained successfully, false otherwise.

     @param const UnlabelledData &trainingData: the unlabelledData training data that will be used to train the clusterer at the core of the pipeline
     @return bool returns true if the clusterer was trained and tested successfully, false otherwise
     */
    bool train(const UnlabelledData &trainingData);

    /**
     This function is the main interface for testing the accuracy of a pipeline with ClassificationData.  This function will pass
     the testData through any PreProcessing or FeatureExtraction modules that have been added to the GestureRecognitionPipeline, and then calls the
     predict function of the classification module that has been added to the GestureRecognitionPipeline.
     The function will return true if the pipeline was tested successfully, false otherwise.

     @param const ClassificationData &testData: the labelled classification data that will be used to test the accuracy of the pipeline
     @return bool returns true if the pipeline was tested successfully, false otherwise
	*/
    bool test(const ClassificationData &testData);

    /**
     This function is the main interface for testing the accuracy of a pipeline with TimeSeriesClassificationData.  This function will pass
     the testData through any PreProcessing or FeatureExtraction modules that have been added to the GestureRecognitionPipeline, and then calls the
     predict function of the classification module that has been added to the GestureRecognitionPipeline.
     The function will return true if the pipeline was tested successfully, false otherwise.

     @param const TimeSeriesClassificationData &testData: the labelled timeseries classification data that will be used to test the accuracy of the pipeline
     @return bool returns true if the pipeline was tested successfully, false otherwise
	*/
    bool test(const TimeSeriesClassificationData &testData);

    /**
     This function is the main interface for testing the accuracy of a pipeline with TimeSeriesClassificationDataStream.  This function will pass
     the testData through any PreProcessing or FeatureExtraction modules that have been added to the GestureRecognitionPipeline, and then calls the
     predict function of the classification module that has been added to the GestureRecognitionPipeline.
     The function will return true if the pipeline was tested successfully, false otherwise.

     @param const TimeSeriesClassificationDataStreamStream &testData: the timeseries classification data stream that will be used to test the accuracy of the pipeline
     @return bool returns true if the pipeline was tested successfully, false otherwise
	*/
    bool test(const TimeSeriesClassificationDataStream &testData);

    /**
     This function is the main interface for testing the accuracy of a pipeline with RegressionData.  This function will pass
     the testData through any PreProcessing or FeatureExtraction modules that have been added to the GestureRecognitionPipeline, and then calls the
     predict function of the regression module that has been added to the GestureRecognitionPipeline.
     The function will return true if the pipeline was tested successfully, false otherwise.

     @param const RegressionData &testData: the labelled regression data that will be used to test the accuracy of the pipeline
     @return bool returns true if the pipeline was tested successfully, false otherwise
	*/
    bool test(const RegressionData &testData);

    /**
     This function is the main interface for all predictions using the gesture recognition pipeline.  You can use this function for both classification
     and regression.  You should only call this function if you  have trained the pipeline.  The input vector should be the same size as your training data.

     @param const VectorDouble &inputVector: the input data that will be passed through the pipeline for classification or regression
     @return bool returns true if the prediction was successful, false otherwise
	*/
    bool predict(const VectorDouble &inputVector);

    /**
     This function is an interface for predictions using timeseries or Matrix data.
     You should only call this function if you  have trained the pipeline.  The input matrix should have the same number of columns as your training data.

     @param const MatrixDouble &inputMatrix: the input atrix that will be passed through the pipeline for classification
     @return bool returns true if the prediction was successful, false otherwise
     */
    bool predict(const MatrixDouble &inputMatrix);

    /**
     This function is now depreciated, you should use the predict function instead.

     This function used to be the main interface for all regression using the gesture recognition pipeline.
     You should only call this function if you  have trained the pipeline.  The input vector should be the same size as your training data.

     @param const VectorDouble &inputVector: the input data that will be passed through the pipeline for regression
     @return bool returns true if the regression was successful, false otherwise
	*/
    bool map(const VectorDouble &inputVector);

    /**
     This function is the main interface for resetting the entire gesture recognition pipeline.  This function will call reset on all the modules in
     the current pipeline.

     @return bool returns true if the reset was successful, false otherwise
	*/
    bool reset();

    /**
     This function will save the entire pipeline to a file.  This includes all the modules types, settings, and models.
     This calls the older savePipelineToFile function.

     @param const string &filename: the name of the file you want to save the pipeline to
     @return bool returns true if the pipeline was saved successful, false otherwise
     */
    bool save(const string &filename) const;

    /**
     This function will save the entire pipeline to a file.  This includes all the modules types, settings, and models.

     @param const string &filename: the name of the file you want to save the pipeline to
     @return bool returns true if the pipeline was saved successful, false otherwise
	*/
    bool savePipelineToFile(const string &filename) const;

    /**
     This function will load an entire pipeline from a file.  This includes all the modules types, settings, and models.
     This calls the older loadPipelineFromFile function

     @param const string &filename: the name of the file you want to load the pipeline from
     @return bool returns true if the pipeline was loaded successful, false otherwise
     */
    bool load(const string &filename);

    /**
     This function will load an entire pipeline from a file.  This includes all the modules types, settings, and models.

     @param const string &filename: the name of the file you want to load the pipeline from
     @return bool returns true if the pipeline was loaded successful, false otherwise
	*/
    bool loadPipelineFromFile(const string &filename);

    /**
     This function will pass the input vector through any preprocessing or feature extraction modules added to the pipeline.  This function
     can be useful for testing and validating a preprocessing or feature extraction module, without having to acutally train a classification or
     regression module.  The second parameter controls if any feature extraction module should be used.  If set to true then both preprocessing and
     feature extraction modules will be used, if false then just preprocessing modules will be used.

     The function will not pass the preprocessed data through the classification or regression module.

     After calling this function, you can access the preprocessed results via the getPreProcessedData() or getFeatureExtractionData() functions.

     @param: VectorDouble inputVector: the input data that should be processed
     @param: bool computeFeatures: sets if just the preprocessing modules should be used (false), or both the preprocessing and feature extraction modules should be used (true)
     @return bool returns true if the data was passed through the preprocessing modules successful, false otherwise
	*/
    bool preProcessData(VectorDouble inputVector,bool computeFeatures = true);

    /**
    This function returns true if the pipeline has been initialized.  The pipeline is initialized if either a classifier or regressifier module has been set at the core of the pipeline.

    @return bool returns true if the pipeline has been initialized, false otherwise.
	*/
    bool getIsInitialized() const;

    /**
	 This function returns true if the classifier or regressifier at the core of the pipeline has been trained.

     @return bool returns true if the classifier or regressifier at the core of the pipeline has been trained, false otherwise.
     */
    bool getTrained() const;

    /**
	 This function returns true if any preprocessing modules have been added to the pipeline.

	@return bool returns true if any preprocessing modules have been added to the pipeline, false otherwise.
	*/
    bool getIsPreProcessingSet() const;

    /**
	 This function returns true if any feature extraction modules have been added to the pipeline.

	@return bool returns true if any feature extraction modules have been added to the pipeline, false otherwise.
	*/
    bool getIsFeatureExtractionSet() const;

    /**
	 This function returns true if a classifier has been added to the pipeline.

	@return bool returns true if a classifier has been added to the pipeline, false otherwise.
	*/
    bool getIsClassifierSet() const;

    /**
	 This function returns true if a regressifier has been added to the pipeline.

	@return bool returns true if a regressifier has been added to the pipeline, false otherwise.
	*/
    bool getIsRegressifierSet() const;

    /**
	 This function returns true if a clusterer has been added to the pipeline.

     @return bool returns true if a clusterer has been added to the pipeline, false otherwise.
     */
    bool getIsClustererSet() const;

    /**
	 This function returns true if any post processing modules have been added to the pipeline.

	@return bool returns true if any post processing modules have been added to the pipeline, false otherwise.
	*/
    bool getIsPostProcessingSet() const;

    /**
	 This function returns true if any context modules have been added to the pipeline.

	@return bool returns true if any context modules have been added to the pipeline, false otherwise.
	*/
    bool getIsContextSet() const;

    /**
	 This function returns true if either a classifier or regressifier has been added to the pipeline.

	@return bool returns true if either a classifier or regressifier has been added to the pipeline, false otherwise.
	*/
    bool getIsPipelineModeSet() const;

    /**
	 This function returns true if a classifier has been added to the pipeline (and the pipeline is therefore in classification mode).

	@return bool returns true if a classifier has been added to the pipeline, false otherwise.
	*/
    bool getIsPipelineInClassificationMode() const;

    /**
	 This function returns true if a regressifier has been added to the pipeline (and the pipeline is therefore in regression mode).

	@return bool returns true if a regressifier has been added to the pipeline, false otherwise.
	*/
    bool getIsPipelineInRegressionMode() const;

    /**
	 This function returns the size of the expected input vector to the pipeline.  This size comes from the size of the training data used to train the pipeline.

	@return UINT representing the size of the input vector to the pipeline.
	*/
    UINT getInputVectorDimensionsSize() const;

    /**
	 This function returns the size of the expected output vector from the pipeline.  This size comes from the size of the training data used to train the pipeline.
	 This is only relevant when the pipeline is in regression mode.

	@return UINT representing the size of the output vector from the pipeline.
	*/
    UINT getOutputVectorDimensionsSize() const;

    /**
	 This function is now depreciated. You should use #getNumClasses() instead.

	@return UINT representing the number of classes in the model.
	*/
    UINT getNumClassesInModel() const;

    /**
	 This function returns the number of classes in the model. If the model has not been trained then the number of classes will be zero.
	 This is only relevant when the pipeline is in classification mode.

     @return UINT representing the number of classes in the model.
     */
    UINT getNumClasses() const;

    /**
	 This function returns the number of preprocessing modules that have been added to the pipeline.

	@return UINT representing the number of preprocessing modules that have been added to the pipeline.
	*/
    UINT getNumPreProcessingModules() const;

    /**
	 This function returns the number of feature extraction modules that have been added to the pipeline.

	@return UINT representing the number of feature extraction modules that have been added to the pipeline.
	*/
    UINT getNumFeatureExtractionModules() const;

    /**
	 This function returns the number of post processing modules that have been added to the pipeline.

	@return UINT representing the number of post processing modules that have been added to the pipeline.
	*/
    UINT getNumPostProcessingModules() const;

    /**
	 This function returns the current position of the prediction module index. The prediction module index indicates how far along the pipeline a data sample gets before the pipeline
	 exits during a prediction.  For example, if you have two preprocessing modules, one feature extraction module, a classifier, and one post processing module in your pipeline and the
	 prediction module index is 3 after you call the predict(...) function, then the data only got as far as the feature extraction module but did not get passed through the classifier or
	 post processing modules.

	@return UINT representing the number of post processing modules that have been added to the pipeline.
	*/
    UINT getPredictionModuleIndexPosition() const;

    /**
	 This function returns the predicted class label from the most recent predict(...) function call.  This value is only relevant when the pipeline is in prediction mode.

	@return UINT representing the predicted class label from the most recent prediction.
	*/
    UINT getPredictedClassLabel() const;

    /**
	 This function returns the unprocessed predicted class label from the most recent predict(...) function call.  The unprocessed predicted class label is the class label output by
	 the classifier before any post processing modules filter the value.  This value is only relevant when the pipeline is in prediction mode.

	@return UINT representing the unprocessed predicted class label from the most recent prediction.
	*/
    UINT getUnProcessedPredictedClassLabel() const;

    /**
     This function returns the number of training samples used to train the pipeline model.

     @return UINT representing the number of training samples used to train the pipeline model.
     */
    UINT getNumTrainingSamples() const;

    /**
     This function returns the number of test samples used to train the pipeline model.

     @return UINT representing the number of test samples used to train the pipeline model.
     */
    UINT getNumTestSamples() const;

    /**
	 This function returns the maximum likelihood value from the most likely class from the most recent prediction.  This value is only relevant when the pipeline is in prediction mode.

	@return double representing the maximum likelihood value from the most likely class from the most recent prediction.
	*/
    double getMaximumLikelihood() const;

    /**
	 This function returns the estimated gesture phase from the most recent prediction.  This value is only relevant when the pipeline is in timeseries classification mode.

     @return double representing the gesture phase value from the most likely class from the most recent prediction.
     */
    double getPhase() const;

    /**
	 This function returns the cross validation value from the most recent cross validation test.  If the pipeline is in prediction mode, then the cross
     validation accuracy will be the average accuracy across each fold of testing. If the pipeline is in regression mode, then the cross validation
     accuracy will be the average RMS error across each fold of testing.

	@return double representing the cross validation value from the most recent cross validation test.
	*/
    double getCrossValidationAccuracy() const;

    /**
	 This function returns the accuracy value from the most recent test.  This will be a value between [0 100]. This value is only relevant when the pipeline is in prediction mode.

	@return double representing the accuracy value from the most recent test.
	*/
    double getTestAccuracy() const;

    /**
	 This function returns the root mean squared error value from the most recent test.  This value is only relevant when the pipeline is in regression mode.

	@return double representing the root mean squared error value from the most recent test.
	*/
    double getTestRMSError() const;

    /**
     This function returns the total squared error value from the most recent test.  This value is only relevant when the pipeline is in regression mode.

    @return double representing the total squared error value from the most recent test.
    */
    double getTestSSError() const;

    /**
	 This function returns the f-measure from the most recent test for the class with the matching classLabel.  This value is only relevant when the pipeline is in classification mode.
	 If the classLabel is not valid then the function will return -1.

    @param const UINT classLabel: the label of the class you want to get the test fMeasure value for
	@return double representing the f-measure from the most recent test for the class with the matching classLabel.
	*/
    double getTestFMeasure(const UINT classLabel) const;

    /**
	 This function returns the precision from the most recent test for the class with the matching classLabel.  This value is only relevant when the pipeline is in classification mode.
	 If the classLabel is not valid then the function will return -1.

    @param const UINT classLabel: the label of the class you want to get the test precision value for
	@return double representing the precision from the most recent test for the class with the matching classLabel.
	*/
    double getTestPrecision(const UINT classLabel) const;

    /**
	 This function returns the recall from the most recent test for the class with the matching classLabel.  This value is only relevant when the pipeline is in classification mode.
	 If the classLabel is not valid then the function will return -1.

    @param const UINT classLabel: the label of the class you want to get the test recall value for
	@return double representing the recall from the most recent test for the class with the matching classLabel.
	*/
    double getTestRecall(const UINT classLabel) const;

    /**
	 This function returns the precision for any null examples in your dataset (examples with the class label of 0) from the most recent test.
	 This value is only relevant when the pipeline is in classification mode.

	@return double representing the precision for any null examples in your dataset.
	*/
    double getTestRejectionPrecision() const;

    /**
	 This function returns the recall for any null examples in your dataset (examples with the class label of 0) from the most recent test.
	 This value is only relevant when the pipeline is in classification mode.

	@return double representing the recall for any null examples in your dataset.
	*/
    double getTestRejectionRecall() const;

    /**
	 This function returns the total test time (in milliseconds) for the most recent test.

	@return double representing the total test time (in milliseconds) for the most recent test.
	*/
    double getTestTime() const;

    /**
	 This function returns the total training time (in milliseconds) for the most recent training.

	@return double representing the total training time (in milliseconds) for the most recent training.
	*/
    double getTrainingTime() const;

    /**
     This function returns the root mean squared error value from the most recent training.  This value is only relevant when the pipeline is in regression mode.

    @return double representing the root mean squared error value from the most recent training.
    */
    double getTrainingRMSError() const;

    /**
     This function returns the total squared error value from the most recent training.  This value is only relevant when the pipeline is in regression mode.

    @return double representing the total squared error value from the most recent training.
    */
    double getTrainingSSError() const;

    /**
	 This function returns the confusion matrix for the most recent round of testing.  If null rejection is enabled then the first row and column of the confusion matrix will
	 represent the null class (class label 0).

	@return MatrixDouble representing the confusion matrix for the most recent round of testing.
	*/
    MatrixDouble getTestConfusionMatrix() const;

    /**
     This function returns all the results from the most recent round of testing.
     The TestResult contains all of the test metrics, such as the accuracy, precision, recall, training and test times, etc. These are the
     same results that you would get if you called the individaul functions (such as getTestAccuracy()).

     @return returns an instance of TestResult containing all the results from the most recent round of testing, an empty TestResult will be returned if the model has not been tested
     */
    TestResult getTestResults() const;

    /**
     Gets a vector of the precision results for each class from the most recent round of testing.
     This will be a K-dimensional vector, where K is the number of classes in the model.

     @return returns a vector of the precision results for each class from the last prediction, an empty vector will be returned if the model has not been tested
     */
    VectorDouble getTestPrecision() const;

    /**
     Gets a vector of the recall results for each class from the most recent round of testing.
     This will be a K-dimensional vector, where K is the number of classes in the model.

     @return returns a vector of the recall results for each class from the last prediction, an empty vector will be returned if the model has not been tested
     */
    VectorDouble getTestRecall() const;

    /**
     Gets a vector of the fMeasure results for each class from the most recent round of testing.
     This will be a K-dimensional vector, where K is the number of classes in the model.

     @return returns a vector of the fMeasure results for each class from the last prediction, an empty vector will be returned if the model has not been tested
     */
    VectorDouble getTestFMeasure() const;

    /**
     Gets a vector of the class likelihoods from the last prediction, this will be an N-dimensional vector, where N is the number of classes in the model.
     The exact form of these likelihoods depends on the classification algorithm.

     @return returns a vector of the class likelihoods from the last prediction, an empty vector will be returned if the model has not been trained
     */
    VectorDouble getClassLikelihoods() const;

    /**
     Gets a vector of the class distances from the last prediction, this will be an N-dimensional vector, where N is the number of classes in the model.
     The exact form of these distances depends on the classification algorithm.

     @return returns a vector of the class distances from the last prediction, an empty vector will be returned if the model has not been trained
     */
    VectorDouble getClassDistances() const;

    /**
     Gets a vector containing the null rejection thresholds for each class, this will be an N-dimensional vector, where N is the number of classes in the model.

     @return returns a vector containing the null rejection thresholds for each class, an empty vector will be returned if the model has not been trained
     */
    VectorDouble getNullRejectionThresholds() const;

    /**
     Gets a vector containing the regression data output by the pipeline, this will be an M-dimensional vector, where M is the number of output dimensions in the model.

     @return returns a vector containing the regression data output by the pipeline, an empty vector will be returned if the model has not been trained
     */
    VectorDouble getRegressionData() const;

    /**
     Gets a vector containing the regression data output by the regression algorithm, this will be an M-dimensional vector, where M is the number of output dimensions in the model.

     @return returns a vector containing the regression data output by the regression algorithm, an empty vector will be returned if the model has not been trained
     */
    VectorDouble getUnProcessedRegressionData() const;

    /**
     Gets a vector containing the output of the last preprocessing module, this will be an M-dimensional vector, where M is the output size of the last preprocessing module.

     @return returns a vector containing the output of the last preprocessing module, an empty vector will be returned if there are no preprocessing modules.
     */
    VectorDouble getPreProcessedData() const;

    /**
     Gets a vector containing the output of the preprocessing module at index X, this will be an M-dimensional vector, where M is the output size of the preprocessing module.

     @param UINT moduleIndex: the index of the pre processing module you want
     @return returns a vector containing the output of the preprocessing module at index X, an empty vector will be returned if there is no preprocessing module at that index.
     */
    VectorDouble getPreProcessedData(UINT moduleIndex) const;

    /**
     Gets a vector containing the output of the last feature extraction module, this will be an M-dimensional vector, where M is the output size of the last feature extraction module.

     @return returns a vector containing the output of the last feature extraction module, an empty vector will be returned if there are no feature extraction modules.
     */
    VectorDouble getFeatureExtractionData() const;

    /**
     Gets a vector containing the output of the feature extraction module at index X, this will be an M-dimensional vector, where M is the output size of the feature extraction module.

     @param const UINT moduleIndex: the index of the feature extraction module you want
     @return returns a vector containing the output of the feature extraction module at index X, an empty vector will be returned if there is no feature extraction module at that index.
     */
    VectorDouble getFeatureExtractionData(const UINT moduleIndex) const;

    /**
     Gets a vector containing the label each class represents, this will be an N-dimensional vector, where N is the number of classes in the model.
     This is useful if the model was trained with non-monotonically class labels (i.e. class labels such as [1, 3, 6, 9, 12] instead of [1, 2, 3, 4, 5]).

     @return returns a vector containing the class labels for each class, an empty vector will be returned if the model has not been trained
     */
    vector< UINT > getClassLabels() const;

    /**
     Gets a vector containing the results from the most recent test.  Each element in the vector represents the results for the corresponding test sample.

     @return returns a vector containing the test instance results from the most recent test, an empty vector will be returned if no test has been run.
     */
    vector< TestInstanceResult > getTestInstanceResults() const;

    /**
     Gets a vector containing the results from the most recent cross validation test.  Each element in the vector represents one fold of cross validation training.

     @return returns a vector containing the results from the most recent cross validation test, an empty vector will be returned if no test has been run.
     */
    vector< TestResult > getCrossValidationResults() const;

    /**
     Gets a pointer to the preprocessing module at the specific moduleIndex.

     @param const UINT moduleIndex: the index of the pre processing module you want
     @return returns a pointer to the preprocessing module at the specific moduleIndex, or NULL if the moduleIndex is invalid
     */
    PreProcessing* getPreProcessingModule(const UINT moduleIndex) const;

    /**
     Gets a pointer to the feature extraction module at the specific moduleIndex.

     @param UINT moduleIndex: the index of the feature extraction module you want
     @return returns a pointer to the feature extraction module at the specific moduleIndex, or NULL if the moduleIndex is invalid
     */
    FeatureExtraction* getFeatureExtractionModule(const UINT moduleIndex) const;

    /**
     Gets a pointer to the classifier module.

     @return returns a pointer to the classifier module, or NULL if the classifier has not been set
     */
    Classifier* getClassifier() const;

    /**
     Gets a pointer to the regressifier module.

     @return returns a pointer to the regressifier module, or NULL if the regressifier has not been set
     */
    Regressifier* getRegressifier() const;

    /**
     Gets a pointer to the clusterer module.

     @return returns a pointer to the clusterer module, or NULL if the clusterer has not been set
     */
    Clusterer* getClusterer() const;

    /**
     Gets a pointer to the post processing module at the specific moduleIndex.

     @param UINT moduleIndex: the index of the post processing module you want
     @return returns a pointer to the post processing module at the specific moduleIndex, or NULL if the moduleIndex is invalid
     */
    PostProcessing* getPostProcessingModule(UINT moduleIndex) const;

    /**
     Gets a pointer to the context module at the specific contextLevel and moduleIndex.

     @param const UINT contextLevel: the context level that contains the context module you want
     @param const UINT moduleIndex: the index of the context module you want
     @return returns a pointer to the context module at the specific contextLevel and moduleIndex, or NULL if the contextLevel or moduleIndex are invalid
     */
    Context* getContextModule(const UINT contextLevel,const UINT moduleIndex) const;

    /**
     Gets a pointer to the preprocessing module at the specific moduleIndex.  You should make sure that the type of the preprocessing module matches the template type.

     @param const UINT moduleIndex: the index of the pre processing module you want
     @return returns a pointer to the preprocessing module at the specific moduleIndex, or NULL if the moduleIndex is invalid
     */
    template <class T> T* getPreProcessingModule(const UINT moduleIndex) const{
        if( moduleIndex < preProcessingModules.size() ){
            return (T*)preProcessingModules[ moduleIndex ];
        }
        return NULL;
    }

    /**
     Gets a pointer to the feature extraction module at the specific moduleIndex.  You should make sure that the type of the feature extraction module matches the template type.

     @param const UINT moduleIndex: the index of the feature extraction module you want
     @return returns a pointer to the feature extraction module at the specific moduleIndex, or NULL if the moduleIndex is invalid
     */
    template <class T> T* getFeatureExtractionModule(const UINT moduleIndex) const{
        if( moduleIndex < featureExtractionModules.size() ){
            return (T*)featureExtractionModules[ moduleIndex ];
        }
        return NULL;
    }

    /**
     Gets a pointer to the classifier module. If the classifier has not been set, or the template type T does not match the current
     classifier type then the function will return NULL.

     @return returns a pointer to the classifier module, or NULL if the classifier has not been set
     */
    template <class T> T* getClassifier() const{

        if( classifier == NULL ) return NULL;

        T temp;

        if( temp.getClassifierType() == classifier->getClassifierType() ){
            return dynamic_cast<T*>(classifier);
        }

        return NULL;
    }

    /**
     Gets a pointer to the regressifier module.  If the regressifier has not been set, or the template type T does not match the current
     regressifier type then the function will return NULL.

     @return returns a pointer to the regressifier module, or NULL if the regressifier has not been set
     */
    template <class T> T* getRegressifier() const{

        if( regressifier == NULL ) return NULL;

        T temp;

        if( temp.getRegressifierType() == regressifier->getRegressifierType() ){
            return (T*)regressifier;
        }

        return NULL;
    }

    /**
     Gets a pointer to the cluster module. If the cluster has not been set, or the template type T does not match the current
     cluster type then the function will return NULL.

     @return returns a pointer to the cluster module, or NULL if the cluster has not been set
     */
    template <class T> T* getCluster() const{

        if( clusterer == NULL ) return NULL;

        T temp;

        if( temp.getClassifierType() == clusterer->getClustererType() ){
            return (T*)clusterer;
        }

        return NULL;
    }

    /**
     Gets a pointer to the post processing module at the specific moduleIndex.  You should make sure that the type of the post processing module matches the template type.

     @param const UINT moduleIndex: the index of the post processing module you want
     @return returns a pointer to the post processing module at the specific moduleIndex, or NULL if the moduleIndex is invalid
     */
    template <class T> T* getPostProcessingModule(const UINT moduleIndex) const{
        if( moduleIndex < postProcessingModules.size() ){
            return (T*)postProcessingModules[ moduleIndex ];
        }
        return NULL;
    }

    /**
     Gets a pointer to the context module at the specific contextLevel and moduleIndex.  You should make sure that the type of the context module matches the template type.

     @param const UINT contextLevel: the context level that contains the context module you want
     @param const UINT moduleIndex: the index of the context module you want
     @return returns a pointer to the context module at the specific contextLevel and moduleIndex, or NULL if the contextLevel or moduleIndex are invalid
     */
    template <class T> T* getContextModule(const UINT contextLevel,const UINT moduleIndex) const{
        if( contextLevel < contextModules.size() ){
            if( moduleIndex < contextModules[ contextLevel ].size() ){
                return (T*)contextModules[ contextLevel ][ moduleIndex ];
            }
        }
        return NULL;
    }

    /**
     Gets the pipeline model as a string.  This includes any classification or regression model, but also any preprocessing, feature extraction or post processing settings.

     @return returns the pipeline model as a string
     */
    string getModelAsString() const;

    /**
     Gets the pipeline mode as a string, this will be either "PIPELINE_MODE_NOT_SET","CLASSIFICATION_MODE", or "REGRESSION_MODE".

     @return returns the pipeline mode as a string
     */
    string getPipelineModeAsString() const;

    /*
     Gets the pipeline info text as a string.

     @return returns the pipeline info as a string
     */
    string getInfo() const;

    /**
     Converts a string to the pipeline mode.

     @param string pipelineMode: the pipeline mode as a string, i.e. "CLASSIFICATION_MODE"
     @return returns an unsigned integer representing the current pipeline mode
     */
	UINT getPipelineModeFromString(string pipelineMode) const;

    /**
     Adds a new pre processing module to the pipeline.  The user can specify the position at which the new module should be inserted into the list of preprocessing modules.
     The default position is to insert the new module at the end of the list.

     @param const PreProcessing &preProcessingModule: a reference to the pre processing module you want to add
     @param UINT insertIndex: the index of where you want to insert the new pre processing module. Default is to insert the new module at the end of the list
     @return returns true if the preprocessing module was added successfully, false otherwise
     */
    bool addPreProcessingModule(const PreProcessing &preProcessingModule,UINT insertIndex = INSERT_AT_END_INDEX);

	/**
	 This function removes any existing pre processing modules, then it adds the new pre processing module.

     @param const PreProcessing &preProcessingModule: a reference to the pre processing module you want to add
     @return returns true if the preprocessing module was added successfully, false otherwise
     */
    bool setPreProcessingModule(const PreProcessing &preProcessingModule);

    /**
     Adds a new feature extraction module to the pipeline.  The user can specify the position at which the new module should be inserted into the list of feature extraction modules.
     The default position is to insert the new module at the end of the list.

     @param const FeatureExtraction &featureExtractionModule: a reference to the feature extraction module you want to add
     @param UINT insertIndex: the index of where you want to insert the new feature extraction module. Default is to insert the new module at the end of the list
     @return returns true if the feature extraction module was added successfully, false otherwise
     */
    bool addFeatureExtractionModule(const FeatureExtraction &featureExtractionModule,UINT insertIndex = INSERT_AT_END_INDEX);

	/**
	 This function removes any existing feature extraction modules, then it adds the new feature extraction module.

     @param const FeatureExtraction &featureExtractionModule: a reference to the feature extraction module you want to add
     @return returns true if the feature extraction module was added successfully, false otherwise
     */
    bool setFeatureExtractionModule(const FeatureExtraction &featureExtractionModule);

    /**
     Sets the classifier at the core of the pipeline.  A pipeline can only have one classifier or regressifier, setting a new classifier will override any previous classifier or regressifier.

     @param const Classifier &classifier: a reference to the classifier module you want to add to the pipeline
     @return returns true if the classifier module was set successfully, false otherwise
     */
    bool setClassifier(const Classifier &classifier);

    /**
     Sets the regressifier at the core of the pipeline.  A pipeline can only have one classifier or regressifier, setting a new regressifier will override any previous classifier or regressifier.

     @param const Regressifier &regressifier: a reference to the regression module you want to add to the pipeline
     @return returns true if the regressifier module was set successfully, false otherwise
     */
    bool setRegressifier(const Regressifier &regressifier);

    /**
     Sets the clusterer at the core of the pipeline.  A pipeline can only have one cluster algorithm, setting a new cluster will override any previous classifier or regressifier.

     @param const Regressifier &regressifier: a reference to the regression module you want to add to the pipeline
     @return returns true if the regressifier module was set successfully, false otherwise
     */
    bool setClusterer(const Clusterer &clusterer);

    /**
     Adds a new post processing module to the pipeline.  The user can specify the position at which the new module should be inserted into the list of post processing modules.
     The default position is to insert the new module at the end of the list.

     @param const PostProcessing &postProcessingModule: a reference to the post processing module you want to add
     @param UINT insertIndex: the index of where you want to insert the new post processing module. Default is to insert the new module at the end of the list
     @return returns true if the post processing module was added successfully, false otherwise
     */
    bool addPostProcessingModule(const PostProcessing &postProcessingModule,UINT insertIndex = INSERT_AT_END_INDEX);

	/**
     This function removes any existing post processing modules, then it adds the new post processing module.

     @param const PostProcessing &postProcessingModule: a reference to the post processing module you want to add
     @return returns true if the post processing module was added successfully, false otherwise
     */
    bool setPostProcessingModule(const PostProcessing &postProcessingModule);

	/**
	 Adds a new context module to the pipeline.  The user can specify the position at which the new module should be inserted into the list of context modules.
	 The default position is to insert the new module at the end of the list.

     @param const Context &contextModule: a reference to the context module that you want to add
     @param UINT contextLevel: the context level where you want to add the new context module
     @param UINT insertIndex: the index of where you want to insert the new context module. Default is to insert the new module at the end of the list
	 @return returns true if the context module was added successfully, false otherwise
	 */
	bool addContextModule(const Context &contextModule,UINT contextLevel,UINT insertIndex = INSERT_AT_END_INDEX);

    /**
	 Updates the context module at the specific contextLevel and moduleIndex.
	 The user can specify the position at which the new module should be inserted into the list of context modules.
	 The default position is to insert the new module at first contextLevel and first moduleIndex

     @param UINT contextLevel: the context level that contains the context module you want to update
     @param UINT moduleIndex: the index of the module you want to update
	 @return returns true if the context module was updated successfully, false otherwise
	 */
	bool updateContextModule(bool value,UINT contextLevel = 0,UINT moduleIndex = 0);

    /**
	 Removes all the preprocessing modules from the current pipeline. If the pipeline has been trained it will need to be retrained before it can be used.

	 @return returns true if preprocessing modules were removed successfully, false otherwise
	 */
    bool removeAllPreProcessingModules();

    /**
	 Removes the specific preprocessing module at the module index from the current pipeline. If the pipeline has been trained it will need to be retrained before it can be used.

     @param UINT moduleIndex: the index of the module you want to remove
	 @return returns true if the preprocessing module was removed successfully, false otherwise
	 */
    bool removePreProcessingModule(UINT moduleIndex);

    /**
	 Removes all the feature extraction modules from the current pipeline. If the pipeline has been trained it will need to be retrained before it can be used.

	 @return returns true if feature extraction modules were removed successfully, false otherwise
	 */
    bool removeAllFeatureExtractionModules();

    /**
	 Removes the specific feature extraction module at the module index from the current pipeline. If the pipeline has been trained it will need to be retrained before it can be used.

     @param UINT moduleIndex: the index of the module you want to remove
	 @return returns true if the feature extraction module was removed successfully, false otherwise
	 */
    bool removeFeatureExtractionModule(UINT moduleIndex);

    /**
	 Removes the classifier from the current pipeline.

	 @return returns true if classifier was removed successfully, false otherwise
	 */
    bool removeClassifier(){ deleteClassifier(); return true; }

    /**
	 Removes the regressifier from the current pipeline.

	 @return returns true if regressifier was removed successfully, false otherwise
	 */
	bool removeRegressifier(){ deleteRegressifier(); return true; }

    /**
	 Removes the clusterer from the current pipeline.

	 @return returns true if clusterer was removed successfully, false otherwise
	 */
	bool removeClusterer(){ deleteClusterer(); return true; }

	/**
	 Removes all the post processing extraction modules from the current pipeline. If the pipeline has been trained it will need to be retrained before it can be used.

	 @return returns true if post processing modules were removed successfully, false otherwise
	 */
    bool removeAllPostProcessingModules();

    /**
	 Removes the specific post processing module at the module index from the current pipeline. If the pipeline has been trained it will need to be retrained before it can be used.

     @param const UINT moduleIndex: the index of the module you want to remove
	 @return returns true if the post processing module was removed successfully, false otherwise
	 */
    bool removePostProcessingModule(const UINT moduleIndex);

    /**
	 Removes all the context modules from the current pipeline. If the pipeline has been trained it will need to be retrained before it can be used.

	 @return returns true if context modules were removed successfully, false otherwise
	 */
    bool removeAllContextModules();

    /**
	 Removes the specific context module at the module index from the current pipeline. If the pipeline has been trained it will need to be retrained before it can be used.

     @param const UINT contextLevel: the context level that contains the specific context module you want to remove
     @param const UINT moduleIndex: the index of the context module you want to remove
	 @return returns true if the context module was removed successfully, false otherwise
	 */
    bool removeContextModule(const UINT contextLevel,const UINT moduleIndex);

    /**
	 Removes everything from the pipeline.

	 @return returns true if all the modules were removed successfully, false otherwise
	 */
	bool clearAll();

    /**
	 Resets all the test results to zero.

	 @return returns true if the test results were cleared successfully, false otherwise
	 */
    bool clearTestResults();

    /**
     Sets the pipeline's info text.
      @return returns true if the info text was updated successfully, false otherwise
     */
    bool setInfo(const string info);

protected:
    bool predict_classifier(const VectorDouble &inputVector);
    bool predict_regressifier(const VectorDouble &inputVector);
    bool predict_clusterer(const VectorDouble &inputVector);
    void deleteAllPreProcessingModules();
    void deleteAllFeatureExtractionModules();
    void deleteClassifier();
    void deleteRegressifier();
    void deleteClusterer();
    void deleteAllPostProcessingModules();
    void deleteAllContextModules();
    bool updateTestMetrics(const UINT classLabel,const UINT predictedClassLabel,VectorDouble &precisionCounter,VectorDouble &recallCounter,double &rejectionPrecisionCounter,double &rejectionRecallCounter,VectorDouble &confusionMatrixCounter);
    bool computeTestMetrics(VectorDouble &precisionCounter,VectorDouble &recallCounter,double &rejectionPrecisionCounter,double &rejectionRecallCounter,VectorDouble &confusionMatrixCounter,const UINT numTestSamples);

    bool initialized;
    bool trained;
    string info;
    UINT inputVectorDimensions;
    UINT outputVectorDimensions;
    UINT predictedClassLabel;
    UINT predictedClusterLabel;
    UINT pipelineMode;
    UINT predictionModuleIndex;
    UINT numTrainingSamples;
    UINT numTestSamples;
    double testAccuracy;
    double testRMSError;
    double testSquaredError;
    double testTime;
    double trainingTime;
    VectorDouble testFMeasure;
    VectorDouble testPrecision;
    VectorDouble testRecall;
    VectorDouble regressionData;
    double testRejectionPrecision;
    double testRejectionRecall;
    MatrixDouble testConfusionMatrix;
    vector< TestResult > crossValidationResults;
    vector< TestInstanceResult > testResults;

    vector< PreProcessing* > preProcessingModules;
    vector< FeatureExtraction* > featureExtractionModules;
    Classifier *classifier;
    Regressifier *regressifier;
    Clusterer *clusterer;
    vector< PostProcessing* > postProcessingModules;
    vector< vector< Context* > > contextModules;

    enum PipelineModes{PIPELINE_MODE_NOT_SET=0,CLASSIFICATION_MODE,REGRESSION_MODE,CLUSTER_MODE};

public:
    enum ContextLevels{START_OF_PIPELINE=0,AFTER_PREPROCESSING,AFTER_FEATURE_EXTRACTION,AFTER_CLASSIFIER,END_OF_PIPELINE,NUM_CONTEXT_LEVELS};

};

} //End of namespace GRT

#endif //GRT_GESTURE_RECOGNITION_PIPELINE_HEADER