LCOV - code coverage report
Current view: top level - chart2/source/tools - StatisticsHelper.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 77 158 48.7 %
Date: 2014-11-03 Functions: 8 17 47.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "StatisticsHelper.hxx"
      21             : #include "DataSeriesHelper.hxx"
      22             : #include "ErrorBar.hxx"
      23             : #include "macros.hxx"
      24             : #include <unonames.hxx>
      25             : 
      26             : #include <rtl/math.hxx>
      27             : #include <rtl/ustrbuf.hxx>
      28             : #include <comphelper/processfactory.hxx>
      29             : 
      30             : #include <com/sun/star/chart2/data/LabeledDataSequence.hpp>
      31             : #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
      32             : #include <com/sun/star/chart2/data/XDataSink.hpp>
      33             : #include <com/sun/star/chart/ErrorBarStyle.hpp>
      34             : 
      35             : using ::com::sun::star::uno::Sequence;
      36             : using ::com::sun::star::uno::Reference;
      37             : using namespace ::com::sun::star;
      38             : 
      39             : namespace
      40             : {
      41             : 
      42           0 : double lcl_getVariance( const Sequence< double > & rData, sal_Int32 & rOutValidCount,
      43             :         bool bUnbiasedEstimator )
      44             : {
      45           0 :     const sal_Int32 nCount = rData.getLength();
      46           0 :     rOutValidCount = nCount;
      47             : 
      48           0 :     double fSum = 0.0;
      49           0 :     double fQuadSum = 0.0;
      50             : 
      51           0 :     for( sal_Int32 i = 0; i < nCount; ++i )
      52             :     {
      53           0 :         const double fData = rData[i];
      54           0 :         if( ::rtl::math::isNan( fData ))
      55           0 :             --rOutValidCount;
      56             :         else
      57             :         {
      58           0 :             fSum     += fData;
      59           0 :             fQuadSum += fData * fData;
      60             :         }
      61             :     }
      62             : 
      63             :     double fResult;
      64           0 :     if( rOutValidCount == 0 )
      65           0 :         ::rtl::math::setNan( & fResult );
      66             :     else
      67             :     {
      68           0 :         const double fN = static_cast< double >( rOutValidCount );
      69           0 :         if( bUnbiasedEstimator )
      70           0 :             fResult = (fQuadSum - fSum*fSum/fN) / (fN - 1);
      71             :         else
      72           0 :             fResult = (fQuadSum - fSum*fSum/fN) / fN;
      73             :     }
      74             : 
      75           0 :     return fResult;
      76             : }
      77             : 
      78          80 : Reference< chart2::data::XLabeledDataSequence > lcl_getErrorBarLabeledSequence(
      79             :     const Reference< chart2::data::XDataSource > & xDataSource,
      80             :     bool bPositiveValue, bool bYError,
      81             :     OUString & rOutRoleNameUsed )
      82             : {
      83          80 :     OUStringBuffer aRole( "error-bars-");
      84          80 :     if( bYError )
      85          80 :         aRole.append( 'y');
      86             :     else
      87           0 :         aRole.append( 'x');
      88             : 
      89         160 :     OUString aPlainRole = aRole.makeStringAndClear();
      90          80 :     aRole.append( aPlainRole );
      91          80 :     aRole.append( '-' );
      92             : 
      93          80 :     if( bPositiveValue )
      94          40 :         aRole = aRole.appendAscii( "positive" );
      95             :     else
      96          40 :         aRole = aRole.appendAscii( "negative" );
      97             : 
      98         160 :     OUString aLongRole = aRole.makeStringAndClear();
      99             :     Reference< chart2::data::XLabeledDataSequence > xLSeq(
     100          80 :         ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource, aLongRole ));
     101             :     // try role without "-negative" or "-positive" postfix
     102          80 :     if( xLSeq.is())
     103          68 :         rOutRoleNameUsed = aLongRole;
     104             :     else
     105             :     {
     106          12 :         xLSeq.set( ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource, aPlainRole ));
     107          12 :         if( xLSeq.is())
     108           0 :             rOutRoleNameUsed = aPlainRole;
     109             :         else
     110          12 :             rOutRoleNameUsed = aLongRole;
     111             :     }
     112             : 
     113         160 :     return xLSeq;
     114             : }
     115             : 
     116          12 : void lcl_setRole(
     117             :     const Reference< chart2::data::XDataSequence > & xNewSequence,
     118             :     const OUString & rRole )
     119             : {
     120          12 :     Reference< beans::XPropertySet > xSeqProp( xNewSequence, uno::UNO_QUERY );
     121          12 :     if( xSeqProp.is())
     122          12 :         xSeqProp->setPropertyValue( "Role", uno::makeAny( rRole ));
     123          12 : }
     124             : 
     125          12 : void lcl_addSequenceToDataSource(
     126             :     const Reference< chart2::data::XDataSource > & xDataSource,
     127             :     const Reference< chart2::data::XDataSequence > & xNewSequence,
     128             :     const OUString & rRole )
     129             : {
     130          12 :     Reference< chart2::data::XDataSink > xSink( xDataSource, uno::UNO_QUERY );
     131          24 :     Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
     132          12 :     if( ! xSink.is() )
     133          12 :         return;
     134             : 
     135          24 :     Reference< chart2::data::XLabeledDataSequence > xLSeq( chart2::data::LabeledDataSequence::create(xContext), uno::UNO_QUERY_THROW );
     136             : 
     137          12 :     lcl_setRole( xNewSequence, rRole );
     138          12 :     xLSeq->setValues( xNewSequence );
     139             :     Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences(
     140          24 :         xDataSource->getDataSequences());
     141          12 :     aSequences.realloc( aSequences.getLength() + 1 );
     142          12 :     aSequences[ aSequences.getLength() - 1 ] = xLSeq;
     143          24 :     xSink->setData( aSequences );
     144             : }
     145             : 
     146          12 : void lcl_setXMLRangePropertyAtDataSequence(
     147             :     const Reference< chart2::data::XDataSequence > & xDataSequence,
     148             :     const OUString & rXMLRange )
     149             : {
     150             :     try
     151             :     {
     152          12 :         const OUString aXMLRangePropName( "CachedXMLRange");
     153          24 :         Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY_THROW );
     154          24 :         Reference< beans::XPropertySetInfo > xInfo( xProp->getPropertySetInfo());
     155          12 :         if( xInfo.is() && xInfo->hasPropertyByName( aXMLRangePropName ))
     156          12 :             xProp->setPropertyValue( aXMLRangePropName, uno::makeAny( rXMLRange ));
     157             :     }
     158           0 :     catch( const uno::Exception & ex )
     159             :     {
     160             :         ASSERT_EXCEPTION( ex );
     161             :     }
     162          12 : }
     163             : 
     164             : } // anonymous namespace
     165             : 
     166             : namespace chart
     167             : {
     168             : 
     169           0 : double StatisticsHelper::getVariance(
     170             :     const Sequence< double > & rData,
     171             :     bool bUnbiasedEstimator /* = false */ )
     172             : {
     173             :     sal_Int32 nValCount;
     174           0 :     return lcl_getVariance( rData, nValCount, bUnbiasedEstimator );
     175             : }
     176             : 
     177           0 : double StatisticsHelper::getStandardDeviation( const Sequence< double > & rData )
     178             : {
     179           0 :     double fResult = getVariance( rData );
     180           0 :     if( ! ::rtl::math::isNan( fResult ))
     181           0 :         fResult = sqrt( fResult );
     182             : 
     183           0 :     return fResult;
     184             : }
     185             : 
     186           0 : double StatisticsHelper::getStandardError( const Sequence< double > & rData )
     187             : {
     188             :     sal_Int32 nValCount;
     189           0 :     double fVar = lcl_getVariance( rData, nValCount, false );
     190             :     double fResult;
     191             : 
     192           0 :     if( nValCount == 0 ||
     193           0 :         ::rtl::math::isNan( fVar ))
     194             :     {
     195           0 :         ::rtl::math::setNan( & fResult );
     196             :     }
     197             :     else
     198             :     {
     199             :         // standard-deviation / sqrt(n)
     200           0 :         fResult = sqrt( fVar ) / sqrt( double(nValCount) );
     201             :     }
     202             : 
     203           0 :     return fResult;
     204             : }
     205             : 
     206          68 : Reference< chart2::data::XLabeledDataSequence > StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
     207             :     const Reference< chart2::data::XDataSource > & xDataSource,
     208             :     bool bPositiveValue,
     209             :     bool bYError /* = true */ )
     210             : {
     211          68 :     Reference< chart2::data::XLabeledDataSequence > xResult;
     212          68 :     if( !xDataSource.is())
     213           0 :         return xResult;
     214             : 
     215         136 :     OUString aRole;
     216             :     Reference< chart2::data::XLabeledDataSequence > xLSeq(
     217         136 :         lcl_getErrorBarLabeledSequence( xDataSource, bPositiveValue, bYError, aRole ));
     218          68 :     if( xLSeq.is())
     219          68 :         xResult.set( xLSeq );
     220             : 
     221          68 :     return xResult;
     222             : }
     223             : 
     224          68 : Reference< chart2::data::XDataSequence > StatisticsHelper::getErrorDataSequenceFromDataSource(
     225             :     const Reference< chart2::data::XDataSource > & xDataSource,
     226             :     bool bPositiveValue,
     227             :     bool bYError /* = true */ )
     228             : {
     229             :     Reference< chart2::data::XLabeledDataSequence > xLSeq(
     230             :         StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
     231             :             xDataSource, bPositiveValue,
     232          68 :             bYError ));
     233          68 :     if( !xLSeq.is())
     234           0 :         return Reference< chart2::data::XDataSequence >();
     235             : 
     236          68 :     return xLSeq->getValues();
     237             : }
     238             : 
     239          36 : double StatisticsHelper::getErrorFromDataSource(
     240             :     const Reference< chart2::data::XDataSource > & xDataSource,
     241             :     sal_Int32 nIndex,
     242             :     bool bPositiveValue,
     243             :     bool bYError /* = true */ )
     244             : {
     245          36 :     double fResult = 0.0;
     246          36 :     ::rtl::math::setNan( & fResult );
     247             : 
     248             :     Reference< chart2::data::XDataSequence > xValues(
     249          36 :         StatisticsHelper::getErrorDataSequenceFromDataSource( xDataSource, bPositiveValue, bYError ));
     250             : 
     251          72 :     Reference< chart2::data::XNumericalDataSequence > xNumValues( xValues, uno::UNO_QUERY );
     252          36 :     if( xNumValues.is())
     253             :     {
     254          36 :         Sequence< double > aData( xNumValues->getNumericalData());
     255          36 :         if( nIndex < aData.getLength())
     256          36 :             fResult = aData[nIndex];
     257             :     }
     258           0 :     else if( xValues.is())
     259             :     {
     260           0 :         Sequence< uno::Any > aData( xValues->getData());
     261           0 :         if( nIndex < aData.getLength())
     262           0 :             aData[nIndex] >>= fResult;
     263             :     }
     264             : 
     265          72 :     return fResult;
     266             : }
     267             : 
     268          12 : void StatisticsHelper::setErrorDataSequence(
     269             :     const Reference< chart2::data::XDataSource > & xDataSource,
     270             :     const Reference< chart2::data::XDataProvider > & xDataProvider,
     271             :     const OUString & rNewRange,
     272             :     bool bPositiveValue,
     273             :     bool bYError /* = true */,
     274             :     OUString * pXMLRange /* = 0 */ )
     275             : {
     276          12 :     Reference< chart2::data::XDataSink > xDataSink( xDataSource, uno::UNO_QUERY );
     277          12 :     if( ! ( xDataSink.is() && xDataProvider.is()))
     278          12 :         return;
     279             : 
     280          24 :     OUString aRole;
     281             :     Reference< chart2::data::XLabeledDataSequence > xLSeq(
     282          24 :         lcl_getErrorBarLabeledSequence( xDataSource, bPositiveValue, bYError, aRole ));
     283             :     Reference< chart2::data::XDataSequence > xNewSequence(
     284          24 :         xDataProvider->createDataSequenceByRangeRepresentation( rNewRange ));
     285          12 :     if( xNewSequence.is())
     286             :     {
     287          12 :         if( pXMLRange )
     288          12 :             lcl_setXMLRangePropertyAtDataSequence( xNewSequence, *pXMLRange );
     289          12 :         if( xLSeq.is())
     290             :         {
     291           0 :             lcl_setRole( xNewSequence, aRole );
     292           0 :             xLSeq->setValues( xNewSequence );
     293             :         }
     294             :         else
     295          12 :             lcl_addSequenceToDataSource( xDataSource, xNewSequence, aRole );
     296          12 :     }
     297             : }
     298             : 
     299           0 : Reference< beans::XPropertySet > StatisticsHelper::addErrorBars(
     300             :     const Reference< chart2::XDataSeries > & xDataSeries,
     301             :     const Reference< uno::XComponentContext > & xContext,
     302             :     sal_Int32 nStyle,
     303             :     bool bYError /* = true */ )
     304             : {
     305           0 :     Reference< beans::XPropertySet > xErrorBar;
     306           0 :     Reference< beans::XPropertySet > xSeriesProp( xDataSeries, uno::UNO_QUERY );
     307           0 :     if( !xSeriesProp.is())
     308           0 :         return xErrorBar;
     309             : 
     310             :     const OUString aPropName(
     311           0 :             (bYError) ? OUString(CHART_UNONAME_ERRORBAR_Y) : OUString(CHART_UNONAME_ERRORBAR_X));
     312           0 :     if( !( xSeriesProp->getPropertyValue( aPropName ) >>= xErrorBar ) ||
     313           0 :         !xErrorBar.is())
     314             :     {
     315           0 :         xErrorBar.set( createErrorBar( xContext ));
     316             :     }
     317             : 
     318             :     OSL_ASSERT( xErrorBar.is());
     319           0 :     if( xErrorBar.is())
     320             :     {
     321           0 :         xErrorBar->setPropertyValue( "ErrorBarStyle", uno::makeAny( nStyle ));
     322             :     }
     323             : 
     324           0 :     xSeriesProp->setPropertyValue( aPropName, uno::makeAny( xErrorBar ));
     325             : 
     326           0 :     return xErrorBar;
     327             : }
     328             : 
     329           0 : Reference< beans::XPropertySet > StatisticsHelper::getErrorBars(
     330             :     const Reference< chart2::XDataSeries > & xDataSeries,
     331             :     bool bYError /* = true */ )
     332             : {
     333           0 :     Reference< beans::XPropertySet > xSeriesProp( xDataSeries, uno::UNO_QUERY );
     334           0 :     Reference< beans::XPropertySet > xErrorBar;
     335             :     const OUString aPropName(
     336           0 :             (bYError) ? OUString(CHART_UNONAME_ERRORBAR_Y) : OUString(CHART_UNONAME_ERRORBAR_X));
     337             : 
     338           0 :     if ( xSeriesProp.is())
     339           0 :         xSeriesProp->getPropertyValue( aPropName ) >>= xErrorBar;
     340             : 
     341           0 :     return xErrorBar;
     342             : }
     343             : 
     344           0 : bool StatisticsHelper::hasErrorBars(
     345             :     const Reference< chart2::XDataSeries > & xDataSeries,
     346             :     bool bYError /* = true */ )
     347             : {
     348           0 :     Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError ));
     349           0 :     sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE;
     350             : 
     351           0 :     return ( xErrorBar.is() &&
     352           0 :              ( xErrorBar->getPropertyValue( "ErrorBarStyle") >>= nStyle ) &&
     353           0 :              nStyle != ::com::sun::star::chart::ErrorBarStyle::NONE );
     354             : }
     355             : 
     356           0 : void StatisticsHelper::removeErrorBars(
     357             :     const Reference< chart2::XDataSeries > & xDataSeries,
     358             :     bool bYError /* = true  */ )
     359             : {
     360           0 :     Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError ));
     361           0 :     if ( xErrorBar.is())
     362           0 :         xErrorBar->setPropertyValue( "ErrorBarStyle", uno::makeAny(
     363           0 :                                          ::com::sun::star::chart::ErrorBarStyle::NONE ));
     364           0 : }
     365             : 
     366           0 : bool StatisticsHelper::usesErrorBarRanges(
     367             :     const Reference< chart2::XDataSeries > & xDataSeries,
     368             :     bool bYError /* = true */ )
     369             : {
     370           0 :     Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError ));
     371           0 :     sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE;
     372             : 
     373           0 :     return ( xErrorBar.is() &&
     374           0 :              ( xErrorBar->getPropertyValue( "ErrorBarStyle") >>= nStyle ) &&
     375           0 :              nStyle == ::com::sun::star::chart::ErrorBarStyle::FROM_DATA );
     376             : }
     377             : 
     378             : } //  namespace chart
     379             : 
     380             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10