Persistence 1D inc. Reconstruct1D  1.1
Finding extrema in one dimensional data, filtering them by persistence and reconstructing smooth functions
 All Classes Namespaces Files Functions Variables Macros Pages
run_persistence1d.cpp
Go to the documentation of this file.
1 /*! \file run_persistence1d.cpp
2 
3 * Main Matlab-C++ Interface file.
4 *
5 * Compile with MEX to use as MATLAB interface for Persistence1D class.
6 * Tested on 32-bits only, MATLAB 2011b and above.
7 *
8 * Usage: [MinIndices MaxIndices Persistence GlobalMinIdx GlobalMinVal] = run_persistence1d(single(data))
9 *
10 * Supports input in single format. Output is INT32 and SINGLE.
11 *
12 * To see output messages in Matlab, uncomment line 38 before compilation.
13 *
14 * @param[in] data A vector of data, sorted according to coordinates.
15 * This should contain only data values to be sorted.
16 * Assumes the data is one dimensional.
17 *
18 * @param[out] MinIndices Vector of (Matlab compatible) indices of local maxima.
19 * @param[out] MaxIndices Vector of (Matlab compatible) indices of local minima.
20 * @param[out] Persistence Vector of persistence of the paired extrema whose indices live in
21 * MinIndices and MaxIndices
22 * @param[out] GlobalMinIdx Index (Matlab compatible) of global minimum.
23 * @param[out] GlobalMinVal Value of global minimum.
24 *
25 ************************************************/
26 
27 #include <matrix.h>
28 #include <mex.h>
29 #include <algorithm>
30 #include <vector>
31 #include "..\src\persistence1d\persistence1d.hpp"
32 
33 #define NUM_INPUT_VARIABLES 1
34 #define NUM_OUTPUT_VARIABLES 5
35 #define MATLAB_INDEXING true
36 #define NO_FILTERING 0.0
37 
38 //uncomment the next line to see debug output in Matlab
39 //#define _DEBUG
40 
41 using namespace p1d;
42 using namespace std;
43 
44 bool MxFloatArrayToFloatVector(const mxArray * input, std::vector<float> & data);
45 mxArray * VectorToMxSingleArray(const std::vector<float> data);
46 mxArray * VectorToMxSingleArray(const std::vector<int> data);
47 mxArray * VectorToMxSingleArray(const std::vector<TPairedExtrema> data);
48 mxArray * ScalarToMxSingleArray(const float data);
49 mxArray * ScalarToMxSingleArray(const int data);
50 
51 bool CheckInput(const int nOuts, mxArray *outs[], const int nIns, const mxArray *ins[]);
52 void WriteVectorToMexOutput(const std::vector<float> data);
53 void WriteInputToVector(const mxArray *prhs[], std::vector<float> & data);
54 
55 /*!
56  Main MATLAB interface
57 
58  @param[in,out] nlhs Number of left hand (output) matrices.
59  @param[in,out] plhs Pointers to left hand (output) matrices.
60  @param[in] nrhs Number of right hand (input) matrices.
61  @param[in] prhs Pointers to right hand (input) matrices.
62 */
63 void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
64 {
65  //persistence and data variables
66  Persistence1D p;
67  std::vector<float> data;
68 
69  //Variables to store persistence results
70  std::vector<int> minIndices;
71  std::vector<int> maxIndices;
72  std::vector<TPairedExtrema> pairs;
73  float gminValue;
74  int gminIndex;
75 
76  //Assumption: Vector data lives in phrs[0]
77  //Any deviation from this is not tolerated.
78 
79  //prhs - right hand - input - MATLAB standard naming convention
80  //plhs - left hand - output
81  if (!CheckInput(nlhs, plhs, nrhs, prhs)) return;
82 
83 #ifdef _DEBUG
84  mexPrintf("Copying input data...\n");
85 #endif
86  WriteInputToVector(prhs, data);
87 
88 #ifdef _DEBUG
90 #endif
91 
92 #ifdef _DEBUG
93  mexPrintf("Running Persistence1D...\n");
94 #endif
95  p.RunPersistence(data);
96 
97 #ifdef _DEBUG
98  mexPrintf("Done.\n");
99  mexPrintf("Getting results...\n");
100 #endif
101 
103  gminIndex = p.GetGlobalMinimumIndex(MATLAB_INDEXING);
104  gminValue = p.GetGlobalMinimumValue();
105  p.GetExtremaIndices(minIndices, maxIndices, NO_FILTERING, MATLAB_INDEXING);
106 
107 #ifdef _DEBUG
108  mexPrintf("Done.\n");
109  mexPrintf("Writing results to MATLAB...\n");
110 #endif
111 
112  plhs[0] = VectorToMxSingleArray(minIndices);
113  plhs[1] = VectorToMxSingleArray(maxIndices);
114  plhs[2] = VectorToMxSingleArray(pairs);
115  plhs[3] = ScalarToMxSingleArray(gminIndex);
116  plhs[4] = ScalarToMxSingleArray(gminValue);
117 
118 #ifdef _DEBUG
119  mexPrintf("Done.\n");
120 #endif
121  return;
122 }
123 
124 /*!
125  Fills a given float data vector with values from float mxArray.
126  Warning - does not check if mxArray format is single.
127 */
128 bool MxFloatArrayToFloatVector(const mxArray * input, std::vector<float> & data)
129 {
130  if (mxGetClassID(input) != mxSINGLE_CLASS)
131  {
132  mexPrintf ("Error. Expecting SINGLE value matrix");
133  return false;
134  }
135 
136  mwSize numElements = mxGetNumberOfElements(input);
137  float *inputPt;
138  inputPt = (float *)mxGetData(input);
139 
140  data.reserve(numElements);
141 
142  for (int i = 0; i < numElements; i++)
143  {
144  data.push_back((float)*inputPt++);
145  }
146 
147  return true;
148 }
149 /*!
150  Creates a 1x1 Single Type Matlab matrix from a single float value.
151 */
152 mxArray * ScalarToMxSingleArray(const float data)
153 {
154  mxArray * out = mxCreateNumericMatrix(1, 1, mxSINGLE_CLASS, mxREAL);
155  float * mPt = (float *)mxGetData(out);
156 
157  *mPt++ = data;
158  return out;
159 }
160 mxArray * ScalarToMxSingleArray(const int data)
161 {
162  return ScalarToMxSingleArray((float)data);
163 }
164 
165 /*!
166  Copies vector<float> data to 1-d MATLAB matrix
167 
168  @param[in] data A vector of float to copy.
169 */
170 mxArray * VectorToMxSingleArray(const std::vector<float> data)
171 {
172  mxArray * out = mxCreateNumericMatrix(data.size(), 1, mxSINGLE_CLASS, mxREAL);
173  float * mPt = (float *)mxGetData(out);
174 
175  for (std::vector<float>::const_iterator pt = data.begin();
176  pt != data.end(); pt++)
177  {
178  *mPt++ = *pt;
179  }
180 
181  return out;
182 }
183 
184 /*!
185  Copies vector<int> data to 1-d Single-type MATLAB matrix
186  @param[in] data data to be copied to Matlab.
187 */
188 mxArray * VectorToMxSingleArray(const std::vector<int> data)
189 {
190  mxArray * out = mxCreateNumericMatrix(data.size(), 1, mxSINGLE_CLASS, mxREAL);
191  float * mPt = (float *)mxGetData(out);
192 
193  for (std::vector<int>::const_iterator pt = data.begin();
194  pt != data.end(); pt++)
195  {
196  *mPt++ = (float)*pt;
197  }
198 
199  return out;
200 }
201 /*!
202  Creates a 1-d Single-Type MATLAB matrix with the persistence values from a vector of TPairedExtrema.
203  @param[in] data Vector of paired extrema
204 */
205 mxArray * VectorToMxSingleArray(const std::vector<TPairedExtrema> data)
206 {
207  mxArray * out = mxCreateNumericMatrix(data.size(), 1, mxSINGLE_CLASS, mxREAL);
208  float * mPt = (float *)mxGetData(out);
209 
210  for (std::vector<TPairedExtrema>::const_iterator pt = data.begin();
211  pt != data.end(); pt++)
212  {
213  *mPt++ = (*pt).Persistence;
214  }
215  return out;
216 }
217 /*!
218  Validates the following for the input:
219  - Total number of arguments = 1
220  - The only arguments should be data, in a 1-d matrix
221  - Matrix data type is single (AKA float)
222  - No complex data
223  - No char data
224 
225  Validates the following for the output:
226  - There are three output variables
227 
228  @param[in] nOuts Number of output variables.
229  @param[in] outs Array of pointers to output matrices.
230  @param[in] nIns Number of input variables.
231  @param[in] ins Array of pointers in input matrices.
232 */
233 bool CheckInput(const int nOuts, mxArray *outs[], const int nIns, const mxArray *ins[])
234 {
235  bool noerror = true;
236 
237  if (nIns != NUM_INPUT_VARIABLES)
238  {
239  mexPrintf("\nExpecting one input variables: data vector.");
240  noerror = false;
241  }
242  if (nOuts != NUM_OUTPUT_VARIABLES)
243  {
244  mexPrintf("\nExpecting five output variables: MinIndices MaxIndices Persistence GlobalMinIdx GlobalMinVal\n");
245  noerror = false;
246  }
247  if (!mxIsNumeric(ins[0]) || mxIsComplex(ins[0]) || !mxIsSingle(ins[0]))
248  {
249  mexPrintf ("\nExpecting the data vector to be REAL, SINGLE, matrix");
250  noerror = false;
251  }
252 
253  mwSize dims = mxGetNumberOfDimensions(ins[0]);
254  if (dims > 2)
255  {
256  mexPrintf("\nWarning. %d number of dimensions not supported, will handle data as one dimensional data", dims);
257  }
258 
259  size_t mrows,ncols;
260  mrows = mxGetM(ins[0]);
261  ncols = mxGetN(ins[0]);
262 
263  if (mrows!=1 && ncols!=1) //Input data should be 1-d vector shaped - results are not guaranteed for 2d data
264  {
265  mexPrintf("\nInput rows: %d cols: %d", mrows, ncols);
266  mexPrintf("\nWarning. Expecting one dimensional vector data. Data vector contains: %d %d", mrows, ncols);
267  }
268 
269  return noerror;
270 }
271 /*!
272  Displays float-vector content in Matlab output window.
273 
274  @param[in] data Float vector to write
275 */
276 void WriteVectorToMexOutput(const std::vector<float> data)
277 {
278  for (std::vector<float>::const_iterator it = data.begin();
279  it != data.end(); it++)
280  {
281  mexPrintf("\n data[%d] %f",it-data.begin(),*it);
282  }
283  mexPrintf("\n");
284 }
285 /*!
286  Assumption - first input argument is a vector of 1-d data,
287 
288  Copies the content of mxArray to a vector.
289 
290  @param[in] inputs Array of MATLAB matrix data, as received by mexFunction (MATLAB entrance point)
291  @param[out] data Vector which contain data for Persistence
292 */
293 void WriteInputToVector(const mxArray *inputs[], std::vector<float> & data)
294 {
295  MxFloatArrayToFloatVector(inputs[0], data);
296 }