Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / chart2 / source / tools / StatisticsHelper.cxx
blob25e27438c259c9b001f8e4d4770a072e50f7131e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <StatisticsHelper.hxx>
21 #include <DataSeriesHelper.hxx>
22 #include <ErrorBar.hxx>
23 #include <unonames.hxx>
25 #include <rtl/math.hxx>
26 #include <rtl/ustrbuf.hxx>
27 #include <comphelper/processfactory.hxx>
29 #include <com/sun/star/chart2/data/LabeledDataSequence.hpp>
30 #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
31 #include <com/sun/star/chart2/data/XDataProvider.hpp>
32 #include <com/sun/star/chart2/data/XDataSink.hpp>
33 #include <com/sun/star/chart/ErrorBarStyle.hpp>
34 #include <tools/diagnose_ex.h>
36 using ::com::sun::star::uno::Sequence;
37 using ::com::sun::star::uno::Reference;
38 using namespace ::com::sun::star;
40 namespace
43 double lcl_getVariance( const Sequence< double > & rData, sal_Int32 & rOutValidCount )
45 const sal_Int32 nCount = rData.getLength();
46 rOutValidCount = nCount;
48 double fSum = 0.0;
49 double fQuadSum = 0.0;
51 for( sal_Int32 i = 0; i < nCount; ++i )
53 const double fData = rData[i];
54 if( ::rtl::math::isNan( fData ))
55 --rOutValidCount;
56 else
58 fSum += fData;
59 fQuadSum += fData * fData;
63 double fResult;
64 if( rOutValidCount == 0 )
65 ::rtl::math::setNan( & fResult );
66 else
68 const double fN = static_cast< double >( rOutValidCount );
69 fResult = (fQuadSum - fSum*fSum/fN) / fN;
72 return fResult;
75 Reference< chart2::data::XLabeledDataSequence > lcl_getErrorBarLabeledSequence(
76 const Reference< chart2::data::XDataSource > & xDataSource,
77 bool bPositiveValue, bool bYError,
78 OUString & rOutRoleNameUsed )
80 OUStringBuffer aRole( "error-bars-");
81 if( bYError )
82 aRole.append( 'y');
83 else
84 aRole.append( 'x');
86 OUString aPlainRole = aRole.makeStringAndClear();
87 aRole.append( aPlainRole );
88 aRole.append( '-' );
90 if( bPositiveValue )
91 aRole.append( "positive" );
92 else
93 aRole.append( "negative" );
95 OUString aLongRole = aRole.makeStringAndClear();
96 Reference< chart2::data::XLabeledDataSequence > xLSeq(
97 ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource, aLongRole ));
98 // try role without "-negative" or "-positive" postfix
99 if( xLSeq.is())
100 rOutRoleNameUsed = aLongRole;
101 else
103 xLSeq.set( ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource, aPlainRole ));
104 if( xLSeq.is())
105 rOutRoleNameUsed = aPlainRole;
106 else
107 rOutRoleNameUsed = aLongRole;
110 return xLSeq;
113 void lcl_setRole(
114 const Reference< chart2::data::XDataSequence > & xNewSequence,
115 const OUString & rRole )
117 Reference< beans::XPropertySet > xSeqProp( xNewSequence, uno::UNO_QUERY );
118 if( xSeqProp.is())
119 xSeqProp->setPropertyValue( "Role", uno::Any( rRole ));
122 void lcl_addSequenceToDataSource(
123 const Reference< chart2::data::XDataSource > & xDataSource,
124 const Reference< chart2::data::XDataSequence > & xNewSequence,
125 const OUString & rRole )
127 Reference< chart2::data::XDataSink > xSink( xDataSource, uno::UNO_QUERY );
128 Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
129 if( ! xSink.is() )
130 return;
132 Reference< chart2::data::XLabeledDataSequence > xLSeq( chart2::data::LabeledDataSequence::create(xContext), uno::UNO_QUERY_THROW );
134 lcl_setRole( xNewSequence, rRole );
135 xLSeq->setValues( xNewSequence );
136 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences(
137 xDataSource->getDataSequences());
138 aSequences.realloc( aSequences.getLength() + 1 );
139 aSequences[ aSequences.getLength() - 1 ] = xLSeq;
140 xSink->setData( aSequences );
143 void lcl_setXMLRangePropertyAtDataSequence(
144 const Reference< chart2::data::XDataSequence > & xDataSequence,
145 const OUString & rXMLRange )
149 const OUString aXMLRangePropName( "CachedXMLRange");
150 Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY_THROW );
151 Reference< beans::XPropertySetInfo > xInfo( xProp->getPropertySetInfo());
152 if( xInfo.is() && xInfo->hasPropertyByName( aXMLRangePropName ))
153 xProp->setPropertyValue( aXMLRangePropName, uno::Any( rXMLRange ));
155 catch( const uno::Exception & )
157 DBG_UNHANDLED_EXCEPTION("chart2");
161 } // anonymous namespace
163 namespace chart
166 double StatisticsHelper::getVariance(
167 const Sequence< double > & rData )
169 sal_Int32 nValCount;
170 return lcl_getVariance( rData, nValCount );
173 double StatisticsHelper::getStandardDeviation( const Sequence< double > & rData )
175 double fResult = getVariance( rData );
176 if( ! ::rtl::math::isNan( fResult ))
177 fResult = sqrt( fResult );
179 return fResult;
182 double StatisticsHelper::getStandardError( const Sequence< double > & rData )
184 sal_Int32 nValCount;
185 double fVar = lcl_getVariance( rData, nValCount );
186 double fResult;
188 if( nValCount == 0 ||
189 ::rtl::math::isNan( fVar ))
191 ::rtl::math::setNan( & fResult );
193 else
195 // standard-deviation / sqrt(n)
196 fResult = sqrt( fVar ) / sqrt( double(nValCount) );
199 return fResult;
202 Reference< chart2::data::XLabeledDataSequence > StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
203 const Reference< chart2::data::XDataSource > & xDataSource,
204 bool bPositiveValue,
205 bool bYError /* = true */ )
207 Reference< chart2::data::XLabeledDataSequence > xResult;
208 if( !xDataSource.is())
209 return xResult;
211 OUString aRole;
212 Reference< chart2::data::XLabeledDataSequence > xLSeq(
213 lcl_getErrorBarLabeledSequence( xDataSource, bPositiveValue, bYError, aRole ));
214 if( xLSeq.is())
215 xResult.set( xLSeq );
217 return xResult;
220 Reference< chart2::data::XDataSequence > StatisticsHelper::getErrorDataSequenceFromDataSource(
221 const Reference< chart2::data::XDataSource > & xDataSource,
222 bool bPositiveValue,
223 bool bYError /* = true */ )
225 Reference< chart2::data::XLabeledDataSequence > xLSeq(
226 StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
227 xDataSource, bPositiveValue,
228 bYError ));
229 if( !xLSeq.is())
230 return Reference< chart2::data::XDataSequence >();
232 return xLSeq->getValues();
235 double StatisticsHelper::getErrorFromDataSource(
236 const Reference< chart2::data::XDataSource > & xDataSource,
237 sal_Int32 nIndex,
238 bool bPositiveValue,
239 bool bYError /* = true */ )
241 double fResult = 0.0;
242 ::rtl::math::setNan( & fResult );
244 Reference< chart2::data::XDataSequence > xValues(
245 StatisticsHelper::getErrorDataSequenceFromDataSource( xDataSource, bPositiveValue, bYError ));
247 Reference< chart2::data::XNumericalDataSequence > xNumValues( xValues, uno::UNO_QUERY );
248 if( xNumValues.is())
250 Sequence< double > aData( xNumValues->getNumericalData());
251 if( nIndex < aData.getLength())
252 fResult = aData[nIndex];
254 else if( xValues.is())
256 Sequence< uno::Any > aData( xValues->getData());
257 if( nIndex < aData.getLength())
258 aData[nIndex] >>= fResult;
261 return fResult;
264 void StatisticsHelper::setErrorDataSequence(
265 const Reference< chart2::data::XDataSource > & xDataSource,
266 const Reference< chart2::data::XDataProvider > & xDataProvider,
267 const OUString & rNewRange,
268 bool bPositiveValue,
269 bool bYError /* = true */,
270 OUString const * pXMLRange /* = 0 */ )
272 Reference< chart2::data::XDataSink > xDataSink( xDataSource, uno::UNO_QUERY );
273 if( ! ( xDataSink.is() && xDataProvider.is()))
274 return;
276 OUString aRole;
277 Reference< chart2::data::XLabeledDataSequence > xLSeq(
278 lcl_getErrorBarLabeledSequence( xDataSource, bPositiveValue, bYError, aRole ));
279 Reference< chart2::data::XDataSequence > xNewSequence(
280 xDataProvider->createDataSequenceByRangeRepresentation( rNewRange ));
281 if( xNewSequence.is())
283 if( pXMLRange )
284 lcl_setXMLRangePropertyAtDataSequence( xNewSequence, *pXMLRange );
285 if( xLSeq.is())
287 lcl_setRole( xNewSequence, aRole );
288 xLSeq->setValues( xNewSequence );
290 else
291 lcl_addSequenceToDataSource( xDataSource, xNewSequence, aRole );
295 Reference< beans::XPropertySet > StatisticsHelper::addErrorBars(
296 const Reference< chart2::XDataSeries > & xDataSeries,
297 sal_Int32 nStyle,
298 bool bYError /* = true */ )
300 Reference< beans::XPropertySet > xErrorBar;
301 Reference< beans::XPropertySet > xSeriesProp( xDataSeries, uno::UNO_QUERY );
302 if( !xSeriesProp.is())
303 return xErrorBar;
305 const OUString aPropName(
306 bYError ? OUString(CHART_UNONAME_ERRORBAR_Y) : OUString(CHART_UNONAME_ERRORBAR_X));
307 if( !( xSeriesProp->getPropertyValue( aPropName ) >>= xErrorBar ) ||
308 !xErrorBar.is())
310 xErrorBar.set( new ErrorBar );
313 OSL_ASSERT( xErrorBar.is());
314 if( xErrorBar.is())
316 xErrorBar->setPropertyValue( "ErrorBarStyle", uno::Any( nStyle ));
319 xSeriesProp->setPropertyValue( aPropName, uno::Any( xErrorBar ));
321 return xErrorBar;
324 Reference< beans::XPropertySet > StatisticsHelper::getErrorBars(
325 const Reference< chart2::XDataSeries > & xDataSeries,
326 bool bYError /* = true */ )
328 Reference< beans::XPropertySet > xSeriesProp( xDataSeries, uno::UNO_QUERY );
329 Reference< beans::XPropertySet > xErrorBar;
330 const OUString aPropName(
331 bYError ? OUString(CHART_UNONAME_ERRORBAR_Y) : OUString(CHART_UNONAME_ERRORBAR_X));
333 if ( xSeriesProp.is())
334 xSeriesProp->getPropertyValue( aPropName ) >>= xErrorBar;
336 return xErrorBar;
339 bool StatisticsHelper::hasErrorBars(
340 const Reference< chart2::XDataSeries > & xDataSeries,
341 bool bYError /* = true */ )
343 Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError ));
344 sal_Int32 nStyle = css::chart::ErrorBarStyle::NONE;
346 return ( xErrorBar.is() &&
347 ( xErrorBar->getPropertyValue( "ErrorBarStyle") >>= nStyle ) &&
348 nStyle != css::chart::ErrorBarStyle::NONE );
351 void StatisticsHelper::removeErrorBars(
352 const Reference< chart2::XDataSeries > & xDataSeries,
353 bool bYError /* = true */ )
355 Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError ));
356 if ( xErrorBar.is())
357 xErrorBar->setPropertyValue( "ErrorBarStyle", uno::Any(
358 css::chart::ErrorBarStyle::NONE ));
361 bool StatisticsHelper::usesErrorBarRanges(
362 const Reference< chart2::XDataSeries > & xDataSeries,
363 bool bYError /* = true */ )
365 Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError ));
366 sal_Int32 nStyle = css::chart::ErrorBarStyle::NONE;
368 return ( xErrorBar.is() &&
369 ( xErrorBar->getPropertyValue( "ErrorBarStyle") >>= nStyle ) &&
370 nStyle == css::chart::ErrorBarStyle::FROM_DATA );
373 } // namespace chart
375 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */