Filter Library Camera Interface Physics

ScanFilterLinearRegression.cpp

00001 /*
00002  * ScanFilterLinearRegression.cpp - determine linear regression parameters of image.
00003  *
00004  * This file is part of the Camera Filter Library.
00005  * Computer Aided Measurement Environment for Realtime Atomic imaging (Camera)
00006  *
00007  * Copyright (C) 2004-2005, Leiden Probe Microscopy.
00008  * Copyright (C) 2004-2005, Universiteit Leiden.
00009  *
00010  * Authors: Martin J. Moene (original)
00011  *
00012  * $Id: ScanFilterLinearRegression.cpp 339 2006-02-27 12:02:15Z moene $
00013  */
00014 
00015 /*
00016  * configuration defines:
00017  */
00018 
00019 //#define NO_FILTER_SETTINGS            // if Get/WriteFilterSettings() is not supported
00020 //#define NO_RETRACE_LINE               // if the buffers do not contain a retrace line (nacra)
00021 
00022 /*
00023  * end of configuration defines.
00024  */
00025 
00026 /**
00027  * \todo: can do partial data?
00028  */
00029 
00030 /**
00031  * \todo change "stdafx.h" to <cfl/stdafx.h> when all filters have been adapted.
00032  * "stdafx.h" is used to determine the contents of the precompiled headers;
00033  * see prj settings C/C++, precompiled headers, through header "stdafx.h")
00034  */
00035 
00036 #include "stdafx.h"                     // for common (pre-compiled) headers
00037 //#include <cfl/stdafx.h>                 // for common (pre-compiled) headers
00038 #include <cfl/resource.h>               // for messages and other resources
00039 
00040 #include <Camera/InterfaceDll.h>        // Camera--Filter Library interface
00041 
00042 #include <cfl/ScanFilterLinearRegression.h> // this filter's header
00043 #include <cfl/FilterDlg_LinearRegression.h> // this filter's dialog
00044 
00045 #pragma warning( push, 3 )              // header file limits requires warning level 3
00046 
00047 #include <limits>                       // for std::numeric_limits<>
00048 
00049 #pragma warning( pop )
00050 
00051 #ifdef _DEBUG
00052 #undef THIS_FILE
00053 static char THIS_FILE[]=__FILE__;
00054 #define new DEBUG_NEW
00055 #endif
00056 
00057 #define CFL_SCHEMAVERSION_FILTERLINEARREGRESSION 0  ///< permanent storage schema version
00058 
00059                                         // this filter's name
00060 LPCTSTR CScanFilterLinearRegression::m_lpcsFilterName = _T( "Linear-Regression" );
00061                                         // this filter's short name
00062 LPCTSTR CScanFilterLinearRegression::m_lpcsShortFilterName = _T( "LinReg" );
00063                                         // serialization
00064 IMPLEMENT_SERIAL( CScanFilterLinearRegression, CScanFilter, CFL_SCHEMAVERSION_FILTERLINEARREGRESSION )
00065 
00066 /*
00067  * default parameter values: 9x9.
00068  */
00069 const int CScanFilterLinearRegression::def_iXY  = 9;
00070 
00071 /*
00072  * default A, B, Alpha, Beta multiplication factor.
00073  */
00074 const double CScanFilterLinearRegression::def_dFactor = 100;
00075 
00076 /*
00077  * default selection of A, B, Alpha, etc.
00078  */
00079 const LinearRegressionImageFilter::FeatureSelector CScanFilterLinearRegression::def_eParameter = LinearRegressionImageFilter::AlphaPi;
00080 
00081 /*
00082  * default constructor: initialize filter with last used settings;
00083  * see also CScanFilterNull::CScanFilterLinearNull().
00084  */
00085 CScanFilterLinearRegression::CScanFilterLinearRegression() : CScanFilter( ),
00086    m_iSizeX    ( def_iXY ),
00087    m_iSizeY    ( def_iXY ),
00088    m_dFactor   ( def_dFactor ),
00089    m_eParameter( def_eParameter )
00090 {
00091    m_csFilterName = m_lpcsFilterName;
00092 
00093    ReadFilterSettings();                 // get filter settings to run without dialog
00094 }
00095 
00096 /*
00097  * destructor; current filter settings are saved via WriteFilterSettings()
00098  * when user pressed OK-button, see CFilterDlg::OnOK().
00099  */
00100 CScanFilterLinearRegression::~CScanFilterLinearRegression()
00101 {
00102    ; // do nothing here
00103 }
00104 
00105 /*
00106  * store or retrieve the object's settings;
00107  * currently filter serialization is not used;
00108  * see also CScanFilterNull::Serialize().
00109  */
00110 void CScanFilterLinearRegression::Serialize( CArchive& ar )
00111 {
00112 //   Q_LOG( _T("CScanFilterLinearRegression::Serialize") );
00113 
00114    CScanFilter::Serialize( ar );
00115 
00116    if ( ar.IsStoring() )
00117    {
00118       ar << m_iSizeX << m_iSizeY << static_cast<int>( m_eParameter ) << m_dFactor;
00119    }
00120    else
00121    {
00122       int iParameter;
00123       ar >> m_iSizeX >> m_iSizeY >> iParameter >> m_dFactor;
00124       m_eParameter = static_cast<FeatureSelector>( iParameter );
00125    }
00126 }
00127 
00128 #if 0
00129 /*
00130  * true if filter can process a data-selection in the buffer.
00131  */
00132 BOOL CScanFilterLinearRegression::CanDoPartialData() const
00133 {
00134    return TRUE;
00135 }
00136 #endif
00137 
00138 #if 0
00139 /*
00140  * true if a dialog can be used.
00141  */
00142 BOOL CScanFilterLinearRegression::CanDoDialogEntry() const
00143 {
00144    return FALSE;
00145 }
00146 #endif
00147 
00148 /*
00149  * \brief configure filter with settings as provided by the application on the
00150  * filterlist window (e.g. via registry); see also CScanFilterNull::ReadFilterSettings().
00151  */
00152 void CScanFilterLinearRegression::ReadFilterSettings( )
00153 {
00154 //   Q_LOG( _T("CScanFilterLinearRegression::ReadFilterSettings()") );
00155 
00156 #ifdef NO_FILTER_SETTINGS
00157    /*
00158     * Only few filters provide this method.
00159     */
00160 #else
00161    CWinApp* pApp = AfxGetApp();
00162 
00163    if ( Q_INVALID( NULL == pApp ) )
00164       return ;
00165 
00166    /*
00167     * parameter string: x-size,y-size,parameter,factor
00168     */
00169    SetParameters( pApp->GetProfileString( gCflRegistrySubkey, m_lpcsFilterName, _T( "5,5,1,100" ) ) );
00170 #endif
00171 }
00172 
00173 /*
00174  * \brief save filter settings e.g. for use with the filterlist window (e.g. via registry);
00175  * see also ReadFilterSettings().
00176  */
00177 void CScanFilterLinearRegression::WriteFilterSettings() const
00178 {
00179 #ifdef NO_FILTER_SETTINGS
00180    /*
00181     * do nothing.
00182     */
00183 #else
00184    CWinApp* pApp = AfxGetApp();
00185 
00186    if ( Q_INVALID( NULL == pApp ) )
00187       return ;
00188 
00189    /*
00190     * parameter string: x-size,y-size,parameter,factor
00191     */
00192    LPCTSTR pStr = GetParameters();
00193 
00194    if ( pStr )
00195    {
00196       pApp->WriteProfileString( gCflRegistrySubkey, m_lpcsFilterName, pStr );
00197       delete const_cast<LPTSTR>( pStr );
00198    }
00199 #endif
00200 }
00201 
00202 /*
00203  * provide current filter parameter(s) for filter-scripting capture
00204  * in the main application;
00205  * see also CScanFilterNull::GetParameters().
00206  */
00207 LPCTSTR CScanFilterLinearRegression::GetParameters( ) const
00208 {
00209 //   Q_LOG( _T("CScanFilterLinearRegression::GetParameters()") );
00210 
00211    /*
00212     * format parameters and return a c-string on the heap:
00213     */
00214    CString csParameters;
00215 
00216    csParameters.Format( _T( "%d,%d,%d,%g,%g" ),
00217       m_iSizeX, m_iSizeY, m_eParameter, m_dTheta, m_dFactor );
00218 
00219    return strcpy( new TCHAR[ csParameters.GetLength() + 1 ], csParameters );
00220 }
00221 
00222 /*
00223  * set parameters for filter-script execution of filter;
00224  * see also CScanFilterNull::SetParameters().
00225  */
00226 BOOL CScanFilterLinearRegression::SetParameters( LPCTSTR lpParameters )
00227 {
00228 //   Q_LOG( _T("CScanFilterLinearRegression::SetParameters()") );
00229 
00230    if ( Q_INVALID( NULL == lpParameters ) &&
00231            "CScanFilterLinearRegression (SetParameters): parameters expected, none provided (NULL).")
00232    {
00233       return FALSE;
00234    }
00235 
00236    /*
00237     * set defaults, read parameter string with factor and optional offset:
00238     */
00239    m_iSizeX     = def_iXY;
00240    m_iSizeY     = def_iXY;
00241    m_dFactor    = def_dFactor;
00242    m_eParameter = def_eParameter;
00243 
00244    int nfields = _stscanf( lpParameters, _T( "%d,%d,%d,%lg,%lg" ),
00245       &m_iSizeX, &m_iSizeY, &m_eParameter, &m_dTheta, &m_dFactor );
00246 
00247    if ( Q_INVALID( 4 > nfields &&
00248       "CScanFilterLinearRegression (SetParameters): X- and Y-size, parameter and factor expected, got fewer." ) )
00249    {
00250       return FALSE;
00251    }
00252 
00253    return TRUE;
00254 }
00255 
00256 /*
00257  * create filter dialog and pre Apply() filter to view result;
00258  * see also CScanFilterNull::RunModeless().
00259  */
00260 BOOL CScanFilterLinearRegression::RunModeless( CWnd* pParentWnd, CDocument* pDoc )
00261 {
00262 //   Q_LOG( _T("CScanFilterLinearRegression::RunModeless()") );
00263 
00264    CFilterDlg_LinearRegressionPtr pDlg = new CFilterDlg_LinearRegression();
00265 
00266    if ( Q_INVALID( NULL == pDlg ) )
00267       return FALSE;
00268 
00269    pDlg->SetParameters( this, pDoc );   // (void) method
00270 
00271    /*
00272     * For the dialog panel, I had to replace several lines in resource.h with
00273     * lines from a previously created dialog to make the dialog visible.
00274     *
00275     * Create returns non-zero if dialog was created and initialized succesfully.
00276     * Note: no pDlg->DestroyWindow() must be done.
00277     */
00278    pDlg->Create( IDD_FILTERDLG_LINEARREGRESSION, pParentWnd );
00279 
00280    m_pDlg = pDlg;
00281 
00282    /*
00283     * pre-Apply the filter and show initial results;
00284     * on error, simulate failure to create dialog:
00285     */
00286    BOOL bRet = PreApply();
00287 
00288    if ( bRet )
00289    {
00290       pDlg->UpdateView();
00291    }
00292 
00293    return bRet;
00294 }
00295 
00296 /*
00297  * let PreApplyCore() perform the filter pre-processing; catch MFC and std exceptions;
00298  * see also CScanFilterNull::Apply().
00299  */
00300 BOOL CScanFilterLinearRegression::PreApply()
00301 {
00302 //   Q_LOG( _T("CScanFilterLinearRegression::Apply()") );
00303 
00304    BOOL bRet = FALSE;                   // preset to Failure
00305 
00306    try
00307    {
00308       bRet = PreApplyCore();            // sets status, unless exception occurs
00309    }
00310    catch ( CException* e )
00311    {
00312       Q_MFC_EXCEPTION( e );             // macro uses pointer-to (without surrounding () )
00313       e->Delete();                      // see MSDN: Exceptions: Catching and Deleting Exceptions
00314    }
00315    catch ( const std::exception& e )
00316    {
00317       Q_STD_EXCEPTION( e );
00318    }
00319 
00320    return bRet;                         // return status
00321 }
00322 
00323 /*
00324  * let ApplyCore() perform the filter processing; catch MFC and std exceptions;
00325  * see also CScanFilterNull::Apply().
00326  */
00327 BOOL CScanFilterLinearRegression::Apply()
00328 {
00329 //   Q_LOG( _T("CScanFilterLinearRegression::Apply()") );
00330 
00331    BOOL bRet = FALSE;                   // preset to Failure
00332 
00333    try
00334    {
00335       bRet = ApplyCore();               // sets status, unless exception occurs
00336    }
00337    catch ( CException* e )
00338    {
00339       Q_MFC_EXCEPTION( e );             // macro uses pointer-to (without surrounding () )
00340       e->Delete();                      // see MSDN: Exceptions: Catching and Deleting Exceptions
00341    }
00342    catch ( const std::exception& e )
00343    {
00344       Q_STD_EXCEPTION( e );
00345 #if 0
00346       if ( m_pDlg )
00347 //      if ( IsInteractive() )          // FIXME: when member of CScanFilter.
00348       {
00349          ::MessageBox(
00350             AfxGetMainWnd()->m_hWnd, e.what(), _T("Linear Regression Filter Failure"), MB_OK | MB_ICONWARNING );
00351       }
00352 #endif
00353    }
00354 
00355    return bRet;                         // return status
00356 }
00357 
00358 /*
00359  * the selected parameter name.
00360  */
00361 CharCptr CScanFilterLinearRegression::ParamName()
00362 {
00363    switch( Parameter() )
00364    {
00365       case  LinearRegressionImageFilter::A: return "A";
00366       case  LinearRegressionImageFilter::B: return "B";
00367       case  LinearRegressionImageFilter::C: return "C";
00368       case  LinearRegressionImageFilter::AlphaPi: return "Alpha[Pi]";
00369       case  LinearRegressionImageFilter::AlphaDeg: return "Alpha[deg]";
00370       case  LinearRegressionImageFilter::BetaPi: return "Beta[Pi]";
00371       case  LinearRegressionImageFilter::BetaDeg: return "Beta[deg]";
00372       case  LinearRegressionImageFilter::AngleLength: return "Length";
00373       case  LinearRegressionImageFilter::AngleLengthNeg: return "Length (Neg)";
00374       case  LinearRegressionImageFilter::AngleLengthPi: return "Length[Pi]";
00375       case  LinearRegressionImageFilter::AngleLengthPiNeg: return "Length[Pi] (Neg)";
00376       case  LinearRegressionImageFilter::AngleLengthDeg: return "Length[deg]";
00377       case  LinearRegressionImageFilter::AngleLengthDegNeg: return "Length[deg] (Neg)";
00378       case  LinearRegressionImageFilter::AngleSum: return "Sum";
00379       case  LinearRegressionImageFilter::AngleSumPi: return "Sum[Pi]";
00380       case  LinearRegressionImageFilter::AngleSumDeg: return "Sum[deg]";
00381       default: return "[unrcognized]";
00382    }
00383 }
00384 
00385 /*
00386  * check parameters, take care of a properly sized output buffer,
00387  * set its name and copy filter parameters;
00388  * see also CScanFilterNull::ApplyCore().
00389  */
00390 BOOL CScanFilterLinearRegression::PreApplyCore()
00391 {
00392    if ( Q_INVALID( NULL == m_lpsbIn ) && "ensure valid input buffer" )
00393       return FALSE;
00394 
00395    if ( Q_INVALID( NULL == m_lpsbOut ) && "ensure valid output buffer"  )
00396       return FALSE;
00397 
00398    /*
00399     * setup filter settings, filter name, dialog if present and output buffer;
00400     * copy the filter settings (not the data):
00401     */
00402    Q_RETURN( m_lpsbOut->CreateOutputBufferFor( *m_lpsbIn ) );
00403 
00404    switch ( Parameter() )
00405    {
00406       case LinearRegressionImageFilter::C:
00407          m_lpsbOut->m_csBufferName.Format( _T("%s - %s %dx%d %s"),
00408             m_lpsbIn->m_csBufferName, m_lpcsShortFilterName, Ncols(), Nrows(), ParamName() );
00409          break;
00410 
00411       case LinearRegressionImageFilter::AngleSum:
00412       case LinearRegressionImageFilter::AngleSumPi:
00413       case LinearRegressionImageFilter::AngleSumDeg:
00414          m_lpsbOut->m_csBufferName.Format( _T("%s - %s %dx%d %g·%s(%g\xB0)" ),
00415             m_lpsbIn->m_csBufferName, m_lpcsShortFilterName, Ncols(), Nrows(), Factor(), ParamName(), Theta() );
00416          break;
00417 
00418       default:
00419          m_lpsbOut->m_csBufferName.Format( _T("%s - %s %dx%d %g·%s"),
00420             m_lpsbIn->m_csBufferName, m_lpcsShortFilterName, Ncols(), Nrows(), Factor(), ParamName() );
00421          break;
00422    }
00423 
00424    /*
00425     * if the dialog is present:
00426     */
00427    if ( IsInteractive() )
00428    {
00429       m_pDlg->SetDlgItemText( IDC_BUFFEROUTNAME, m_lpsbOut->m_csBufferName );
00430    }
00431 
00432    return TRUE;                         // Ok
00433 }
00434 
00435 /*
00436  * pre-apply and process;
00437  * see also CScanFilterNull::ApplyCore().
00438  */
00439 BOOL CScanFilterLinearRegression::ApplyCore()
00440 {
00441    /*   
00442     * pre-apply must also be done from apply for scripting use:
00443     */
00444    if ( !PreApplyCore() )
00445    {
00446       return FALSE;
00447    }
00448 
00449    /*
00450     * process the L2R part and the R2L part (if present).
00451     */
00452 
00453 //   LinearRegressionImageFilter filter( Ncols(), Nrows(), Parameter() );
00454    LinearRegressionImageFilter filter( ToRadius( Ncols(), Nrows() ) );
00455    
00456    filter.Select   ( Parameter() );
00457    filter.SetTheta ( Theta()  );
00458    filter.SetFactor( Factor() );
00459 
00460    /** \todo setNorm(): verify its correct working */
00461    if ( std::numeric_limits< CScanBaseBuffer::SpacingType >::epsilon() < m_lpsbIn->GetSpacingX() )
00462    {
00463       filter.SetNorm( m_lpsbIn->GetSpacingZ() / m_lpsbIn->GetSpacingX() );
00464    }
00465    else
00466    {
00467       filter.SetNorm( 1.0 );
00468    }
00469 
00470 //   filter.apply( to_channel( m_lpsbIn ), to_channel( m_lpsbOut )  );
00471    filter.Apply( ToImage( m_lpsbIn ), ToImage( m_lpsbOut )  );
00472 
00473    if ( m_lpsbIn->IsBidirectionalScan() && m_lpsbOut->IsBidirectionalScan() )
00474    {
00475 //      filter.apply( to_channel( m_lpsbIn, true ), to_channel( m_lpsbOut, true ) );
00476       filter.Apply( ToImage( m_lpsbIn, true ), ToImage( m_lpsbOut, true ) );
00477    }
00478 
00479    /*
00480     * recalculate all temporary variables:
00481     */
00482    // ClearParametersMask( m_lpsbOut ); // FIXME: maybe
00483    m_lpsbOut->m_dwParameterMask  = 0;
00484 
00485    return TRUE;                         // return Ok
00486 }
00487 
00488 /*
00489  * measure algorithm performance.
00490  */
00491 SPerformanceTestResult CScanFilterLinearRegression::GetPerformanceTestResult()
00492 {
00493    SPerformanceTestResult result;
00494 
00495    typedef long Count;
00496 
00497    CPerfTimer Timer;
00498 
00499    /*
00500     * time Preparation:
00501     */
00502 
00503    ; // do nothing
00504 
00505    /*
00506     * time Process:
00507     */
00508    Time  timeToProcess  = 0.4;          // time to measure in [s]
00509    Count countProcessed = 0;            // iteration count
00510 
00511    Timer.Start( true );                 // restart the timing
00512    while ( Timer.Elapsed() < timeToProcess )
00513    {
00514       LinearRegressionImageFilter filter( ToRadius( Ncols(), Nrows() ) ); 
00515       
00516       filter.Select   ( Parameter() );
00517       filter.SetFactor( Factor()    );
00518 
00519 //      filter.apply( to_channel( m_lpsbIn ), to_channel( m_lpsbOut )  );
00520       filter.Apply( ToImage( m_lpsbIn ), ToImage( m_lpsbOut )  );
00521 
00522       ++countProcessed;                // update iteration count
00523    }
00524 
00525    Timer.Stop();                        // stop the timing
00526    result.timeBuffer = Timer.Elapsed() / countProcessed;
00527 
00528    if ( m_lpsbIn->IsBidirectionalScan() && m_lpsbOut->IsBidirectionalScan() )
00529    {
00530       result.timeBuffer *= 2;
00531    }
00532 
00533    result.totalTime = result.timePrepare + result.timeBuffer;
00534 
00535    return result;
00536 }
00537 
00538 /*
00539  * end of file
00540  */

Camera Filter Library documentation © 2004-2007 by Leiden Probe Microscopy