merged tag ooo/OOO330_m14
[LibreOffice.git] / chart2 / source / tools / StatisticsHelper.cxx
blob721451c276da744e1cb876efa693daf04693c8cb
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_chart2.hxx"
30 #include "StatisticsHelper.hxx"
31 #include "DataSeriesHelper.hxx"
32 #include "ErrorBar.hxx"
33 #include "macros.hxx"
35 #include <rtl/math.hxx>
36 #include <rtl/ustrbuf.hxx>
37 #include <comphelper/processfactory.hxx>
39 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
40 #include <com/sun/star/chart2/data/XLabeledDataSequence.hpp>
41 #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
42 #include <com/sun/star/chart2/data/XDataSink.hpp>
43 #include <com/sun/star/chart/ErrorBarStyle.hpp>
45 using ::com::sun::star::uno::Sequence;
46 using ::com::sun::star::uno::Reference;
47 using ::rtl::OUString;
48 using ::rtl::OUStringBuffer;
49 using namespace ::com::sun::star;
51 namespace
54 double lcl_getVariance( const Sequence< double > & rData, sal_Int32 & rOutValidCount,
55 bool bUnbiasedEstimator )
57 const sal_Int32 nCount = rData.getLength();
58 rOutValidCount = nCount;
60 double fSum = 0.0;
61 double fQuadSum = 0.0;
63 for( sal_Int32 i = 0; i < nCount; ++i )
65 const double fData = rData[i];
66 if( ::rtl::math::isNan( fData ))
67 --rOutValidCount;
68 else
70 fSum += fData;
71 fQuadSum += fData * fData;
75 double fResult;
76 if( rOutValidCount == 0 )
77 ::rtl::math::setNan( & fResult );
78 else
80 const double fN = static_cast< double >( rOutValidCount );
81 if( bUnbiasedEstimator )
82 fResult = (fQuadSum - fSum*fSum/fN) / (fN - 1);
83 else
84 fResult = (fQuadSum - fSum*fSum/fN) / fN;
87 return fResult;
90 Reference< chart2::data::XLabeledDataSequence > lcl_getErrorBarLabeledSequence(
91 const Reference< chart2::data::XDataSource > & xDataSource,
92 bool bPositiveValue, bool bYError,
93 OUString & rOutRoleNameUsed )
95 OUStringBuffer aRole( C2U("error-bars-"));
96 if( bYError )
97 aRole.append( sal_Unicode( 'y' ));
98 else
99 aRole.append( sal_Unicode( 'x' ));
101 OUString aPlainRole = aRole.makeStringAndClear();
102 aRole.append( aPlainRole );
103 aRole.append( sal_Unicode( '-' ));
105 if( bPositiveValue )
106 aRole = aRole.appendAscii( "positive" );
107 else
108 aRole = aRole.appendAscii( "negative" );
110 OUString aLongRole = aRole.makeStringAndClear();
111 Reference< chart2::data::XLabeledDataSequence > xLSeq(
112 ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource, aLongRole ));
113 // try role without "-negative" or "-positive" postfix
114 if( xLSeq.is())
115 rOutRoleNameUsed = aLongRole;
116 else
118 xLSeq.set( ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource, aPlainRole ));
119 if( xLSeq.is())
120 rOutRoleNameUsed = aPlainRole;
121 else
122 rOutRoleNameUsed = aLongRole;
125 return xLSeq;
128 void lcl_setRole(
129 const Reference< chart2::data::XDataSequence > & xNewSequence,
130 const OUString & rRole )
132 Reference< beans::XPropertySet > xSeqProp( xNewSequence, uno::UNO_QUERY );
133 if( xSeqProp.is())
134 xSeqProp->setPropertyValue( C2U("Role"), uno::makeAny( rRole ));
137 void lcl_addSequenceToDataSource(
138 const Reference< chart2::data::XDataSource > & xDataSource,
139 const Reference< chart2::data::XDataSequence > & xNewSequence,
140 const OUString & rRole )
142 Reference< chart2::data::XDataSink > xSink( xDataSource, uno::UNO_QUERY );
143 Reference< lang::XMultiServiceFactory > xFact( comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW );
144 if( ! ( xFact.is() && xSink.is() ))
145 return;
147 Reference< chart2::data::XLabeledDataSequence > xLSeq(
148 xFact->createInstance( C2U("com.sun.star.chart2.data.LabeledDataSequence")), uno::UNO_QUERY );
149 if( xLSeq.is())
151 lcl_setRole( xNewSequence, rRole );
152 xLSeq->setValues( xNewSequence );
153 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences(
154 xDataSource->getDataSequences());
155 aSequences.realloc( aSequences.getLength() + 1 );
156 aSequences[ aSequences.getLength() - 1 ] = xLSeq;
157 xSink->setData( aSequences );
161 void lcl_setXMLRangePropertyAtDataSequence(
162 const Reference< chart2::data::XDataSequence > & xDataSequence,
163 const OUString & rXMLRange )
167 const OUString aXMLRangePropName( C2U( "CachedXMLRange" ));
168 Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY_THROW );
169 Reference< beans::XPropertySetInfo > xInfo( xProp->getPropertySetInfo());
170 if( xInfo.is() && xInfo->hasPropertyByName( aXMLRangePropName ))
171 xProp->setPropertyValue( aXMLRangePropName, uno::makeAny( rXMLRange ));
173 catch( const uno::Exception & ex )
175 ASSERT_EXCEPTION( ex );
179 } // anonymous namespace
181 namespace chart
184 // static
185 double StatisticsHelper::getVariance(
186 const Sequence< double > & rData,
187 bool bUnbiasedEstimator /* = false */ )
189 sal_Int32 nValCount;
190 return lcl_getVariance( rData, nValCount, bUnbiasedEstimator );
193 // static
194 double StatisticsHelper::getStandardDeviation( const Sequence< double > & rData )
196 double fResult = getVariance( rData );
197 if( ! ::rtl::math::isNan( fResult ))
198 fResult = sqrt( fResult );
200 return fResult;
203 // static
204 double StatisticsHelper::getStandardError( const Sequence< double > & rData )
206 sal_Int32 nValCount;
207 double fVar = lcl_getVariance( rData, nValCount, false );
208 double fResult;
210 if( nValCount == 0 ||
211 ::rtl::math::isNan( fVar ))
213 ::rtl::math::setNan( & fResult );
215 else
217 // standard-deviation / sqrt(n)
218 fResult = sqrt( fVar ) / sqrt( double(nValCount) );
221 return fResult;
224 // static
225 Reference< chart2::data::XLabeledDataSequence > StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
226 const Reference< chart2::data::XDataSource > & xDataSource,
227 bool bPositiveValue,
228 bool bYError /* = true */ )
230 Reference< chart2::data::XLabeledDataSequence > xResult;
231 if( !xDataSource.is())
232 return xResult;
234 OUString aRole;
235 Reference< chart2::data::XLabeledDataSequence > xLSeq(
236 lcl_getErrorBarLabeledSequence( xDataSource, bPositiveValue, bYError, aRole ));
237 if( xLSeq.is())
238 xResult.set( xLSeq );
240 return xResult;
243 // static
244 Reference< chart2::data::XDataSequence > StatisticsHelper::getErrorDataSequenceFromDataSource(
245 const Reference< chart2::data::XDataSource > & xDataSource,
246 bool bPositiveValue,
247 bool bYError /* = true */ )
249 Reference< chart2::data::XLabeledDataSequence > xLSeq(
250 StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
251 xDataSource, bPositiveValue,
252 bYError ));
253 if( !xLSeq.is())
254 return Reference< chart2::data::XDataSequence >();
256 return xLSeq->getValues();
259 // static
260 double StatisticsHelper::getErrorFromDataSource(
261 const Reference< chart2::data::XDataSource > & xDataSource,
262 sal_Int32 nIndex,
263 bool bPositiveValue,
264 bool bYError /* = true */ )
266 double fResult = 0.0;
267 ::rtl::math::setNan( & fResult );
269 Reference< chart2::data::XDataSequence > xValues(
270 StatisticsHelper::getErrorDataSequenceFromDataSource( xDataSource, bPositiveValue, bYError ));
272 Reference< chart2::data::XNumericalDataSequence > xNumValues( xValues, uno::UNO_QUERY );
273 if( xNumValues.is())
275 Sequence< double > aData( xNumValues->getNumericalData());
276 if( nIndex < aData.getLength())
277 fResult = aData[nIndex];
279 else if( xValues.is())
281 Sequence< uno::Any > aData( xValues->getData());
282 if( nIndex < aData.getLength())
283 aData[nIndex] >>= fResult;
286 return fResult;
289 // static
290 void StatisticsHelper::setErrorDataSequence(
291 const Reference< chart2::data::XDataSource > & xDataSource,
292 const Reference< chart2::data::XDataProvider > & xDataProvider,
293 const OUString & rNewRange,
294 bool bPositiveValue,
295 bool bYError /* = true */,
296 OUString * pXMLRange /* = 0 */ )
298 Reference< chart2::data::XDataSink > xDataSink( xDataSource, uno::UNO_QUERY );
299 if( ! ( xDataSink.is() && xDataProvider.is()))
300 return;
302 OUString aRole;
303 Reference< chart2::data::XLabeledDataSequence > xLSeq(
304 lcl_getErrorBarLabeledSequence( xDataSource, bPositiveValue, bYError, aRole ));
305 Reference< chart2::data::XDataSequence > xNewSequence(
306 xDataProvider->createDataSequenceByRangeRepresentation( rNewRange ));
307 if( xNewSequence.is())
309 if( pXMLRange )
310 lcl_setXMLRangePropertyAtDataSequence( xNewSequence, *pXMLRange );
311 if( xLSeq.is())
313 lcl_setRole( xNewSequence, aRole );
314 xLSeq->setValues( xNewSequence );
316 else
317 lcl_addSequenceToDataSource( xDataSource, xNewSequence, aRole );
321 // static
322 Reference< beans::XPropertySet > StatisticsHelper::addErrorBars(
323 const Reference< chart2::XDataSeries > & xDataSeries,
324 const Reference< uno::XComponentContext > & xContext,
325 sal_Int32 nStyle,
326 bool bYError /* = true */ )
328 Reference< beans::XPropertySet > xErrorBar;
329 Reference< beans::XPropertySet > xSeriesProp( xDataSeries, uno::UNO_QUERY );
330 if( !xSeriesProp.is())
331 return xErrorBar;
333 const OUString aPropName( bYError ? C2U("ErrorBarY") : C2U("ErrorBarX"));
334 if( !( xSeriesProp->getPropertyValue( aPropName ) >>= xErrorBar ) ||
335 !xErrorBar.is())
337 xErrorBar.set( createErrorBar( xContext ));
340 OSL_ASSERT( xErrorBar.is());
341 if( xErrorBar.is())
343 xErrorBar->setPropertyValue( C2U("ErrorBarStyle"), uno::makeAny( nStyle ));
346 xSeriesProp->setPropertyValue( aPropName, uno::makeAny( xErrorBar ));
348 return xErrorBar;
351 // static
352 Reference< beans::XPropertySet > StatisticsHelper::getErrorBars(
353 const Reference< chart2::XDataSeries > & xDataSeries,
354 bool bYError /* = true */ )
356 Reference< beans::XPropertySet > xSeriesProp( xDataSeries, uno::UNO_QUERY );
357 Reference< beans::XPropertySet > xErrorBar;
358 const OUString aPropName( bYError ? C2U("ErrorBarY") : C2U("ErrorBarX"));
360 if ( xSeriesProp.is())
361 xSeriesProp->getPropertyValue( aPropName ) >>= xErrorBar;
363 return xErrorBar;
366 // static
367 bool StatisticsHelper::hasErrorBars(
368 const Reference< chart2::XDataSeries > & xDataSeries,
369 bool bYError /* = true */ )
371 Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError ));
372 sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE;
374 return ( xErrorBar.is() &&
375 ( xErrorBar->getPropertyValue( C2U("ErrorBarStyle")) >>= nStyle ) &&
376 nStyle != ::com::sun::star::chart::ErrorBarStyle::NONE );
379 // static
380 void StatisticsHelper::removeErrorBars(
381 const Reference< chart2::XDataSeries > & xDataSeries,
382 bool bYError /* = true */ )
384 Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError ));
385 if ( xErrorBar.is())
386 xErrorBar->setPropertyValue( C2U("ErrorBarStyle"), uno::makeAny(
387 ::com::sun::star::chart::ErrorBarStyle::NONE ));
390 // static
391 bool StatisticsHelper::usesErrorBarRanges(
392 const Reference< chart2::XDataSeries > & xDataSeries,
393 bool bYError /* = true */ )
395 Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError ));
396 sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE;
398 return ( xErrorBar.is() &&
399 ( xErrorBar->getPropertyValue( C2U("ErrorBarStyle")) >>= nStyle ) &&
400 nStyle == ::com::sun::star::chart::ErrorBarStyle::FROM_DATA );
403 } // namespace chart