summaryrefslogtreecommitdiff
path: root/chart2/source/tools/StatisticsHelper.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'chart2/source/tools/StatisticsHelper.cxx')
-rwxr-xr-xchart2/source/tools/StatisticsHelper.cxx391
1 files changed, 391 insertions, 0 deletions
diff --git a/chart2/source/tools/StatisticsHelper.cxx b/chart2/source/tools/StatisticsHelper.cxx
new file mode 100755
index 000000000000..8cec1321c579
--- /dev/null
+++ b/chart2/source/tools/StatisticsHelper.cxx
@@ -0,0 +1,391 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+#include "StatisticsHelper.hxx"
+#include "DataSeriesHelper.hxx"
+#include "ErrorBar.hxx"
+#include "macros.hxx"
+
+#include <rtl/math.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <comphelper/processfactory.hxx>
+
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/chart2/data/XLabeledDataSequence.hpp>
+#include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
+#include <com/sun/star/chart2/data/XDataSink.hpp>
+#include <com/sun/star/chart/ErrorBarStyle.hpp>
+
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+using ::rtl::OUString;
+using ::rtl::OUStringBuffer;
+using namespace ::com::sun::star;
+
+namespace
+{
+
+double lcl_getVariance( const Sequence< double > & rData, sal_Int32 & rOutValidCount,
+ bool bUnbiasedEstimator )
+{
+ const sal_Int32 nCount = rData.getLength();
+ rOutValidCount = nCount;
+
+ double fSum = 0.0;
+ double fQuadSum = 0.0;
+
+ for( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ const double fData = rData[i];
+ if( ::rtl::math::isNan( fData ))
+ --rOutValidCount;
+ else
+ {
+ fSum += fData;
+ fQuadSum += fData * fData;
+ }
+ }
+
+ double fResult;
+ if( rOutValidCount == 0 )
+ ::rtl::math::setNan( & fResult );
+ else
+ {
+ const double fN = static_cast< double >( rOutValidCount );
+ if( bUnbiasedEstimator )
+ fResult = (fQuadSum - fSum*fSum/fN) / (fN - 1);
+ else
+ fResult = (fQuadSum - fSum*fSum/fN) / fN;
+ }
+
+ return fResult;
+}
+
+Reference< chart2::data::XLabeledDataSequence > lcl_getErrorBarLabeledSequence(
+ const Reference< chart2::data::XDataSource > & xDataSource,
+ bool bPositiveValue, bool bYError,
+ OUString & rOutRoleNameUsed )
+{
+ OUStringBuffer aRole( C2U("error-bars-"));
+ if( bYError )
+ aRole.append( sal_Unicode( 'y' ));
+ else
+ aRole.append( sal_Unicode( 'x' ));
+
+ OUString aPlainRole = aRole.makeStringAndClear();
+ aRole.append( aPlainRole );
+ aRole.append( sal_Unicode( '-' ));
+
+ if( bPositiveValue )
+ aRole = aRole.appendAscii( "positive" );
+ else
+ aRole = aRole.appendAscii( "negative" );
+
+ OUString aLongRole = aRole.makeStringAndClear();
+ Reference< chart2::data::XLabeledDataSequence > xLSeq(
+ ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource, aLongRole ));
+ // try role without "-negative" or "-positive" postfix
+ if( xLSeq.is())
+ rOutRoleNameUsed = aLongRole;
+ else
+ {
+ xLSeq.set( ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource, aPlainRole ));
+ if( xLSeq.is())
+ rOutRoleNameUsed = aPlainRole;
+ else
+ rOutRoleNameUsed = aLongRole;
+ }
+
+ return xLSeq;
+}
+
+void lcl_setRole(
+ const Reference< chart2::data::XDataSequence > & xNewSequence,
+ const OUString & rRole )
+{
+ Reference< beans::XPropertySet > xSeqProp( xNewSequence, uno::UNO_QUERY );
+ if( xSeqProp.is())
+ xSeqProp->setPropertyValue( C2U("Role"), uno::makeAny( rRole ));
+}
+
+void lcl_addSequenceToDataSource(
+ const Reference< chart2::data::XDataSource > & xDataSource,
+ const Reference< chart2::data::XDataSequence > & xNewSequence,
+ const OUString & rRole )
+{
+ Reference< chart2::data::XDataSink > xSink( xDataSource, uno::UNO_QUERY );
+ Reference< lang::XMultiServiceFactory > xFact( comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW );
+ if( ! ( xFact.is() && xSink.is() ))
+ return;
+
+ Reference< chart2::data::XLabeledDataSequence > xLSeq(
+ xFact->createInstance( C2U("com.sun.star.chart2.data.LabeledDataSequence")), uno::UNO_QUERY );
+ if( xLSeq.is())
+ {
+ lcl_setRole( xNewSequence, rRole );
+ xLSeq->setValues( xNewSequence );
+ Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences(
+ xDataSource->getDataSequences());
+ aSequences.realloc( aSequences.getLength() + 1 );
+ aSequences[ aSequences.getLength() - 1 ] = xLSeq;
+ xSink->setData( aSequences );
+ }
+}
+
+void lcl_setXMLRangePropertyAtDataSequence(
+ const Reference< chart2::data::XDataSequence > & xDataSequence,
+ const OUString & rXMLRange )
+{
+ try
+ {
+ const OUString aXMLRangePropName( C2U( "CachedXMLRange" ));
+ Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY_THROW );
+ Reference< beans::XPropertySetInfo > xInfo( xProp->getPropertySetInfo());
+ if( xInfo.is() && xInfo->hasPropertyByName( aXMLRangePropName ))
+ xProp->setPropertyValue( aXMLRangePropName, uno::makeAny( rXMLRange ));
+ }
+ catch( const uno::Exception & ex )
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+double StatisticsHelper::getVariance(
+ const Sequence< double > & rData,
+ bool bUnbiasedEstimator /* = false */ )
+{
+ sal_Int32 nValCount;
+ return lcl_getVariance( rData, nValCount, bUnbiasedEstimator );
+}
+
+double StatisticsHelper::getStandardDeviation( const Sequence< double > & rData )
+{
+ double fResult = getVariance( rData );
+ if( ! ::rtl::math::isNan( fResult ))
+ fResult = sqrt( fResult );
+
+ return fResult;
+}
+
+double StatisticsHelper::getStandardError( const Sequence< double > & rData )
+{
+ sal_Int32 nValCount;
+ double fVar = lcl_getVariance( rData, nValCount, false );
+ double fResult;
+
+ if( nValCount == 0 ||
+ ::rtl::math::isNan( fVar ))
+ {
+ ::rtl::math::setNan( & fResult );
+ }
+ else
+ {
+ // standard-deviation / sqrt(n)
+ fResult = sqrt( fVar ) / sqrt( double(nValCount) );
+ }
+
+ return fResult;
+}
+
+Reference< chart2::data::XLabeledDataSequence > StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
+ const Reference< chart2::data::XDataSource > & xDataSource,
+ bool bPositiveValue,
+ bool bYError /* = true */ )
+{
+ Reference< chart2::data::XLabeledDataSequence > xResult;
+ if( !xDataSource.is())
+ return xResult;
+
+ OUString aRole;
+ Reference< chart2::data::XLabeledDataSequence > xLSeq(
+ lcl_getErrorBarLabeledSequence( xDataSource, bPositiveValue, bYError, aRole ));
+ if( xLSeq.is())
+ xResult.set( xLSeq );
+
+ return xResult;
+}
+
+Reference< chart2::data::XDataSequence > StatisticsHelper::getErrorDataSequenceFromDataSource(
+ const Reference< chart2::data::XDataSource > & xDataSource,
+ bool bPositiveValue,
+ bool bYError /* = true */ )
+{
+ Reference< chart2::data::XLabeledDataSequence > xLSeq(
+ StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
+ xDataSource, bPositiveValue,
+ bYError ));
+ if( !xLSeq.is())
+ return Reference< chart2::data::XDataSequence >();
+
+ return xLSeq->getValues();
+}
+
+double StatisticsHelper::getErrorFromDataSource(
+ const Reference< chart2::data::XDataSource > & xDataSource,
+ sal_Int32 nIndex,
+ bool bPositiveValue,
+ bool bYError /* = true */ )
+{
+ double fResult = 0.0;
+ ::rtl::math::setNan( & fResult );
+
+ Reference< chart2::data::XDataSequence > xValues(
+ StatisticsHelper::getErrorDataSequenceFromDataSource( xDataSource, bPositiveValue, bYError ));
+
+ Reference< chart2::data::XNumericalDataSequence > xNumValues( xValues, uno::UNO_QUERY );
+ if( xNumValues.is())
+ {
+ Sequence< double > aData( xNumValues->getNumericalData());
+ if( nIndex < aData.getLength())
+ fResult = aData[nIndex];
+ }
+ else if( xValues.is())
+ {
+ Sequence< uno::Any > aData( xValues->getData());
+ if( nIndex < aData.getLength())
+ aData[nIndex] >>= fResult;
+ }
+
+ return fResult;
+}
+
+void StatisticsHelper::setErrorDataSequence(
+ const Reference< chart2::data::XDataSource > & xDataSource,
+ const Reference< chart2::data::XDataProvider > & xDataProvider,
+ const OUString & rNewRange,
+ bool bPositiveValue,
+ bool bYError /* = true */,
+ OUString * pXMLRange /* = 0 */ )
+{
+ Reference< chart2::data::XDataSink > xDataSink( xDataSource, uno::UNO_QUERY );
+ if( ! ( xDataSink.is() && xDataProvider.is()))
+ return;
+
+ OUString aRole;
+ Reference< chart2::data::XLabeledDataSequence > xLSeq(
+ lcl_getErrorBarLabeledSequence( xDataSource, bPositiveValue, bYError, aRole ));
+ Reference< chart2::data::XDataSequence > xNewSequence(
+ xDataProvider->createDataSequenceByRangeRepresentation( rNewRange ));
+ if( xNewSequence.is())
+ {
+ if( pXMLRange )
+ lcl_setXMLRangePropertyAtDataSequence( xNewSequence, *pXMLRange );
+ if( xLSeq.is())
+ {
+ lcl_setRole( xNewSequence, aRole );
+ xLSeq->setValues( xNewSequence );
+ }
+ else
+ lcl_addSequenceToDataSource( xDataSource, xNewSequence, aRole );
+ }
+}
+
+Reference< beans::XPropertySet > StatisticsHelper::addErrorBars(
+ const Reference< chart2::XDataSeries > & xDataSeries,
+ const Reference< uno::XComponentContext > & xContext,
+ sal_Int32 nStyle,
+ bool bYError /* = true */ )
+{
+ Reference< beans::XPropertySet > xErrorBar;
+ Reference< beans::XPropertySet > xSeriesProp( xDataSeries, uno::UNO_QUERY );
+ if( !xSeriesProp.is())
+ return xErrorBar;
+
+ const OUString aPropName( bYError ? C2U("ErrorBarY") : C2U("ErrorBarX"));
+ if( !( xSeriesProp->getPropertyValue( aPropName ) >>= xErrorBar ) ||
+ !xErrorBar.is())
+ {
+ xErrorBar.set( createErrorBar( xContext ));
+ }
+
+ OSL_ASSERT( xErrorBar.is());
+ if( xErrorBar.is())
+ {
+ xErrorBar->setPropertyValue( C2U("ErrorBarStyle"), uno::makeAny( nStyle ));
+ }
+
+ xSeriesProp->setPropertyValue( aPropName, uno::makeAny( xErrorBar ));
+
+ return xErrorBar;
+}
+
+Reference< beans::XPropertySet > StatisticsHelper::getErrorBars(
+ const Reference< chart2::XDataSeries > & xDataSeries,
+ bool bYError /* = true */ )
+{
+ Reference< beans::XPropertySet > xSeriesProp( xDataSeries, uno::UNO_QUERY );
+ Reference< beans::XPropertySet > xErrorBar;
+ const OUString aPropName( bYError ? C2U("ErrorBarY") : C2U("ErrorBarX"));
+
+ if ( xSeriesProp.is())
+ xSeriesProp->getPropertyValue( aPropName ) >>= xErrorBar;
+
+ return xErrorBar;
+}
+
+bool StatisticsHelper::hasErrorBars(
+ const Reference< chart2::XDataSeries > & xDataSeries,
+ bool bYError /* = true */ )
+{
+ Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError ));
+ sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE;
+
+ return ( xErrorBar.is() &&
+ ( xErrorBar->getPropertyValue( C2U("ErrorBarStyle")) >>= nStyle ) &&
+ nStyle != ::com::sun::star::chart::ErrorBarStyle::NONE );
+}
+
+void StatisticsHelper::removeErrorBars(
+ const Reference< chart2::XDataSeries > & xDataSeries,
+ bool bYError /* = true */ )
+{
+ Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError ));
+ if ( xErrorBar.is())
+ xErrorBar->setPropertyValue( C2U("ErrorBarStyle"), uno::makeAny(
+ ::com::sun::star::chart::ErrorBarStyle::NONE ));
+}
+
+bool StatisticsHelper::usesErrorBarRanges(
+ const Reference< chart2::XDataSeries > & xDataSeries,
+ bool bYError /* = true */ )
+{
+ Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError ));
+ sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE;
+
+ return ( xErrorBar.is() &&
+ ( xErrorBar->getPropertyValue( C2U("ErrorBarStyle")) >>= nStyle ) &&
+ nStyle == ::com::sun::star::chart::ErrorBarStyle::FROM_DATA );
+}
+
+} // namespace chart