<!--{{{-->
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml' />
<!--}}}-->
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/*{{{*/
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}

a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}

h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}

.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}

.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}

.tabSelected{color:[[ColorPalette::PrimaryDark]];
	background:[[ColorPalette::TertiaryPale]];
	border-left:1px solid [[ColorPalette::TertiaryLight]];
	border-top:1px solid [[ColorPalette::TertiaryLight]];
	border-right:1px solid [[ColorPalette::TertiaryLight]];
}
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}

#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}

.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
	border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}
	
.wizard .notChanged {background:transparent;}
.wizard .changedLocally {background:#80ff80;}
.wizard .changedServer {background:#8080ff;}
.wizard .changedBoth {background:#ff8080;}
.wizard .notFound {background:#ffff80;}
.wizard .putToServer {background:#ff80ff;}
.wizard .gotFromServer {background:#80ffff;}

#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}

.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}

.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}

.tiddler .defaultCommand {font-weight:bold;}

.shadow .title {color:[[ColorPalette::TertiaryDark]];}

.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}

.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}

.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}

.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}

.sparkline {background:[[ColorPalette::PrimaryPale]]; border:0;}
.sparktick {background:[[ColorPalette::PrimaryDark]];}

.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}

.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}

.imageLink, #displayArea .imageLink {background:transparent;}

.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}

.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}

.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}

.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}

.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}

.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}

#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:'alpha(opacity:60)';}
/*}}}*/
/*{{{*/
* html .tiddler {height:1%;}

body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}

h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}

.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}

/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}

#mainMenu .tiddlyLinkExisting,
	#mainMenu .tiddlyLinkNonExisting,
	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0em 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0em 1em 1em; left:0px; top:0px;}

.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}

#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}

#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0em 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 .3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

.wizard {padding:0.1em 1em 0em 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0em 0em 0em; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0em;}
.wizardFooter .status {padding:0em 0.4em 0em 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em 0.1em 0.2em;}

#messageArea {position:fixed; top:2em; right:0em; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em 0.2em 0.2em 0.2em;}
#messageArea a {text-decoration:underline;}

.tiddlerPopupButton {padding:0.2em 0.2em 0.2em 0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em 1em 1em 1em; margin:0;}

.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0em;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}

.tabset {padding:1em 0em 0em 0.5em;}
.tab {margin:0em 0em 0em 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}

#contentWrapper {display:block;}
#splashScreen {display:none;}

#displayArea {margin:1em 17em 0em 14em;}

.toolbar {text-align:right; font-size:.9em;}

.tiddler {padding:1em 1em 0em 1em;}

.missing .viewer,.missing .title {font-style:italic;}

.title {font-size:1.6em; font-weight:bold;}

.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}

.tiddler .button {padding:0.2em 0.4em;}

.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}

.footer {font-size:.9em;}
.footer li {display:inline;}

.annotation {padding:0.5em; margin:0.5em;}

* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0em 0.25em; padding:0em 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}

.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}

.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0em; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}

.fieldsetFix {border:0; padding:0; margin:1px 0px 1px 0px;}

.sparkline {line-height:1em;}
.sparktick {outline:0;}

.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}

* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0em; right:0em;}
#backstageButton a {padding:0.1em 0.4em 0.1em 0.4em; margin:0.1em 0.1em 0.1em 0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; width:90%; margin:0em 3em 0em 3em; padding:1em 1em 1em 1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em 0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
***/
/*{{{*/
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
/*}}}*/
/*{{{*/
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none ! important;}
#displayArea {margin: 1em 1em 0em 1em;}
/* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
noscript {display:none;}
}
/*}}}*/
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<!--}}}-->
To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:
* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* MainMenu: The menu (usually on the left)
* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
These InterfaceOptions for customising TiddlyWiki are saved in your browser

Your username for signing your edits. Write it as a WikiWord (eg JoeBloggs)

<<option txtUserName>>
<<option chkSaveBackups>> SaveBackups
<<option chkAutoSave>> AutoSave
<<option chkRegExpSearch>> RegExpSearch
<<option chkCaseSensitiveSearch>> CaseSensitiveSearch
<<option chkAnimate>> EnableAnimations

----
Also see AdvancedOptions
<<importTiddlers>>
libPRSD provides a simple API (Application Programming Interface)
!Initialization and releasing the library
* [[prsd_InitKernel]]
* [[prsd_InitKernelLicString]]
* [[prsd_LicenseCheck]]
* [[prsd_ReleaseKernel]]
!Status and error reporting
* [[prsd_GetErrorMsg]]
* [[prsd_GetErrorCode]]
* [[libPRSD error messages]]
* {{{#define PRSD_OK       0}}}
* {{{#define PRSD_ERROR   -1}}}
* {{{#define PRSD_YES      1}}}
* {{{#define PRSD_NO       0}}}
!Loading and releasing pipelines
* [[prsd_LoadPipeline]]
* [[prsd_GetPipelineCount]]
* [[prsd_ReleasePipeline]]
!Operations on a specific loaded pipeline
* [[prsd_GetName]]
* [[prsd_GetInputFc]]
* [[prsd_GetOutputFc]]
* [[prsd_GetDecCount]]
* [[prsd_GetDecName]]
!!Attaching and detaching application memory to/from the pipeline
* [[prsd_AttachMemToInput]] - Attach memory chunk allocated by the application to the pipeline input
* [[prsd_AttachMemToOutput]] - Attach memory chunk allocated by the application to the pipeline input
* [[prsd_BufAttachToInput]] - Attach buffer object to the pipeline input (see below for data buffer object)
* [[prsd_BufAttachToOutput]] - Attach buffer object to the pipeline output (see below for data buffer object)
* [[prsd_DetachInput]] - Detach memory attached to the pipeline input
* [[prsd_DetachOutput]] - Detach memory attached to the pipeline input 
!!Pipeline execution
* [[prsd_IsReadyToExecute]]
* [[prsd_Execute]]
* [[prsd_SetOp]] - Set classifier to a specific operating point
!Data buffers
* [[prsd_BufNew]] - Allocate memory buffer
* [[prsd_BufNewReferringTo]] - Create buffer refering to existing application memory chunk
* [[prsd_BufLoadFromCSVFile]] - Allocate a buffer and fill it with data from a comma-separated file
* [[prsd_BufFree]] - Free a buffer
* [[prsd_BufGetSc]] - Return the number of samples in a buffer
* [[prsd_BufSetSc]] - Set the number of actual samples in the allocated buffer
* [[prsd_BufGetFc]] - Return the number of features in a buffer
!!Getting/Setting values in a buffer
* [[prsd_BufGetValue]]
* [[prsd_BufSetValue]]
<part prsd_InitKernel>
aaa
</part>

<part prsd_LoadPipeline>
nnn
</part>

In order to access the details such as per-fold training / test sets or the trained algorithm, we may take advantage of the evaluation object returned as the second output of the <<ref sdcrossval>> function. 
In this example, we will fix the operating point of interest based on the ROC analysis, we performed [[here|Evaluation for the sets of operating points]]:
{{{
>> getdata(ops,7)
ans =
    0.6000    0.4000
>> ops2=sdops('w',getdata(ops,7),getlablist(a))
Weight-based operating point,2 classes,[0.60,0.40]
}}}
Now, we invoke <<ref sdcrossval>> again asking for two outputs:
{{{
>> [r,e]=sdcrossval(nmc,a,'ops',ops2)
10 folds: [1: ] [2: ] [3: ] [4: ] [5: ] [6: ] [7: ] [8: ] [9: ] [10: ] 
ROC (w-based op.point, 2 measures, 10 folds)
est: 1:err(apple)=0.12(0.10), 2:err(pear)=0.20(0.14)
completed 10-fold evaluation 'sde_rotation' (alg: 'sda_prtools')
}}}
The {{{r}}} output is the ROC with variance (now for a single op.point). The second output {{{e}}} represents the evaluation session. We may use it to access per-fold training and test sets and even all trained algorithms:
{{{
>> tr=gettrdata(e,a,2) % 2nd fold training set
Banana Set, 180 by 2 dataset with 2 classes: [109   71]
>> ts=gettsdata(e,a,2) % 2nd fold test set
Banana Set, 20 by 2 dataset with 2 classes: [12   8]

>> e(2) % algorithm trained in 2nd fold
trained sdalg 'sda_prtools'
expar:
 w               2x2       2764  mapping  Nearest Mean, 2 to 2 trained classifier --> affine
ops: Weight-based operating point,2 classes,[0.60,0.40]
output: decision,name
}}}
We can run the algorithm on the fold test set and compute confusion matrix:
{{{
>> confmat(getlab(ts),ts*e(2))

  True   | Estimated Labels
  Labels |  apple  pear | Totals
 --------|--------------|-------
  apple  |   12      0  |   12
  pear   |    1      7  |    8
 --------|--------------|-------
  Totals |   13      7  |   20
}}}
Comparison to the ROC object returned from the cross-validation:
{{{
>> r(1,:,2) % first (and only) operating point, all measures, 2nd fold
ans =
         0    0.1250
>> 1/8
ans =
    0.1250
}}}
Activation key is 19-character string of the form {{{1234-1234-1234-1234}}}. You receive the activation key in an e-mail sent automatically after downloading PRSD Studio. If you cannot find your activation key, contact us at [[support@prsysdesign.net|mailto:support@prsysdesign.net]]
In this example, we illustrate how to adjust the set of algorithm operating points using [[ROC analysis|ROC Analysis]]:
{{{
>> a
Difficult Dataset, 100 by 10 dataset with 2 classes: [50  50]
>> [tr,ts]=gendat(a,0.5)
Difficult Dataset, 50 by 10 dataset with 2 classes: [25  25]
Difficult Dataset, 50 by 10 dataset with 2 classes: [25  25]

>> tralg=tr*sda_featex
trained sdalg 'sda_featex'
expar:
 w              10x4       3156  mapping  PCA ret. 90.0% var, 10 to 4 trained  mapping   --> affine
 clf             4x2       3192  mapping  Bayes-Normal-2, 4 to 2 trained  mapping   --> normal_map
ops: Weight-based operating point,2 classes,[0.50,0.50]
output: decision,name
}}}
We gather the soft outputs on the test set and estimate the ROC curve:
{{{
>> out=ts*setoutput(tralg,'soft')
Difficult Dataset, 50 by 2 dataset with 2 classes: [25  25]
>> r=sdroc(out)
ROC (31 w-based op.points, 2 measures), curop: 1
est: 1:err(apple)=0.24, 2:err(banana)=0.08
}}}
We can draw the ROC curve:
{{{
>> sddrawroc(r)
}}}
[img[ROC estimated on the test set|images/13_roc.png]]
The operating points, derived by ROC analysis, may be set into the algorithm object using the <<ref setops>> method:
{{{
>> tralg=setops(tralg,r)
trained sdalg 'sda_featex'
expar:
 w              10x4       3156  mapping  PCA ret. 90.0% var, 10 to 4 trained  mapping   --> affine
 clf             4x2       3192  mapping  Bayes-Normal-2, 4 to 2 trained  mapping   --> normal_map
ops: Weight-based operating set (31 ops, 2 classes) at op 1
output: decision,name
}}}
We can set the current operating point using <<ref setcurop>> method:
<html><pre>
>> tralg=setcurop(tralg,21)
trained sdalg 'sda_featex'
expar:
 w              10x4       3156  mapping  PCA ret. 90.0% var, 10 to 4 trained  mapping   --> affine
 clf             4x2       3192  mapping  Bayes-Normal-2, 4 to 2 trained  mapping   --> normal_map
ops: Weight-based operating set (31 ops, 2 classes) <b>at op 21</b>
output: decision,name
</pre></html>
Confusion matrix at this operating point:
{{{
>> confmat(getlab(ts),ts*tralg)

  True   | Estimated Labels
  Labels | apple  banana| Totals
 --------|--------------|-------
  apple  |   22      3  |   25
  banana |    2     23  |   25
 --------|--------------|-------
  Totals |   24     26  |   50
}}}
And confusion matrix at the operating point #10, minimizing the error on banana:
{{{
>> confmat(getlab(ts),ts*setcurop(tralg,10))

  True   | Estimated Labels
  Labels | apple  banana| Totals
 --------|--------------|-------
  apple  |   18      7  |   25
  banana |    0     25  |   25
 --------|--------------|-------
  Totals |   18     32  |   50
}}}

next: [[Creating algorithms from PRTools mappings]]
/% * basic structure (picture)
* what are the tasks when designing PR system?
* design in Matlab, deployment anywhere
* using the best available tools for the job (integrating, not replacing)
* user-friendly, industry-oriented
------
%/
PRSD Studio is a software toolkit facilitating design and deployment of advanced pattern recognition algorithms. It consists of the Matlab-based PRSD Toolbox and the C execution library libPRSD which can be easily embedded in custom applications.
[img[PRSD Studio structure|images/20_prsd_studio.png]]
PRSD Studio provides tools for
* Visualizing data and meta-data in pattern recognition problems
* Writing custom algorithms modeling pattern recognition systems from measurements to decisions
* Fine-tuning classifiers using two-class and multi-class ROC analysis with standard or custom performance measures
* Quickly define execution pipelines representing complex pattern recognition systems
* Export the pipelines for execution via the libPRSD DLL outside of Matlab in custom applications

PRSD Studio build upon the leading academic toolbox for pattern recognition, [[PRTools|http://prtools.org]]
Background: #fff
Foreground: #000
PrimaryPale: #ffe9ac
PrimaryLight: #4b0815
PrimaryMid: #830424
PrimaryDark: #01c
SecondaryPale: #ffc
SecondaryLight: #ffe9ac
SecondaryMid: #ffe9ac
SecondaryDark: #830424
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
Link: #1a46bd

!!!Under MS Windows
{{{
cl /c example1.c
link /out:example1.exe example1.obj libprsd.lib
}}}

!!!Under Mac OSX
{{{
gcc -c example1.c
gcc example1.o libprsd.dylib -o example1
}}}

!!!Under GNU/Linux
{{{
gcc -c example1.c
gcc example1.o libprsd.so -o example1
}}}
The goal of our running example is to distinguish three major classes of European circular signs from images of sign boards. The road sign dataset is available in the  {{{data}}} sub-directory:
{{{
>> load data\road_signs.mat
>> whos
  Name        Size                Bytes  Class     Attributes

  data      381x1024             390144  uint8                
  type      381x4                  3048  char                
}}}
We have a dataset with 381 gray-scale images rescaled to 32x32 pixel size. For each image, we've got also its type according to the transportation standard.

Let us first create PRTools dataset object that will contain both the data and meta-data. We call the {{{dataset}}} constructor providing the measurement matrix converted to double precision and the labels. PRTools uses a convention where each row corresponds to a single data sample (measurement, here one image) and the columns represent the feaures (here pixel values).
{{{
>> a=dataset(double(data),type)
381 by 1024 dataset with 17 classes: [31  28  24  33  19  21  57  26  21   9  13  15  14   1  14  29  26]
}}}
We can retrieve the class names using the {{{getlablist}}} command:
{{{
>> getlablist(a)

ans =

B1  
B2  
B20a
B21a
B24a
B24b
B28 
B29 
B4  
C3  
C4b 
C4c 
C4d 
C4e 
C4f 
C5a 
C5b 
}}}
In order to visualize the dataset content as images, we need to provide extra information on image dimensions. The 1024 features may be re-scaled to the 32x32 pixel raster. We need to se the {{{featsize}}} field of the dataset:
{{{
>> a=set(a,'featsize',[32 32])
381 by 1024 dataset with 17 classes: [31  28  24  33  19  21  57  26  21   9  13  15  14   1  14  29  26]
}}}
We can now visualize the images stored in the dataset:
{{{
>> show(a)
}}}
[img[Road sign dataset|images/1_show.png]]

next: [[Defining a pattern recognition problem]]
~PRTools mappings (both untrained and trained) may be converted into algorithms using the {{{sdalg}}} constructor. Number of PRSD Toolbox functions such as <<ref sdcrossval>>, <<ref sdexe>> or <<ref sdscatter>> accept ~PRTools mappings taking advantage of this wrapping technique.
{{{
>> alg=sdalg(nmc)
untrained sdalg 'sda_prtools'
trpar:
 w               0x0       2306  mapping  Nearest Mean, untrained  mapping   --> nmc

>> w=parzenc(tr)
Parzen Classifier, 10 to 2 trained  mapping   --> parzen_map

>> tralg=sdalg(w)
trained sdalg 'sda_prtools'
expar:
 w              10x2      20188  mapping  Parzen Classifier, 10 to 2 trained  mapping   --> parzen_map
ops: Weight-based operating point,2 classes,[0.50,0.50]
output: decision,name
}}}

next: [[Creating custom algorithms]]
Bellow is listed a simple {{{sdalg}}} algorithm describing a two-step process with a feature extractor and classifier.
<html>
<div style="text-align:left;color:#000000; background-color:#ffffff; border:solid black 1px; padding:0.5em 1em 0.5em 1em; overflow:auto;font-size:small; font-family:monospace; "><em><span style="color:#236e25;">%SDA_FEATEX feature extractor followed by a classifier<br />
%<br />
% DESCRIPTION<br />
% SDA_FEATEX is a two-stage algorithm consisting of a feature extractor<br />
% followed by a classifier<br />
</span></em><br />
<span style="color:#0000b2;">function</span> [out1,out2]<span style="color:#7600b2;">=</span>sda_featex(alg,data)<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000b2;">if</span> <span style="color:#0000b2;">nargin</span><span style="color:#7600b2;">==</span>0 <em><span style="color:#236e25;">% initialize the algorithm<br />
</span></em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alg<span style="color:#7600b2;">=</span>sdalg(mfilename);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em><span style="color:#236e25;">% set up all the parameters needed for training<br />
</span></em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alg.trpar.featex<span style="color:#7600b2;">=</span>pca([],0.9); <em><span style="color:#236e25;">% feature extraction mapping<br />
</span></em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alg.trpar.<span style="color:#0000b2;">clf</span><span style="color:#7600b2;">=</span>qdc; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em><span style="color:#236e25;">% classifier<br />
</span></em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alg<span style="color:#7600b2;">=</span>setoutput(alg,{<span style="color:#c00600;">'similarity'</span>,<span style="color:#c00600;">'decision'</span>});<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out1<span style="color:#7600b2;">=</span>setstate(alg,<span style="color:#c00600;">'untrained'</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000b2;">return</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000b2;">end</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000b2;">if</span> <span style="color:#7600b2;">~</span>istrained(alg) <em><span style="color:#236e25;">% training =========================<br />
</span></em>&nbsp;&nbsp;&nbsp;&nbsp;<em><span style="color:#236e25;">% derive all parameters needed for execution (expar)<br />
</span></em><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000b2;">if</span> <span style="color:#7600b2;">~</span>isempty(alg.trpar.featex)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alg.expar.w<span style="color:#7600b2;">=</span>data<span style="color:#7600b2;">*</span>alg.trpar.featex;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data<span style="color:#7600b2;">=</span>data<span style="color:#7600b2;">*</span>alg.expar.w;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000b2;">else</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alg.expar.w<span style="color:#7600b2;">=</span>[];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000b2;">end</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alg.expar.<span style="color:#0000b2;">clf</span><span style="color:#7600b2;">=</span>data<span style="color:#7600b2;">*</span>alg.trpar.<span style="color:#0000b2;">clf</span>;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alg<span style="color:#7600b2;">=</span>setops(alg,sddecide(alg.expar.<span style="color:#0000b2;">clf</span>));<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out1<span style="color:#7600b2;">=</span>setstate(alg,<span style="color:#c00600;">'trained'</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000b2;">elseif</span> istrained(alg) <em><span style="color:#236e25;">% execution ====================<br />
</span></em>&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em><span style="color:#236e25;">% feature computation --------------------<br />
</span></em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000b2;">if</span> <span style="color:#7600b2;">~</span>isempty(alg.expar.w)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data<span style="color:#7600b2;">=</span>data<span style="color:#7600b2;">*</span>alg.expar.w;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000b2;">end</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em><span style="color:#236e25;">% classifier execution -------------------<br />
</span></em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out<span style="color:#7600b2;">=</span>data<span style="color:#7600b2;">*</span>alg.expar.<span style="color:#0000b2;">clf</span>;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out1<span style="color:#7600b2;">=</span>out; out2<span style="color:#7600b2;">=</span>alg;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000b2;">if</span> isoutdecision(alg)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[out1,dectable]<span style="color:#7600b2;">=</span>decide(getops(alg),out);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000b2;">if</span> isoutdecision_name(alg)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out1<span style="color:#7600b2;">=</span>dectable(out1,<span style="color:#7600b2;">:</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000b2;">end</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000b2;">end</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000b2;">end</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#0000b2;">return</span></div>
</html>
{{{sdalg}}} (algorithm) is a Matlab class providing an easy-to-create abstraction of a specific recognition system. The training and execution logic of an algorithm is defined in a single Matlab function. All the parameters needed to perform algorithm training and deliver decisions on new data are stored inside the algorithm object.
* [[Simple example|Custom algorithms: A simple example]]
* [[Using algorithms]]
* [[Algorithm with multiple operating points]]
* [[Creating algorithms from PRTools mappings]]
* [[Creating custom algorithms]]
!!Introduction
PRSD Toolbox algorithms are Matlab objects of ''class sdalg'' encapsulating the training and execution of a pattern recognition system. The algorithm consists of two distinct parts, namely the algorithm definition function and parameters. While the algorithm definition function describes the steps taken in order to train and execute the algorithm, the parameters define the content used during the training and execution. Typically, the algorithm models a system providing decisions (or soft outputs to allow for [[ROC analysis|ROC Analysis]]. However, the user may easily write feature extraction or selection algorithms as well.
The algorithm object exposes its parameters to the user similarly to a Matlab structure. During its life-cycle, the algorithm object undergoes three distinct processes:
* ''Initialization.'' All the parameters needed to commence the training are fixed. These training parameters are stored under the //trpar// field. The initialized algorithm becomes untrained.
* ''Training.'' Algorithm training consists of estimation of various parameters from the labeled training data. This may include feature selection or extraction, classifier training, and definition of a decision operating point. Eventually, the algorithm becomes trained which means it is capable of returning decisions on new, unlabeled, data. The parameters needed for execution are stored in the //expar// field.
* ''Execution'' Presented with data, the algorithm uses the parameters in expar structure to derive decisions.
To see PRSD algorithm in action, look at this [[simple example|Custom algorithms: A simple example]]
Let us illustrate the use of {{{sdalg}}} algorithm on a simple example. We consider a classifier trained in two steps first extracting a feature subset using the Principal Component Analysis (PCA) and then training a classifier in the resulting subspace. 
This classification system is fully defined in a function {{{sda_featex}}}. We can construct an //untrained// algorithm by simply calling its definition function without parameters:
{{{
>> alg=sda_featex
untrained sdalg 'sda_featex'
trpar:
 featex          0x0       2386  mapping  PCA ret. 90.0% var, untrained  mapping   --> pca
 clf             0x0       2506  mapping  Bayes-Normal-2, untrained  mapping   --> qdc
}}}
The untrained algorithm has two //training// parameters, namely the mapping implementing the feature extraction step and the classifier. By default, the PCA projects to a subspace retaining 90% of data variance and the quadratic classifier assuming normal densities (QDC) is used.
We may adjust the algorithm parameters similarly to a structure. Let us fix the PCA output dimensionality to three (simply setting the {{{featex}}} training parameter to an untrained ~PRTools mapping:
<html><pre>
>> alg.trpar.featex=pca([],3)
untrained sdalg 'sda_featex'
trpar:
 featex          0x0       2368  mapping  <em>PCA to 3D</em>, untrained  mapping   --> pca
 clf             0x0       2506  mapping  Bayes-Normal-2, untrained  mapping   --> qdc
</pre></html>We will now train the algorithm on our problem of interest. Let us first prepare the data and split it into the training and test subset:
{{{
>> a=gendatd(100,10)
Difficult Dataset, 100 by 10 dataset with 2 classes: [49  51]
>> a=sdrelab(a,{1 'apple'; 2 'banana'})
new lablist:
1: 1 -> apple 
2: 2 -> banana
Difficult Dataset, 100 by 10 dataset with 2 classes: [49  51]
>> [tr,ts]=gendat(a,0.9)
Difficult Dataset, 91 by 10 dataset with 2 classes: [45  46]
Difficult Dataset, 9 by 10 dataset with 2 classes: [4  5]
}}}
The algorithm is trained using the {{{train}}} method:
{{{
>> tralg=tr*alg
trained sdalg 'sda_featex'
expar:
 w              10x3       3042  mapping  PCA to 3D, 10 to 3 trained  mapping   --> affine
 clf             3x2       3064  mapping  Bayes-Normal-2, 3 to 2 trained  mapping   --> normal_map
ops: Weight-based operating point,2 classes,[0.50,0.50]
output: decision,name
}}}
The trained algorithm contains two //execution// parameters, namely the trained feature extractor and the classifier. Note, that it also has got an operating point, therefore, may provide crisp decisions. Actually, its default output are the decisions.
Executing the algorithm on the new data, we obtain the decisions:
{{{
>> out=execute(tralg,ts)

out =

apple 
apple 
apple 
apple 
banana
banana
banana
banana
banana
}}}
Because the algorithm is fully self-contained, we may apply it also to any 10D data matrix. We will now execute it using the overloaded multiplication operator, following the ~PRTools convention:
{{{
>> rand(1,10)*tralg

ans =

apple 
}}}

next: [[Using algorithms]]
We will now learn how to visualize the data set. We will reduce the original set of 1024 pixels using Principal Component Analysis (PCA) into a smaller number of features retaining the most of the data variability.

PCA command of PRTools allows us to specify either a fraction of variance preserved in the data or directly the desired output dimensionality. A good simple check for the complexity of our problem is to see the dimensionalities trying to preserve 90%, 95% or 99% of the variation:
{{{
>> w=pca(b,0.99)
PR_Warning: getprior: pcaklm: No priors found in dataset, class frequencies are used instead
PCA ret. 99.0% var, 1024 to 181 trained  mapping   --> affine

>> w=pca(b,0.95)
PR_Warning: getprior: pcaklm: No priors found in dataset, class frequencies are used instead
PCA ret. 95.0% var, 1024 to 70 trained  mapping   --> affine

>> w=pca(b,0.9)
PR_Warning: getprior: pcaklm: No priors found in dataset, class frequencies are used instead
PCA ret. 90.0% var, 1024 to 33 trained  mapping   --> affine
}}}
Based on very large dimensionalities needed to describe our imae data, we can conclude that our problem is quite complicated. This is to be expected as the data set contains many specific road sign classes and is, therefore, //multi-modal//.

Let us visualize the  dataset projetion to the 33 dimensions obtained by PCA preserving 90% of variance. We first project the dataset onto the 33D subspace using the trained PCA mapping. The new dataset {{{b2}}} preserves labels and meta-data stored in the original dataset {{{b}}}. Then we invoke the {{{sdscatter}}} command:
{{{
>> b2=b*w
381 by 33 dataset with 3 classes: [177   83  121]
>> sdscatter(b2)
}}}
The scatter plot visualizes 2D projection of the entire (here 33D space). Each data sample (sign image) is represented by a marker. Different marker colors and symbols correspond to different classes.
[img[Scatter plot visualization|images/2_sdscatter.png]]
We can show the legend with class information by pressing the ''l'' key (l for ''l''egend)
[img[Scatter plot with legend|images/3_scatter_legend.png]]
Moving the mouse pointer over the points moves the sample cursor. Detsails on the current sample, highlighted by the cursor, are given in the plot title area. We can see the sample row index in the dataset and the class name.

We can change the features using the cursor keys. The feature presented by the x axis may be changed by pressing //right// and //left// cursor key, the y-axis using //up// and //down// keys.  The axis description consists of the feature index followed by the feature name. You can set descriptive feature names using {{{setfeatlab}}} command).

It is possible to visualize different groupings of samples such as per-sample meta-data defined using {{{setprop}}} command. By pressing the ''g'' key (''g''rouping), we can choose from the available sample groupings. In our dataset, we have only one additional option - the sign ''type''.
[img[Selecting sample grouping|images/4_scatter_groups.png]]
[img[Selecting sample grouping|images/5_scatter_groups2.png]]
By pressing space-bar, we can switch between the two last sample groupings. This allows us to understand, for example, what sample sub-groups cause the class  between.

New, empty, sample grouping may be created by pressing ''n'' key. Initially, all samples are assigned to the //default// group. {{{sdscatter}}} allows the user to specify new sample groups by "painting" the samples. Press ''p'' key to enter the "paint" mode. The dialog window appears asking for the name of the new sample group.
Once the name is defined, the sample cursor is replaced by the rectangle spanning by default 3% of each the visualized range of each feature. 
Samples inside the rectangle are assigned to the selected group using the left mouse button. 

Pressing ''p'' key again leaves the paint mode. Multiple groups may be defined by repeatedly entering the paint mode.
[img[Selecting sample grouping|images/6_scatter_painting.png]]
In order to create the dataset object with the current sample grouping as labels, press the ''s'' key (small s) and enter the desired variable name to be created.
By pressing capital ''S'' key, {{{sdscatter}}} creates a dataset containing all properties including the newly defined sample groupings. 

next: [[Training and evaluating a classifier]]
[[PRSD Studio Documentation]]
In this section, we define a classification problem. Our goal is not to distinguish all the individual road sign types but three major groups, namely the prohibitive signs (red-white-black), obligatory signs (blue), and no-stopping/no-parking signs (red-blue).

We know the mapping of sign types to classes:
{{{
prohibitive:  B1,B2,B4,B21a,B24a,B24b,B20a
obligatory:  C3,C4b,C4c,C4d,C4e,C4f,C5a,C5b
no-stopping/no-parking: B28,B29
}}}
PRSD Toolbox comes with {{{sdrelab}}} command allowing easy definition of classes. Note that PRSD Toolbox commands come with {{{sd}}} name prefix.

We will provide a cell array with class definition rules. Each row of the cell array refers to one rule. The rule may state the string name or indices of current classes and the new class name. The order of classes is always defined by the label list (see the output of {{{getlablist}}} command in [[Creating a dataset]] section):
{{{
>> b=sdrelab(a,{[1:6 9] 'prohibitive'; 7:8 'nostop'; 10:17 'obligatory'})
new lablist:
1: B1   -> prohibitive
2: B2   -> prohibitive
3: B20a -> prohibitive
4: B21a -> prohibitive
5: B24a -> prohibitive
6: B24b -> prohibitive
7: B28  -> nostop     
8: B29  -> nostop     
9: B4   -> prohibitive
10: C3   -> obligatory 
11: C4b  -> obligatory 
12: C4c  -> obligatory 
13: C4d  -> obligatory 
14: C4e  -> obligatory 
15: C4f  -> obligatory 
16: C5a  -> obligatory 
17: C5b  -> obligatory 
381 by 1024 dataset with 3 classes: [177   83  121]
}}}
We have now created a three-class dataset. It is useful to preserve the available sample meta-data in the dataset for the sake of interpretation. We will, therefore, include the sign type in the new dataset as a sample //propery// (meta-data):
{{{
>> b=setprop(b,'type',type)
381 by 1024 dataset with 3 classes: [177   83  121]
}}}
The list of available properties in the dataset may be retrieved using:
{{{
>> getproplist(b)

ans = 

    'ident'
    'type'
}}}
The //ident// property is present by default. It contains a unique sample identifier set when the dataset was created.

We can retrieve a property of a given sample or sample subset using the {{{getprop}}} command:
{{{
>> getprop(b([1 100 120],:),'type')

ans =

C3  
C5b 
C5b 
}}}

next: [[Data visualization]]
PRSD Toolbox handles the decisions only through the objects of {{{sdops}}} (operating point set) class. The sdops object contains everything needed to turn the classifier soft output into the crisp decisions (class names). The operating point is defined by a threshold or a set of weights, the polarity of classifier soft output (similarity or distance), and the names of all decisions.
Let's consider a two class problem:
{{{
>> a=sdrelab(gendatb,{1 'apple'; 2 'banana'})
new lablist:
1: 1 -> apple 
2: 2 -> banana
Banana Set, 100 by 2 dataset with 2 classes: [50  50]
}}}
We create a set of three weighting-based operating points. Note that we must provide the decision names (the lablist of the dataset {{{a}}}) as also these are stored inside the sdops object.
{{{
>> ops=sdops('w',[0.5 0.5;0.2 0.8; 0.7 0.3],getlablist(a))
Weight-based operating set (3 ops, 2 classes) at op 1
}}}
The content of the sdops can be inspected in the following ways:
{{{
>> size(ops)

ans =

     3     2

% provides the list of ops
>> getdata(ops) 

ans =

    0.5000    0.5000
    0.2000    0.8000
    0.7000    0.3000

% provides the weights of a specific operating point:
>> getdata(ops,3)

ans =

    0.7000    0.3000

% provides the label name of the second ("code") class 
>> code2name(ops,2)

ans =

banana

% specifies numerical code for class 'banana'
>> name2code(ops,'banana')

ans =

     2
}}}

next: [[Using operating points]]
Type the text for 'Deploying the classifier'
libPRSD DLL may be invoked directly using Matlab {{{loadlibrary}}} and {{{calllib}}} functions. libPRSD SDK provides several Matlab functions that simplify the use of libPRSD under Matlab.
Alternative execution of trained pipelines is possible through the {{{prsd_mex}}} available in PRSD Toolbox. Note that executing the pipeline through the PRSD Toolbox requires the PRSD Studio development license.

Steps needed to execute a pipeline using Matlab DLL interface:
{{{
% loads the libPRSD library and Matlab libmx library used to pass Matlab data to libPRSD
s=libprsd_init; 

% load the pipeline into libPRSD
s=libprsd_openpipeline(s,'pipeline_file.ppl'); 

% prepare some data to run on. We assume out pipeline takes 2D feature vectors as input
data=rand(100,2); 

% execute on data matrix and produce out matrix:
out=libprsd_process(s,data);

% release the library
libprsd_release(s);
}}}
<<ref sdcrossval>> supports three cross-validation strategies, namely rotation, randomization and leave-one-out. In the rotation scheme, the dataset is split into N parts (in N-fold evaluation). All but one part is used for training the algorithm and the remaining part is used for testing. The rotation uses stratified sampling which means that each class is being split into N parts. This approach assures that all classes preserve prior probabilities found in the total set. Note that due to the class splitting, the smallest number of rotation folds is equal to the number of samples in the smallest class. Each sample is tested only once in the rotation scheme.
{{{
>> a=sdrelab(gendatb,{1 'apple'; 2 'banana'})
new lablist:
1: 1 -> apple 
2: 2 -> banana
Banana Set, 100 by 2 dataset with 2 classes: [50  50]

>> [r1,e1]=sdcrossval(nmc,a)
10 folds: [1: ] [2: ] [3: ] [4: ] [5: ] [6: ] [7: ] [8: ] [9: ] [10: ] 
ROC (w-based op.point, 2 measures, 10 folds)
est: 1:err(apple)=0.12(0.14), 2:err(banana)=0.18(0.15)
completed 10-fold evaluation 'sde_rotation' (alg: 'sda_prtools')
}}}

Randomization cross-validation scheme uses random sample drawn of fraction {{{trfrac}}} from the total (design) dataset. The rest of the data is used for testing. By default, {{{trfrac=0.8}}} is used, i.e. 80% of available data is used for training the algorithm. Due to the randomization, two tests in a cross-validation may contain identical samples.
{{{
>> [r2,e2]=sdcrossval(nmc,a,'method','random')
10 folds: [1: ] [2: ] [3: ] [4: ] [5: ] [6: ] [7: ] [8: ] [9: ] [10: ] 
ROC (w-based op.point, 2 measures, 10 folds)
est: 1:err(apple)=0.14(0.10), 2:err(banana)=0.16(0.18)
completed 10-fold evaluation 'sde_randomization' (alg: 'sda_prtools')
}}}

Leave-on-out scheme uses all but one sample for training and tests only on the remaining sample. Leave-one-out provides the lowest mean error estimates of the three implemented schemes in <<ref sdcrossval>> as it uses the most evidence in training. The shortcoming of this approach is very high variance.
{{{
>> [r3,e3]=sdcrossval(nmc,a,'method','loo')
 samples: ....................................................................................................
ROC (w-based op.point, 2 measures, 100 folds)
est: 1:err(apple)=0.06(0.24), 2:err(banana)=0.09(0.29)
completed -fold evaluation 'sde_loo' (alg: 'sda_prtools')
}}}
Design of pattern recognition system aims at providing two outcomes, namely the algorithm capable of performing decisions for new observations and the estimate of its performance. The classification performance may be reliable estimated only using the data unseen during training. In order to maximally leverage the limited amount of labeled examples available in most projects, PRSD Toolbox offers easy-to-use tools to perform sophisticated cross-validation strategies.
* Introduction
* [[Evaluation for the sets of operating points]]
* [[Accessing the per-fold evaluation details]]
* [[Different cross-validation strategies]]
!!Introduction
''Cross-validation'' is a common algorithm evaluation strategy when the amount of labeled examples for algorithm design is limited. The available design dataset is split into several parts. One part is left out and the algorithm is trained on the remaining parts. The trained algorithm is executed at the remaining part and its decisions are used to compute the classification error. The procedure is repeated so that each part of the design set is used for testing once. Each repetition is called //cross-validation fold//.
Note that because the algorithm produces decisions in each cross-validation fold, its operating point must be fixed at the moment of testing. If the identical operating point is adopted throughout all the folds, the resulting performance estimates are accompanied with statistical variance. 
Example of the cross-validation of the nearest mean classifier 
{{{
>> a=gendatb(200); a=setlablist(a,strvcat({'apple','pear'}))
Banana Set, 200 by 2 dataset with 2 classes: [121   79]
>> r1=sdcrossval(nmc,a)
10 folds: [1: ] [2: ] [3: ] [4: ] [5: ] [6: ] [7: ] [8: ] [9: ] [10: ] 
ROC (w-based op.point, 2 measures, 10 folds)
est: 1:err(apple)=0.17(0.09), 2:err(pear)=0.18(0.12)
}}}
The default 10-fold cross-validation was performed using the default operating point weighting both classes equally. The cross-validation result is the object of class sdroc. The difference to the ROC objects discussed in the ROC section is that all per-fold performance estimates are stored. We may, therefore, see the mean and standard deviations for each measure, instead of the single estimated value.
''User-defined operating points'' may be adopted by the cross-validation scheme. Here, we emphasize the "pear" class being more important in our application:
{{{
>> ops=sdops('w',[0.2 0.8],getlablist(a))
Weight-based operating point,2 classes,[0.20,0.80]
>> r2=sdcrossval(nmc,a,'ops',ops)
10 folds: [1: ] [2: ] [3: ] [4: ] [5: ] [6: ] [7: ] [8: ] [9: ] [10: ] 
ROC (w-based op.point, 2 measures, 10 folds)
est: 1:err(apple)=0.33(0.12), 2:err(pear)=0.04(0.06)
}}}
The user may, naturally, specify the complete set of operating points. In this way, we may effectively estimate the ''average ROC accompanied with variances'' at each operating point. Let us create the grid of operating points varying the weights from 0 to 1 in 0.1 intervals:
{{{
>> W=0:0.1:1;
>> W=[W' 1-W']
W =
         0    1.0000
    0.1000    0.9000
    0.2000    0.8000
    0.3000    0.7000
    0.4000    0.6000
    0.5000    0.5000
    0.6000    0.4000
    0.7000    0.3000
    0.8000    0.2000
    0.9000    0.1000
    1.0000         0
>> ops=sdops('w',W,getlablist(a))
Weight-based operating set (11 ops, 2 classes) at op 1
>> r=sdcrossval(nmc,a,'ops',ops)
10 folds: [1: ] [2: ] [3: ] [4: ] [5: ] [6: ] [7: ] [8: ] [9: ] [10: ] 
ROC (11 w-based op.points, 2 measures, 10 folds), curop: 1
est: 1:err(apple)=1.00(0.00), 2:err(pear)=0.00(0.00)
}}}
The ROC plot now renders also the standard deviation for each of the measures (see the number between parentheses). The sdroc object {{{r}}} is now a matrix with size: # ops, # measures and # folds. By default a 10 cross validation is performed. 
{{{
>> sddrawroc(r)
}}}
[img[images/22_rocvar.png]]
Note that the current operating point is set to the uninteresting extreme situation [0 1]. We may change the current operating point in the ROC object (for example to point #7) using setcurop function:
{{{
>> r=setcurop(r,7)
ROC (11 w-based op.points, 2 measures, 10 folds), curop: 7
est: 1:err(apple)=0.12(0.10), 2:err(pear)=0.20(0.13)
}}}
When we press the ''f'' key (''f''olds) in the ROC Figure, the plot will show all the per-fold realizations for a given operating point instead of the error bars. This view may give us important insight regarding the worst case scenarios:
[img[images/23_rocvar_foldrealizations.png]]

next: [[Accessing the per-fold evaluation details]]
<html>
<div style="text-align:left;color:#000000; background-color:#ffffff; border:solid black 1px; padding:0.5em 1em 0.5em 1em; overflow:auto;font-size:small; font-family:monospace; "><span style="color:#236e25;">/* <br />
&nbsp;&nbsp;&nbsp;Example of calling libPRSD from C code<br />
*/</span><br />
<span style="color:#683821;">#include &lt;stdio.h&gt;<br />
#include &quot;prsd.h&quot;<br />
</span><br />
<span style="color:#683821;">#define PRSD_ABORT(pk) { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br />
&nbsp;&nbsp;printf(&quot;%d: %s\n&quot;,prsd_GetErrorCode(pk),prsd_GetErrorMsg(pk)); &nbsp;&nbsp;&nbsp;\<br />
&nbsp;&nbsp;if( pk!=NULL ) prsd_ReleaseKernel(pk); &nbsp;&nbsp;&nbsp;\<br />
&nbsp;&nbsp;return(PRSD_ERROR); }<br />
</span><br />
<span style="color:#881350;">int</span> <span style="color:#003369;">main</span>(<span style="color:#881350;">void</span>)<br />
{<br />
&nbsp;&nbsp;prkernel* pk=<span style="color:#881350;">NULL</span>;<br />
&nbsp;&nbsp;<span style="color:#881350;">int</span> res,pind,sc,fc,i;<br />
&nbsp;&nbsp;<span style="color:#881350;">double</span>* pd1,*pd2;<br />
<br />
&nbsp;&nbsp;<span style="color:#236e25;">/* initialize the PRSD library: pass NULL as we provide the license<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file in the same directory as the library binary<br />
&nbsp;&nbsp;&nbsp;*/</span><br />
&nbsp;&nbsp;pk=<span style="color:#003369;">prsd_InitKernel</span>(<span style="color:#881350;">NULL</span>);<br />
&nbsp;&nbsp;<span style="color:#881350;">if</span>( pk == <span style="color:#881350;">NULL</span> ) <span style="color:#003369;">PRSD_ABORT</span>(pk);<br />
&nbsp;&nbsp;<span style="color:#003369;">printf</span>(<span style="color:#760f15;">&quot;%s\n&quot;</span>,<span style="color:#003369;">prsd_GetErrorMsg</span>(pk));<br />
<br />
&nbsp;&nbsp;<span style="color:#236e25;">/* load the pipeline: returns the pipeline index */</span><br />
&nbsp;&nbsp;pind=<span style="color:#003369;">prsd_LoadPipeline</span>(pk,<span style="color:#760f15;">&quot;fisher.ppl&quot;</span>);<br />
&nbsp;&nbsp;<span style="color:#881350;">if</span>( res==PRSD_ERROR ) <span style="color:#003369;">PRSD_ABORT</span>(pk);<br />
<br />
&nbsp;&nbsp;<span style="color:#236e25;">/* print the pipeline name */</span><br />
&nbsp;&nbsp;<span style="color:#003369;">printf</span>(<span style="color:#760f15;">&quot;pipeline name='%s' &quot;</span>,<span style="color:#003369;">prsd_GetName</span>(pk,pind));<br />
<br />
&nbsp;&nbsp;<span style="color:#236e25;">/* allocate the input buffer (sc samples in 2D)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- offset to go to next sample == 1,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- offset to go to next feature == sample count */</span><br />
&nbsp;&nbsp;sc=<span style="color:#0000ff;">4</span>; <span style="color:#236e25;">/* you can change sc */</span><br />
&nbsp;&nbsp;fc=<span style="color:#0000ff;">2</span>; <span style="color:#236e25;">/* fc is fixed by the pipeline! */</span><br />
&nbsp;&nbsp;pd1=<span style="color:#003369;">calloc</span>(sc*fc,<span style="color:#881350;">sizeof</span>(<span style="color:#881350;">double</span>));<br />
&nbsp;&nbsp;pd1[<span style="color:#0000ff;">0</span>]=<span style="color:#0000ff;">7.0</span>;<br />
&nbsp;&nbsp;pd1[<span style="color:#0000ff;">0</span>+sc]=<span style="color:#0000ff;">7.0</span>;<br />
&nbsp;&nbsp;pd1[<span style="color:#0000ff;">1</span>]=<span style="color:#0000ff;">1.2</span>;<br />
&nbsp;&nbsp;pd1[<span style="color:#0000ff;">1</span>+sc]=<span style="color:#0000ff;">1.3</span>;<br />
<br />
&nbsp;&nbsp;<span style="color:#236e25;">/* allocate result buffer */</span><br />
&nbsp;&nbsp;pd2=<span style="color:#003369;">calloc</span>(sc*<span style="color:#003369;">prsd_GetOutputFc</span>(pk,pind),<span style="color:#881350;">sizeof</span>(<span style="color:#881350;">double</span>));<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;<span style="color:#236e25;">/* attach memory to the pipeline */</span><br />
&nbsp;&nbsp;res=<span style="color:#003369;">prsd_AttachMemToInput</span>(pk,pind,pd1,sc,fc,<span style="color:#0000ff;">1</span>,sc);<br />
&nbsp;&nbsp;<span style="color:#881350;">if</span>( res==PRSD_ERROR ) <span style="color:#003369;">PRSD_ABORT</span>(pk);<br />
&nbsp;&nbsp;res=<span style="color:#003369;">prsd_AttachMemToOutput</span>(pk,pind,pd2,sc,fc,<span style="color:#0000ff;">1</span>,sc);<br />
&nbsp;&nbsp;<span style="color:#881350;">if</span>( res==PRSD_ERROR ) <span style="color:#003369;">PRSD_ABORT</span>(pk);<br />
&nbsp;<br />
&nbsp;&nbsp;<span style="color:#236e25;">/* test whether the algorithm is ready to run */</span><br />
&nbsp;&nbsp;res=<span style="color:#003369;">prsd_IsReadyToExecute</span>(pk,pind);<br />
&nbsp;&nbsp;<span style="color:#881350;">if</span>( res==PRSD_NO ) <span style="color:#003369;">PRSD_ABORT</span>(pk);<br />
<br />
&nbsp;&nbsp;res=<span style="color:#003369;">prsd_Execute</span>(pk,pind);<br />
<br />
&nbsp;&nbsp;<span style="color:#236e25;">/* print out the outputs */</span><br />
&nbsp;&nbsp;<span style="color:#003369;">printf</span>(<span style="color:#760f15;">&quot;first run:\n&quot;</span>);<br />
&nbsp;&nbsp;<span style="color:#881350;">for</span>(i=<span style="color:#0000ff;">0</span>; i&lt;sc; i++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">printf</span>(<span style="color:#760f15;">&quot;out(%d)=%f,%f\n&quot;</span>,i,pd2[i],pd2[i+sc]);<br />
<br />
&nbsp;&nbsp;<span style="color:#236e25;">/* fill-in new data to the input buffer */</span><br />
&nbsp;&nbsp;pd1[<span style="color:#0000ff;">0</span>]=<span style="color:#0000ff;">2.2</span>;<br />
&nbsp;&nbsp;pd1[<span style="color:#0000ff;">0</span>+sc]=<span style="color:#0000ff;">3.1</span>;<br />
<br />
&nbsp;&nbsp;<span style="color:#236e25;">/* execute the pipeline again */</span><br />
&nbsp;&nbsp;<span style="color:#003369;">prsd_Execute</span>(pk,pind);<br />
<br />
&nbsp;&nbsp;<span style="color:#236e25;">/* print out the outputs */</span><br />
&nbsp;&nbsp;<span style="color:#003369;">printf</span>(<span style="color:#760f15;">&quot;second run:\n&quot;</span>);<br />
&nbsp;&nbsp;<span style="color:#881350;">for</span>(i=<span style="color:#0000ff;">0</span>; i&lt;sc; i++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">printf</span>(<span style="color:#760f15;">&quot;out(%d)=%f,%f\n&quot;</span>,i,pd2[i],pd2[i+sc]);<br />
<br />
&nbsp;&nbsp;<span style="color:#003369;">free</span>(pd1);<br />
&nbsp;&nbsp;<span style="color:#003369;">free</span>(pd2);<br />
<br />
&nbsp;&nbsp;<span style="color:#236e25;">/* release the PRSD library */</span><br />
&nbsp;&nbsp;<span style="color:#003369;">prsd_ReleaseKernel</span>(pk);<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;<span style="color:#881350;">return</span>(<span style="color:#0000ff;">0</span>);<br />
}<br />
</div></html>
{{{
>> a=sdrelab(gendatb,{1 'apple'; 2 'banana'})
new lablist:
1: 1 -> apple 
2: 2 -> banana
Banana Set, 100 by 2 dataset with 2 classes: [50  50]
}}}
We train a simple ~PRTools classifier such as Fisher linear discriminant:
{{{
>> w=fisherc(a)
Fisher, 2 to 2 trained classifier --> affine
}}}
We convert the trained mapping {{{w}}} to a pipeline:
{{{
>> p=sdconvert(w)
sequential pipeline     2x2 'Fisher'
 1  sdp_affine          2x2  Fisher
 2  sdp_sigmoid         2x2  scale=1.00
}}}
Note, that the resulting pipeline consists of two steps. The affine mapping and the sigmoid normalization of the output (~PRTools adds the sigmoid mapping to allow fusion of different classifier architectures. The sigmoid estimates a classifier-conditional posteriori probability output).
We execute the pipeline on new data:
{{{
>> data

data =

    0.1471    0.0775
    0.7218    0.1306
    0.8553    0.4457
    0.7777    0.9343
    0.3283    0.8653

>> sdexe(p,data)

ans =

    0.7516    0.2484
    0.8371    0.1629
    0.8338    0.1662
    0.7858    0.2142
    0.7107    0.2893
}}}
Comparing with the ~PRTools result:
{{{
>> double(data*w)

ans =

    0.7516    0.2484
    0.8371    0.1629
    0.8338    0.1662
    0.7858    0.2142
    0.7107    0.2893
}}}
The {{{*}}} operator may be used also for pipelines so the expression {{{data*p}}} simply calls {{{sdexe}}} internally. Individual steps in the pipeline may be accessed directly using parentheses {{{()}}}:
{{{
>> p(2)
sequential pipeline     2x2 'Fisher'
 1  sdp_sigmoid         2x2  scale=1.00
}}}
In order to access the //content// of the pipeline step (i.e. the parameters), use the curly brackets:
{{{
>> p{1}

ans = 

       rot: [2x2 double]
    offset: [1.0024 -1.0024]

>> p{1}.rot

ans =

    0.9672   -0.9672
   -0.4867    0.4867

>> p{2}

ans = 

    scale: 1
}}}
/% * pipeline objects ({{{sdppl}}}) encapsulate execution of a trained pattern recognition algorithm
* pipelines are always executed through the C-based libPRSD library (MEX under Matlab) using <<ref sdexe>> function
* pipelines may be exported <<ref sdexport>> for execution using libPRSD DLL outside Matlab.
* Identical execution code is used when executing pipelines in and out of Matlab (Matlab may be used to test the results obtained later by libPRSD in the production application)
* pipelines are by default sequential series of actions
* pipelines may be created manually by the user by providing canonical (basic) classifier parameters
* all parameters required for pipeline execution may be extracted from a pipeline in unified manner
* PRTools mappings may be converted into a pipeline automatically using <<ref sdconvert>> function
%/
PRSD Studio provides a comprehensive toolkit for execution of trained pattern recognition algorithms in custom applications using the C-based libPRSD library. Pipeline class plays the key role in defining the pattern recognition algorithms for deployment.
* Introduction
* [[Example on using pipelines]]
!!Introduction
Algorithms trained in PRSD Toolbox may be executed outside Matlab using the libPRSD library. The algorithm execution logic is defined in Matlab through the ''pipeline object''. A pipeline example may be a sequence of the PCA feature extractor followed by a mixture of Gaussians and the decision at a specific operating point. The user may interactively test the pipeline steps under Matlab using the libPRSD MEX interface. Once ready, the pipeline object is simply exported to a binary file readable by the libPRSD DLL linked to a custom application. The task of embedding the custom application with the libPRSD consists of connecting the pipeline input and output to the respective pre-allocated memory buffers. Because the user does not manually call any algorithm-specific functions in libPRSD, replacing the pipeline in the production setting is as easy as loading a new data file.
{{{
>> a=gendatb; a=setlablist(a,strvcat({'apple','pear'}))
Banana Set, 100 by 2 dataset with 2 classes: [50  50]
>> w=qdc(a)
Bayes-Normal-2, 2 to 2 trained  mapping   --> normal_map

>> p=sdconvert(w) % convert PRTools mapping into a pipeline
sequential pipeline     2x2 'Bayes-Normal-2'
 1  sdp_normal          2x2  Bayes-Normal-2, 2 classes, 2 components

>> sdexport(p,'test1.ppl')
Exporting pipeline to: 'test1.ppl'..ok

>> b=gendatb; b=setlablist(b,strvcat({'apple','pear'})) % prepare the test set
Banana Set, 100 by 2 dataset with 2 classes: [50  50]
>> dlmwrite('data.txt',double(b)) % save as the comma-separated text file
}}}
We will now start the ~PRSDdemo application located in the ~PRSD_Studio/sdk directory. This GUI application links to the libPRSD dynamic library. We will load the pipeline from the test1.ppl file and data from the data.txt file. The quadratic classifier is invoked by clicking the 'Execute pipeline' button:
[img[images/24_prsddemo.png]]
We may now compare the execution results with the classifier output under Matlab:
{{{
>> out=b*w
Banana Set, 100 by 2 dataset with 2 classes: [50  50]
>> +out(1:4,:)
ans =
    0.0054    0.0001
    0.0064    0.0001
    0.0041    0.0002
    0.0051    0.0000
}}}
/%
!Defining a pipeline manually
Let us define a nearest mean pipeline. First, we compute mean vector of each class:
{{{
>> a
Banana Set, 100 by 2 dataset with 2 classes: [50  50]
>> m=+meancov(a)

m =

    1.1447   -2.1750
   -5.3405   -2.0437

}}}
We can now define <<ref sdp_1nn>> action:
{{{
>> p=sdp_1nn(m,[1 2]',{'apple','banana'})
sequential pipeline     2x2 ''
 1  sdp_1nn             2x2  2 classes, 2 prototypes

>> p{1}

ans = 

    proto: [2x2 double]
     nlab: [2x1 double]
}}}
Note that we provide the mean vectors, the label for each and, optionally, the class names.
We can now execute the pipeline on arbitrary 2D data:
{{{
>> data*p

ans =

    6.0688   34.6132
    5.4943   41.4786
    6.9517   44.5849
    9.8025   46.3004
    9.9097   40.5975
}}}
The result is identical to squared Euclidean distance computed to each class prototype:
{{{
>> +distm(data,m)

ans =

    6.0688   34.6132
    5.4943   41.4786
    6.9517   44.5849
    9.8025   46.3004
    9.9097   40.5975
}}}
%/

next: [[Example on using pipelines]]
A classifier, converting the soft outputs into decisions, is said to work at a specific operating point. Classifier performance in a specific application may be, usually, significantly improved by fine-tuning the operating point based on the application specific requirements (costs). The process of classifier tuning involves evaluation at large number of operating points, so called Receiver Operator Characteristic (ROC) analysis.

In this section, we perform a simple ROC analysis on the road sign classifier. Our starting point will be the soft outputs normalized using the PRTools {{{classc}}} command to the form of posteriori probabilities:
{{{
>> out=ts*w*w2*classc
189 by 3 dataset with 3 classes: [88  41  60]
}}}

Let us now estimate the ROC from the soft outputs:

{{{
>> r=sdroc(out)

maxpoints =

    30

.....
ROC (31 w-based op.points, 3 measures), curop: 1
est: 1:err(prohibitive)=0.15, 2:err(nostop)=0.20, 3:err(obligatory)=0.48
}}}

The ROC estimates 3 per-class errors for 31 operating points (weight triplets). Each ROC ({{{sdroc}}} object) does maintain one operating point as //current//. By default, it is the equal weight (default) operating point which is returned as number one.

We can draw the ROC using the {{{sddrawroc}}} command:
{{{
>> sddrawroc(r)
}}}

[img[ROC plot|images/7_roc.png]]

The ROC plot shows first two error measures, each marker representing one operating point. The current operating point is rendered in black. Moving the mouse pointer over the plot highlights the closest point. Its index and respective error estimates are printed in the figure title area. By pressing the ''w'' key, we get the actual weight values, instead.

Using cursor keys we can change the error measures shown - left/right for the x-axis and up/down for the y-axis.

An operating point of interest may be selected by left mouse click.

In order to save the decision mapping with the selected operating point as current, press ''s'' key and will in the name of the resulting decision mapping.

Operating point may be also selected manually using the {{{setcurop}}} command:
{{{
>> wd2=setcurop(wd,10)
Weight-based decision (3 classes, 31 ops) at op 10, 3 to 1 trained  mapping   --> sddecide
}}}


This getting started section uses a simple road sign recognition problem as a running example. We will show how to create a dataset from sample measurements and meta-data, how to train a classifier, evaluate its performance, define a specific operating point using ROC analysis and export the final classifier for execution using libPRSD DLL in a custom application.
# [[Creating a dataset]]
# [[Defining a pattern recognition problem]]
# [[Data visualization]]
# [[Training and evaluating a classifier]]
# [[Fine-tuning the classifier (ROC Analysis)]]
/% # [[Deploying the classifier]] %/
To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:
* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* MainMenu: The menu (usually on the left)
* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
There are two types of hardware dongles used in PRSD Studio: Long and short. The long dongle is used for ''development licenses'' that comprise both the PRSD Toolbox under Matlab environment and the libPRSD out of Matlab. The short dongle is adopted for ''deployment licenses'' using the libPRSD.
''PRSD Studio software requirements:''
* PC 32-bit x86 operating system: MS Windows, Mac OS X, GNU/Linux
* Matlab 7.x (http://www.mathworks.com)
* ~PRTools 4.1 toolbox which can be downloaded from http://prtools.org. ~PRTools can be used free of charge for non-profit use and commercial in-house use, see [[PRTools license|http://prtools.org/license.html]] for details.
!Evaluation version with internet activation
In order to instal evaluation version of PRSD Studio you need
* Software distribution archive downloaded via http://prsysdesign.net
* [[Activation key]] in the e-mail message sent automatically after filling the download form
* Internet connection
The installation consists of the following steps:
# Unzip the PRSD Studio distribution archive
# Start Matlab 
# Install ~PRTools toolbox. Unzip its distribution archive and add the ~PRTools toolbox on the Matlab path using //Set Path// command in //File// menu or using {{{addpath}}} command
# In Matlab, change the current directory to the {{{matlab}}} sub-directory of the distribution directory
# Execute the {{{prsd_init}}} script and enter the activation key you received in after downloading the software. The installation script requests the license file for the specific machine. The license file, returned by the PR Sys Design activation server is called {{{prsd_studio_eval.lic}}}. It will be stored in the {{{matlab/prsd_toolbox}}} directory and copied to the {{{sdk}}} directory.
# PRSD Toolbox should be now ready for use. In case you encounter any problems, please [[send us the error message|mailto:support@prsysdesign.net]] so we can help you out.
!Demo of commercial version with internet activation
In order to instal commercial demo version of PRSD Studio you need
* Software distribution archive downloaded from the link you received in the e-mail from PR Sys Design
* [[Activation keys|Activation key]] from the same e-mail (one key for PRSD Toolbox and one for libPRSD)
* Internet connection
The installation consists of the following steps:
# Unzip the PRSD Studio distribution archive
# Start Matlab 
# Install ~PRTools toolbox. Unzip its distribution archive and add the ~PRTools toolbox on the Matlab path using //Set Path// command in //File// menu or using {{{addpath}}} command
# Add {{{prsd_toolbox}}} on the Matlab path
# Execute {{{prsd_activate('KEY')}}} command for each key you received (note the apostrophes sorrounding the key string). 
# Copy the {{{prsd_studio.lic}}} file in {{{prsd_toolbox}}} directory to {{{sdk}}} directory so you can execute pipelines via {{{libprsd.dll}}}
# PRSD Studio should be now ready for use. In case you encounter any problems, please [[send us the error message|mailto:support@prsysdesign.net]] so we can help you out.
!Commercial version using a hardware dongle
Three components are needed to install commercial version of PRSD Studio:
* [[Hardware dongle]]
* Software distribution archive
* [[License file]] for the specific dongle
All released distribution files and user-specific license files are available from the private customer center at http://prsysdesign.net as a part of the software maintenance program (login required).
The installation consists of the following steps:
# Unzip the PRSD Studio distribution archive
# Copy the development license file to the {{{matlab\prsd_toolbox}}} directory and deployment license file(s) to the {{{sdk}}} directory
# Plug in the development (long) hardware dongle
# Start Matlab 
# Install ~PRTools toolbox. Unzip its distribution archive and add the ~PRTools toolbox on the Matlab path using //Set Path// command in //File// menu or using {{{addpath}}} command
# Add path to the PRSD Toolbox (directory {{{matlab\prsd_toolbox}}} in the PRSD Studio distribution package) 
# Run {{{prsd_mex}}} command. It should provide copyright notice and version number when PRSD Studio is correctly installed:
{{{
>> prsd_mex
PRSD Toolbox 1.0 (20-Aug-2008), Copyright (C) 2008, PR Sys Design, All rights reserved
Commercial license (customer, contract #X). The license is permanent
}}}
If you encounter problems, consult the [[Installation troubleshooting]] section.
!! Error checking out license: Wrong host for license (-4)

The host (hardware dongle), defined in the license file, was not found. Make sure that correct dongle is attached to the computer. Each dongle has a number (PRSD XXX) Check, that the license file refers to the same dongle - the license file name should list the identical number.

Check that the correct license file is present in the same directory as the {{{prsd_mex}}} binary:
{{{
>> which prsd_mex
C:\PRSD_Studio_1.0_21Aug2008_win_M74\matlab\prsd_toolbox\prsd_mex.mexw32
>> ls C:\PRSD_Studio_1.0_21Aug2008_win_M74\matlab\prsd_toolbox\*.lic
C:\PRSD_Studio_1.0_21Aug2008_win_M74\matlab\prsd_toolbox\customer_devel_prsd003.lic
}}}
The license file in this example expects the dongle ~PRSD003 to be present.

# Add DLL and {{{prsd.h}}} in the project of the custom application
# Prepare the application data into the format expected by the libPRSD library. The application data should be stored in memory such that sample offset is one and feature offset is the number of samples in the data buffer.
# Initialize the library using the [[prsd_InitKernel]]
# Load pipeline using [[prsd_LoadPipeline]]
# Connect the pipeline to the application input data buffer with [[prsd_AttachMemToInput]] or [[prsd_BufAttachToInput]]
# Connect the pipeline to the application output (result) buffer with [[prsd_AttachMemToOutput]] or [[prsd_BufAttachToOutput]]
# Check if the pipeline is correctly setup using [[prsd_IsReadyToExecute]]
# Execute pipeline using [[prsd_Execute]]
# Read out the results from the output buffer
# Fill new input data to the input buffer
# Execute pipeline using [[prsd_Execute]]
# Read out the results from the output buffer
...
13. Release buffers allocated by the application
14. Release the library using [[prsd_ReleaseKernel]]
PRSD Toolbox allows a wide range of visualization possibilities through the <<ref sdscatter>> function. 
Let's first generate an artificial dataset for visualization purposes:
{{{
>>data= [((rand(100,3).*4) +2*ones(100,3)); (rand(80,3).*4); (rand(120,3)*2+4*ones(120,3))];
>>lab=genlab([100 80 120],{'apple';'pear';'banana'});
>>a=dataset(data,lab)
300 by 3 dataset with 3 classes: [100  120   80]
>>a=setfeatlab(a,char('weight','lengh','color'));
>>quality=genlab([60 40 30 50 70 50],{'appleQ1';'appleQ2';'pearQ1';'pearQ2';'bananaQ1';'bananaQ2'});
>>a=setprop(a,'quality',quality);

>>sdscatter(a)
}}}
[img[Scatter plot without legend |images/8_sdscatter.png]]
The <<ref sdscatter>> applied to the dataset {{{a}}} visualizes the scatter plot of the samples. Each marker represents a sample, different markers/colors are used for the different classes. Moving the mouse pointer over the points moves the sample cursor. Details on the current sample, highlighted by the cursor, are given in the figure title area. We can see the sample row index in the dataset, and the class name.

We can change the feature combination using the cursor keys. The feature presented by the x axis may be changed by pressing the //right// and //left// cursor key, the y-axis using the //up// and //down// keys. The axis description consists of the feature index followed by the feature name. You can set descriptive feature names using <<ref setfeatlab>> command. To visualize the legend, select the ''Show legend'' command in the ''Scatter'' menu, or alternatively, press the letter "l" (for ''l''egend) on the keyboard.  
[img[Scatter plot without legend |images/9_sdscatter_legend.png]]
!show class labels or other data properties
It is possible to visualize different groupings of samples such as per-sample meta-data defined using <<ref setprop>> command. 
In the Scatter menu, the ''Use class grouping'' option will show you the available meta-data. You can choose the meta-data to visualize.  In our dataset, we have one additional option: the "quality" description of the fruit.
[img[Selecting sample grouping|images/10_scatter_groups.png]]

Selecting this option will produce the corresponding visualization.  
[img[Selecting sample grouping|images/11_scatter_groups2.png]]
By pressing space-bar, we can switch between the two last sample groupings. This allows us to understand, for example, if an eventual class overlap is caused by a specific sample sub-group. 

In case of class overlap, a class may be partially hidden by another. In order to inspect this overlap it is possible to select the class to be plotted on top of the others. This can be done simply by the ''Class to top'' option of the Scatter menu and specifying the class of interest.

!Rename a class 
You can easily rename an existing class, via the ''Rename class'' option in the Scatter menu. The list of available classes will be shown. Choose the class you want to rename and write the new name in the pop up window. In the figure below we are renaming the class 'apple' with the class name 'orange'.  
[img[Rename a class|images/11b_scatter_rename.png]]

!Intractive labeling of samples in scatter plot
New, empty, sample grouping may be created by selecting the ''New class grouping'' in the Scatter menu or by pressing ''n'' key. The dialog window appears asking for the name of the new sample group. Initially, all samples are assigned to the //default// group. <<ref sdscatter>> allows the user to specify new sample groups. Go to the ''Paint class'' in the Scatter menu and select the ''Create new class'' command. A dialogue window will ask you for the name of the class (//target// is used as a default name). 
Once the name is defined, the sample cursor is replaced by the rectangle spanning by default 3% of the visualized range of each feature. Samples inside the rectangle are assigned to the selected group using the left mouse button. To leave the paint mode select the ''Stop painting'' command in the Scatter menu.
[img[Selecting sample grouping|images/12_scatter_painting_newgroup.png]]

You may also add a class to an existing class grouping. Just select from ''Use class grouping'' in the Scatter menu the group you are interested in. Then enter the 'paint' mode by selecting ''Create new class'' in the 'Paint class' option. 
[img[Painting samples|images/12b_scatter_painting.png]]

You can now name the new class and select the samples you want to label. The meta-data information with the new labels you choose will be updated. As visualized in the figure below the new class 'target' is added to the three previously defined. 
[img[Painting samples|images/12c_scatter_painting.png]]

! Save the modified dataset
In order to create the dataset object with the current sample grouping as labels in the MATLAB workspace, select ''Create dataset with current label'' in the Scatter menu, or alternatively press the ''s'' key (small s), and enter the desired variable name to be created. By selecting the ''Create datasets with all groupings'', or by pressing capital ''S'' key, {{{sdscatter}}} creates a dataset containing all properties including the newly defined sample groupings. 
 
next: [[Visualization of images]]
PRSD Studio license file is a text file describing all conditions of a specific license such as the dongle ID, expiration date, contract and customer details. The license is generated specifically for a given [[Hardware dongle]].
The license file should be copied to the same directory as PRSD binaries, i.e. inside the {{{prsd_toolbox}}} directory, in the {{{sdk}}} directory and in the application directory where {{{libprsd.dll}} is stored.
[[PRSD Doc Index|PRSD Studio Documentation]]
---------
[[Getting Started|Getting Started with PRSD Studio]]
---------
[[User's guide|PRSD Toolbox User's Guide]]
---------
[[libPRSD Guide]]
[[libPRSD API|API Reference]]
Making decisions is the fundamental raison d'etre of a pattern recognition system. However, majority of statistical classifiers don't produce decisions directly. Instead, they deliver soft outputs such as estimated posteriori probability of class membership, confidence level or distance to a decision boundary. This section introduces a comprehensive set of PRSD Toolbox tools for converting the soft outputs into crisp decisions. Understanding how decisions are made is necessary in order to optimize the performance of a pattern recognition system. 
* Introduction
* [[Defining operating points]]
* [[Using operating points]]
** Example on weighting-based decisions
** Example on thresholding-based decisions
** Integration with ~PRTools
!Introduction
We can distinguish two fundamentally different decision making strategies:
* ''Thresholding-based decisions'' are performed when a single concept of interest (target) is to be detected. In order to decide whether an observation does or does not correspond to the target concept, some form of the target-related similarity (soft-output) is computed and //thresholded//. If the similarity value falls above the pre-specified threshold, the observation is labeled as "target", otherwise as "non-target". This decision-making strategy is applied in two-class classification and detection (sometimes called distance-based rejection or one-class classification).
* ''Weighting-based decisions'' are adopted for selecting one of multiple classes. The classifier provides a set of comparable outputs, each related to a specific class. In the simplest scenario, the output with the maximum value defines the decision. Note that this strategy assumes that all the classes are equally important. In many practical situations some classes exhibit higher misclassification costs than others. For example, labeling an ill patient as healthy in cancer diagnostics has much higher human cost than the opposite error, which can be easily discovered by the follow-up analysis. Cost-sensitive decisions are accomplished by weighting the soft-outputs before the maximum operation.
Note that, in general, the soft-output weights are not identical to class priors. This analogy holds only in situation where the classifier is trained on a balanced dataset with equal class sizes. Otherwise, the weights do not directly correspond to the test set priors but rather rectify the original class imbalance.
The decisions are performed at a specific ''operating point''. According to the popular view, the operating point is the threshold value or the set of weights. In PRSD Studio, however, the term operating point refers to a //complete// body of information required to return decisions on the output of a given classifier in a specific problem. In addition to the threshold or weights, the operating point in PRSD Studio encapsulates the polarity of the classifier output (similarity or distance). This allows us to perform decisions also for classifiers such as the nearest neighbor rule without output normalization. Additionally, the numerical decision codes and string names of decisions are included in the operating point. This allows construction of execution pipelines performing decisions at multiple stages, such as detector-classifier cascades or two-level systems with trained combiners.

Next: [[Defining operating points]]
PRSD Toolbox ROC analysis framework handles the multi-class situations similarly to the two-class case. When estimating a multi-class ROC, both the operating points and the related estimates are constructed by the optimization algorithm. Large number of randomly generated operating points is evaluated minimizing the maximum per-class error. The returned set is pruned preserving only the solutions with unique per-class errors. Although this algorithm is, of course, suboptimal, it allows fast investigation of error conditions for multi-class problems.
{{{
>> a=gendatm(1000) % simple multi-class dataset
Multi-Class Problem, 1000 by 2 dataset with 8 classes: [125  117  125  132  138  112  125  126]
>> [tr,ts]=gendat(a,0.5)
Multi-Class Problem, 502 by 2 dataset with 8 classes: [63  59  63  66  69  56  63  63]
Multi-Class Problem, 498 by 2 dataset with 8 classes: [62  58  62  66  69  56  62  63]
>> w=qdc(tr)
Bayes-Normal-2, 2 to 8 trained  mapping   --> normal_map
>> out=ts*w % soft classifier outputs on the test set
Multi-Class Problem, 498 by 8 dataset with 8 classes: [62  58  62  66  69  56  62  63]
>> r=sdroc(out)
.....
ROC (9 w-based op.points, 8 measures), curop: 1
est: 1:err(a)=0.16, 2:err(b)=0.14, 3:err(c)=0.11, 4:err(d)=0.27, 5:err(e)=0.10, 6:err(f)=0.11,
 7:err(g)=0.21, 8:err(h)=0.05
sddrawroc(r)
}}}
[img[ROC multiclass |images/17_roc_multiclass.png]]
Note that the points found are very limited subset from the full 7D mesh applicable in the 8-class problem.

next: [[ROC within the cross-validation method|Evaluation for the sets of operating points]]
These InterfaceOptions for customising TiddlyWiki are saved in your browser

Your username for signing your edits. Write it as a WikiWord (eg JoeBloggs)

<<option txtUserName>>
<<option chkSinglePageMode>> Display one article at a time
<<option chkSaveBackups>> SaveBackups
<<option chkAutoSave>> AutoSave
<<option chkRegExpSearch>> RegExpSearch
<<option chkCaseSensitiveSearch>> CaseSensitiveSearch
<<option chkAnimate>> EnableAnimations

----
Also see AdvancedOptions
!PRSD Studio
* [[Release notes]]
* [[Installation instructions]]
* [[Getting Started with PRSD Studio]]
!PRSD Toolbox
* [[User's guide|PRSD Toolbox User's Guide]] /% * Command reference %/
!libPRSD
* [[LibPRSD Integrator's guide|libPRSD Guide]]
* [[libPRSD API reference|API Reference]]
!Introduction
# [[Building pattern recognition systems with PRSD Studio]]
# [[Preliminary info on PRTools|PRTools basics]]
!Using PRSD Studio
# [[Preparing the data]]
# [[Visualizing the data]]
# [[Training a model]]
# [[Making decisions]]
# [[ROC Analysis]]
# [[Custom algorithms]]
# [[Evaluation]]
# [[Execution pipelines]]
/%
![[Integration with other toolboxes]]
# [[PRTools]]
# [[DD_Tools]]
# [[LibSVM]]
%/
In PRSD Toolbox decision mapping may be directly applied to numerical data (classifier outputs) and provide decisions (datasets are not necessary). To illustrate the difference between PRSD decision mapping and ~PRTools approach, let's consider this example:
{{{
>> data

data =

    0.1471    0.0775
    0.7218    0.1306
    0.8553    0.4457
    0.7777    0.9343
    0.3283    0.8653

>> data*wd

ans =

apple 
apple 
apple 
banana
banana
}}}
~PRTools {{{labeld}}} command will cast an error in this situation as it requires a dataset on its input (it takes decision names from {{{featlab}}} field of the dataset):
{{{
>> data*labeld
??? Undefined function or method 'getfeatlab' for input arguments of type 'double'.

Error in ==> <a href="error:prtools/labeld.m,69,1">labeld at 69</a>
		[m,k] = size(a); featlist = getfeatlab(a);

Error in ==> <a href="error:prtools/map.m,166,1">map at 166</a>
			feval(mapp,a,pars{:})

Error in ==> prtools/@mapping/mtimes.p>mtimes at 17
}}}
If we create a dataset and set as feature labels arbitrary names:
{{{
>> data2=dataset(data,[],'featlab',{'pear','orange'})
5 by 2 dataset with 0 classes: []
>> getfeatlab(data2)

ans =

pear  
orange
}}}
The ~PRTools {{{labeld}}} routine uses them as decision names:
{{{
>> data2*labeld

ans =

pear  
pear  
pear  
orange
orange
}}}
However, our decision mapping still outputs //apple// and //banana// as defined by our operating point:
{{{
>> data2*wd

ans =

apple 
apple 
apple 
banana
banana
}}}

~PRTools toolbox introduces two main concepts, namely the //dataset// and //mapping//. Dataset is a collection of data samples accompanied with meta-data such as class labels, feature labels or class prior probabilities. Mapping is a data transformation such as a feature extractor or a classifier. Mapping may be easily chained into sequences using multiplication operator {{{*}}}.
!!Creating ~PRTools dataset
{{{
>> data_matrix=rand(20,3);
>> label_vector=genlab([8 7 5],strvcat({'apple','banana','orange'}))
label_vector =
apple 
apple 
apple 
apple 
apple 
apple 
apple 
apple 
banana
banana
banana
banana
banana
banana
banana
orange
orange
orange
orange
orange
>> data=dataset(data_matrix,label_vector)
20 by 3 dataset with 3 classes: [8  7  5]
}}}
!!Dataset subsets
Datasets behave like data matrices with samples in the rows and features in the columns:
{{{
>> data(4,:)
1 by 3 dataset with 3 classes: [1  0  0]
>> data([1:4 18:end],[2 3])
7 by 2 dataset with 3 classes: [4  0  3]
>> [tr,ts]=gendat(data,0.7)
15 by 3 dataset with 3 classes: [6  5  4]
5 by 3 dataset with 3 classes: [2  2  1]
}}}
!!Accessing dataset labels
Important concept is a dataset lablist (label list) which is a ordered list of class names used to convert between the internally stored numerical references and class names. Internally ~PRTools dataset stores numerical labels, not the string labels.
{{{
>> getlablist(ts)
ans =
apple 
banana
orange
>> getlab(ts)
ans =
apple 
apple 
banana
banana
orange
>> getnlab(ts)
ans =
     1
     1
     2
     2
     3
>> getclassi(ts,'banana')
ans =
     2
}}}
!!Mappings
~PRTools mappings are fixed or trained procedures processing the dataset objects. We can, for example, train a Principal Component Analysis (PCA) mapping to reduce the dimensionality of input data from 3 to 2D:
{{{
>> w=pca(tr,2)
PCA to 2D, 3 to 2 trained  mapping   --> affine
}}}
The object {{{w}}} is now trained i.e. contains all the parameters needed for projecting new data. Mapping objects may be executed on data using the multiplication operator:
{{{
>> out1=tr*w
15 by 2 dataset with 3 classes: [6  5  4]
}}}
The output is the dataset object {{{out1}}} containing all the 15 samples in {{{tr}}} projected into 2D subspace. Note that sample labels and other meta-data stored in {{{tr}}} are preserved.

We can train a nearest mean classifier in the resulting 2D subspace:
{{{
>> w2=nmc(out1)
Nearest Mean, 2 to 3 trained  mapping   --> normal_map
}}}
And project the test data by both the PCA feature extractor and the classifier in one step:
{{{
>> out2=ts*w*w2
5 by 3 dataset with 3 classes: [2  2  1]
}}}
The result of executing a trained classifier on the data is a dataset with ''soft outputs'' for each of the three classes:
{{{
>> getfeatlab(out2_ts)
ans =
apple 
banana
orange
>> +out2_ts
ans =
    0.1001    0.2282    0.0813
    0.4755    0.3773    0.3030
    0.4969    0.3249    0.3068
    0.3094    0.1676    0.1404
    0.2577    0.1712    0.1154
}}}
By convention the classifier outputs in ~PRTools are similarities (the higher, the more similar to a given class).
In order to convert the soft outputs into crisp decisions, we take a weighted maximum. By default the equal class weights are used:
{{{
>> out2_ts*labeld
ans =
banana
apple 
apple 
apple 
apple 
}}}

For further information, consult ~PRTools manual.
/***
|<html><a name="Top"/></html>''Name:''|PartTiddlerPlugin|
|''Version:''|1.0.9 (2007-07-14)|
|''Source:''|http://tiddlywiki.abego-software.de/#PartTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license]]|
|''CoreVersion:''|2.1.3|
|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|
!Table of Content<html><a name="TOC"/></html>
* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Description',null, event)">Description, Syntax</a></html>
* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Applications',null, event)">Applications</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('LongTiddler',null, event)">Refering to Paragraphs of a Longer Tiddler</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Citation',null, event)">Citation Index</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('TableCells',null, event)">Creating "multi-line" Table Cells</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Tabs',null, event)">Creating Tabs</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Sliders',null, event)">Using Sliders</a></html>
* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Revisions',null, event)">Revision History</a></html>
* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Code',null, event)">Code</a></html>
!Description<html><a name="Description"/></html>
With the {{{<part aPartName> ... </part>}}} feature you can structure your tiddler text into separate (named) parts. 
Each part can be referenced as a "normal" tiddler, using the "//tiddlerName//''/''//partName//" syntax (e.g. "About/Features").  E.g. you may create links to the parts (e.g. {{{[[Quotes/BAX95]]}}} or {{{[[Hobbies|AboutMe/Hobbies]]}}}), use it in {{{<<tiddler...>>}}} or {{{<<tabs...>>}}} macros etc.


''Syntax:'' 
|>|''<part'' //partName// [''hidden''] ''>'' //any tiddler content// ''</part>''|
|//partName//|The name of the part. You may reference a part tiddler with the combined tiddler name "//nameOfContainerTidder//''/''//partName//. <<br>>If you use a partName containing spaces you need to quote it (e.g. {{{"Major Overview"}}} or {{{[[Shortcut List]]}}}).|
|''hidden''|When defined the content of the part is not displayed in the container tiddler. But when the part is explicitly referenced (e.g. in a {{{<<tiddler...>>}}} macro or in a link) the part's content is displayed.|
|<html><i>any&nbsp;tiddler&nbsp;content</i></html>|<html>The content of the part.<br>A part can have any content that a "normal" tiddler may have, e.g. you may use all the formattings and macros defined.</html>|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|
<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!Applications<html><a name="Applications"/></html>
!!Refering to Paragraphs of a Longer Tiddler<html><a name="LongTiddler"/></html>
Assume you have written a long description in a tiddler and now you want to refer to the content of a certain paragraph in that tiddler (e.g. some definition.) Just wrap the text with a ''part'' block, give it a nice name, create a "pretty link" (like {{{[[Discussion Groups|Introduction/DiscussionGroups]]}}}) and you are done.

Notice this complements the approach to first writing a lot of small tiddlers and combine these tiddlers to one larger tiddler in a second step (e.g. using the {{{<<tiddler...>>}}} macro). Using the ''part'' feature you can first write a "classic" (longer) text that can be read "from top to bottom" and later "reuse" parts of this text for some more "non-linear" reading.

<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!!Citation Index<html><a name="Citation"/></html>
Create a tiddler "Citations" that contains your "citations". 
Wrap every citation with a part and a proper name. 

''Example''
{{{
<part BAX98>Baxter, Ira D. et al: //Clone Detection Using Abstract Syntax Trees.// 
in //Proc. ICSM//, 1998.</part>

<part BEL02>Bellon, Stefan: //Vergleich von Techniken zur Erkennung duplizierten Quellcodes.// 
Thesis, Uni Stuttgart, 2002.</part>

<part DUC99>Ducasse, Stéfane et al: //A Language Independent Approach for Detecting Duplicated Code.// 
in //Proc. ICSM//, 1999.</part>
}}}

You may now "cite" them just by using a pretty link like {{{[[Citations/BAX98]]}}} or even more pretty, like this {{{[[BAX98|Citations/BAX98]]}}}.

<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!!Creating "multi-line" Table Cells<html><a name="TableCells"/></html>
You may have noticed that it is hard to create table cells with "multi-line" content. E.g. if you want to create a bullet list inside a table cell you cannot just write the bullet list
{{{
* Item 1
* Item 2
* Item 3
}}}
into a table cell (i.e. between the | ... | bars) because every bullet item must start in a new line but all cells of a table row must be in one line.

Using the ''part'' feature this problem can be solved. Just create a hidden part that contains the cells content and use a {{{<<tiddler >>}}} macro to include its content in the table's cell.

''Example''
{{{
|!Subject|!Items|
|subject1|<<tiddler ./Cell1>>|
|subject2|<<tiddler ./Cell2>>|

<part Cell1 hidden>
* Item 1
* Item 2
* Item 3
</part>
...
}}}

Notice that inside the {{{<<tiddler ...>>}}} macro you may refer to the "current tiddler" using the ".".

BTW: The same approach can be used to create bullet lists with items that contain more than one line.

<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!!Creating Tabs<html><a name="Tabs"/></html>
The build-in {{{<<tabs ...>>}}} macro requires that you defined an additional tiddler for every tab it displays. When you want to have "nested" tabs you need to define a tiddler for the "main tab" and one for every tab it contains. I.e. the definition of a set of tabs that is visually displayed at one place is distributed across multiple tiddlers.

With the ''part'' feature you can put the complete definition in one tiddler, making it easier to keep an overview and maintain the tab sets.

''Example''
The standard tabs at the sidebar are defined by the following eight tiddlers:
* SideBarTabs
* TabAll
* TabMore
* TabMoreMissing
* TabMoreOrphans
* TabMoreShadowed
* TabTags
* TabTimeline

Instead of these eight tiddlers one could define the following SideBarTabs tiddler that uses the ''part'' feature:
{{{
<<tabs txtMainTab 
    Timeline Timeline SideBarTabs/Timeline 
    All 'All tiddlers' SideBarTabs/All 
    Tags 'All tags' SideBarTabs/Tags 
    More 'More lists' SideBarTabs/More>>
<part Timeline hidden><<timeline>></part>
<part All hidden><<list all>></part>
<part Tags hidden><<allTags>></part>
<part More hidden><<tabs txtMoreTab 
    Missing 'Missing tiddlers' SideBarTabs/Missing 
    Orphans 'Orphaned tiddlers' SideBarTabs/Orphans 
    Shadowed 'Shadowed tiddlers' SideBarTabs/Shadowed>></part>
<part Missing hidden><<list missing>></part>
<part Orphans hidden><<list orphans>></part>
<part Shadowed hidden><<list shadowed>></part>
}}}

Notice that you can easily "overwrite" individual parts in separate tiddlers that have the full name of the part.

E.g. if you don't like the classic timeline tab but only want to see the 100 most recent tiddlers you could create a tiddler "~SideBarTabs/Timeline" with the following content:
{{{
<<forEachTiddler 
		sortBy 'tiddler.modified' descending 
		write '(index < 100) ? "* [["+tiddler.title+"]]\n":""'>>
}}}
<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!!Using Sliders<html><a name="Sliders"/></html>
Very similar to the build-in {{{<<tabs ...>>}}} macro (see above) the {{{<<slider ...>>}}} macro requires that you defined an additional tiddler that holds the content "to be slid". You can avoid creating this extra tiddler by using the ''part'' feature

''Example''
In a tiddler "About" we may use the slider to show some details that are documented in the tiddler's "Details" part.
{{{
...
<<slider chkAboutDetails About/Details details "Click here to see more details">>
<part Details hidden>
To give you a better overview ...
</part>
...
}}}

Notice that putting the content of the slider into the slider's tiddler also has an extra benefit: When you decide you need to edit the content of the slider you can just doubleclick the content, the tiddler opens for editing and you can directly start editing the content (in the part section). In the "old" approach you would doubleclick the tiddler, see that the slider is using tiddler X, have to look for the tiddler X and can finally open it for editing. So using the ''part'' approach results in a much short workflow.

<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!Revision history<html><a name="Revisions"/></html>
* v1.0.9 (2007-07-14)
** Bugfix: Error when using the SideBarTabs example and switching between "More" and "Shadow". Thanks to cmari for reporting the issue.
* v1.0.8 (2007-06-16)
** Speeding up display of tiddlers containing multiple pard definitions. Thanks to Paco Rivière for reporting the issue.
** Support "./partName" syntax inside <<tabs ...>> macro
* v1.0.7 (2007-03-07)
** Bugfix: <<tiddler "./partName">> does not always render correctly after a refresh (e.g. like it happens when using the "Include" plugin). Thanks to Morris Gray for reporting the bug.
* v1.0.6 (2006-11-07)
** Bugfix: cannot edit tiddler when UploadPlugin by Bidix is installed. Thanks to José Luis González Castro for reporting the bug.
* v1.0.5 (2006-03-02)
** Bugfix: Example with multi-line table cells does not work in IE6. Thanks to Paulo Soares for reporting the bug.
* v1.0.4 (2006-02-28)
** Bugfix: Shadow tiddlers cannot be edited (in TW 2.0.6). Thanks to Torsten Vanek for reporting the bug.
* v1.0.3 (2006-02-26)
** Adapt code to newly introduced Tiddler.prototype.isReadOnly() function (in TW 2.0.6). Thanks to Paulo Soares for reporting the problem.
* v1.0.2 (2006-02-05)
** Also allow other macros than the "tiddler" macro use the "." in the part reference (to refer to "this" tiddler)
* v1.0.1 (2006-01-27)
** Added Table of Content for plugin documentation. Thanks to RichCarrillo for suggesting.
** Bugfix: newReminder plugin does not work when PartTiddler is installed. Thanks to PauloSoares for reporting.
* v1.0.0 (2006-01-25)
** initial version
<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!Code<html><a name="Code"/></html>
<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>
***/
//{{{
//============================================================================
//                           PartTiddlerPlugin

// Ensure that the PartTiddler Plugin is only installed once.
//
if (!version.extensions.PartTiddlerPlugin) {



version.extensions.PartTiddlerPlugin = {
    major: 1, minor: 0, revision: 9,
    date: new Date(2007, 6, 14), 
    type: 'plugin',
    source: "http://tiddlywiki.abego-software.de/#PartTiddlerPlugin"
};

if (!window.abego) window.abego = {};
if (version.major < 2) alertAndThrow("PartTiddlerPlugin requires TiddlyWiki 2.0 or newer.");

//============================================================================
// Common Helpers

// Looks for the next newline, starting at the index-th char of text. 
//
// If there are only whitespaces between index and the newline 
// the index behind the newline is returned, 
// otherwise (or when no newline is found) index is returned.
//
var skipEmptyEndOfLine = function(text, index) {
	var re = /(\n|[^\s])/g;
	re.lastIndex = index;
	var result = re.exec(text);
	return (result && text.charAt(result.index) == '\n') 
			? result.index+1
			: index;
}


//============================================================================
// Constants

var partEndOrStartTagRE = /(<\/part>)|(<part(?:\s+)((?:[^>])+)>)/mg;
var partEndTagREString = "<\\/part>";
var partEndTagString = "</part>";

//============================================================================
// Plugin Specific Helpers

// Parse the parameters inside a <part ...> tag and return the result.
//