update dev300-m58
[ooovba.git] / chart2 / source / tools / StatisticsHelper.cxx
blob21dc62cd3286def30ce1e66ba332462c72eaf363
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: StatisticsHelper.cxx,v $
10 * $Revision: 1.6 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_chart2.hxx"
33 #include "StatisticsHelper.hxx"
34 #include "DataSeriesHelper.hxx"
35 #include "ErrorBar.hxx"
36 #include "macros.hxx"
38 #include <rtl/math.hxx>
39 #include <rtl/ustrbuf.hxx>
40 #include <comphelper/processfactory.hxx>
42 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
43 #include <com/sun/star/chart2/data/XLabeledDataSequence.hpp>
44 #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
45 #include <com/sun/star/chart2/data/XDataSink.hpp>
46 #include <com/sun/star/chart/ErrorBarStyle.hpp>
48 using ::com::sun::star::uno::Sequence;
49 using ::com::sun::star::uno::Reference;
50 using ::rtl::OUString;
51 using ::rtl::OUStringBuffer;
52 using namespace ::com::sun::star;
54 namespace
57 double lcl_getVariance( const Sequence< double > & rData, sal_Int32 & rOutValidCount,
58 bool bUnbiasedEstimator )
60 const sal_Int32 nCount = rData.getLength();
61 rOutValidCount = nCount;
63 double fSum = 0.0;
64 double fQuadSum = 0.0;
66 for( sal_Int32 i = 0; i < nCount; ++i )
68 const double fData = rData[i];
69 if( ::rtl::math::isNan( fData ))
70 --rOutValidCount;
71 else
73 fSum += fData;
74 fQuadSum += fData * fData;
78 double fResult;
79 if( rOutValidCount == 0 )
80 ::rtl::math::setNan( & fResult );
81 else
83 const double fN = static_cast< double >( rOutValidCount );
84 if( bUnbiasedEstimator )
85 fResult = (fQuadSum - fSum*fSum/fN) / (fN - 1);
86 else
87 fResult = (fQuadSum - fSum*fSum/fN) / fN;
90 return fResult;
93 Reference< chart2::data::XLabeledDataSequence > lcl_getErrorBarLabeledSequence(
94 const Reference< chart2::data::XDataSource > & xDataSource,
95 bool bPositiveValue, bool bYError,
96 OUString & rOutRoleNameUsed )
98 OUStringBuffer aRole( C2U("error-bars-"));
99 if( bYError )
100 aRole.append( sal_Unicode( 'y' ));
101 else
102 aRole.append( sal_Unicode( 'x' ));
104 OUString aPlainRole = aRole.makeStringAndClear();
105 aRole.append( aPlainRole );
106 aRole.append( sal_Unicode( '-' ));
108 if( bPositiveValue )
109 aRole = aRole.appendAscii( "positive" );
110 else
111 aRole = aRole.appendAscii( "negative" );
113 OUString aLongRole = aRole.makeStringAndClear();
114 Reference< chart2::data::XLabeledDataSequence > xLSeq(
115 ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource, aLongRole ));
116 // try role without "-negative" or "-positive" postfix
117 if( xLSeq.is())
118 rOutRoleNameUsed = aLongRole;
119 else
121 xLSeq.set( ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource, aPlainRole ));
122 if( xLSeq.is())
123 rOutRoleNameUsed = aPlainRole;
124 else
125 rOutRoleNameUsed = aLongRole;
128 return xLSeq;
131 void lcl_setRole(
132 const Reference< chart2::data::XDataSequence > & xNewSequence,
133 const OUString & rRole )
135 Reference< beans::XPropertySet > xSeqProp( xNewSequence, uno::UNO_QUERY );
136 if( xSeqProp.is())
137 xSeqProp->setPropertyValue( C2U("Role"), uno::makeAny( rRole ));
140 void lcl_addSequenceToDataSource(
141 const Reference< chart2::data::XDataSource > & xDataSource,
142 const Reference< chart2::data::XDataSequence > & xNewSequence,
143 const OUString & rRole )
145 Reference< chart2::data::XDataSink > xSink( xDataSource, uno::UNO_QUERY );
146 Reference< lang::XMultiServiceFactory > xFact( comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW );
147 if( ! ( xFact.is() && xSink.is() ))
148 return;
150 Reference< chart2::data::XLabeledDataSequence > xLSeq(
151 xFact->createInstance( C2U("com.sun.star.chart2.data.LabeledDataSequence")), uno::UNO_QUERY );
152 if( xLSeq.is())
154 lcl_setRole( xNewSequence, rRole );
155 xLSeq->setValues( xNewSequence );
156 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences(
157 xDataSource->getDataSequences());
158 aSequences.realloc( aSequences.getLength() + 1 );
159 aSequences[ aSequences.getLength() - 1 ] = xLSeq;
160 xSink->setData( aSequences );
164 void lcl_setXMLRangePropertyAtDataSequence(
165 const Reference< chart2::data::XDataSequence > & xDataSequence,
166 const OUString & rXMLRange )
170 const OUString aXMLRangePropName( C2U( "CachedXMLRange" ));
171 Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY_THROW );
172 Reference< beans::XPropertySetInfo > xInfo( xProp->getPropertySetInfo());
173 if( xInfo.is() && xInfo->hasPropertyByName( aXMLRangePropName ))
174 xProp->setPropertyValue( aXMLRangePropName, uno::makeAny( rXMLRange ));
176 catch( const uno::Exception & ex )
178 ASSERT_EXCEPTION( ex );
182 } // anonymous namespace
184 namespace chart
187 // static
188 double StatisticsHelper::getVariance(
189 const Sequence< double > & rData,
190 bool bUnbiasedEstimator /* = false */ )
192 sal_Int32 nValCount;
193 return lcl_getVariance( rData, nValCount, bUnbiasedEstimator );
196 // static
197 double StatisticsHelper::getStandardDeviation( const Sequence< double > & rData )
199 double fResult = getVariance( rData );
200 if( ! ::rtl::math::isNan( fResult ))
201 fResult = sqrt( fResult );
203 return fResult;
206 // static
207 double StatisticsHelper::getStandardError( const Sequence< double > & rData )
209 sal_Int32 nValCount;
210 double fVar = lcl_getVariance( rData, nValCount, false );
211 double fResult;
213 if( nValCount == 0 ||
214 ::rtl::math::isNan( fVar ))
216 ::rtl::math::setNan( & fResult );
218 else
220 // standard-deviation / sqrt(n)
221 fResult = sqrt( fVar ) / sqrt( double(nValCount) );
224 return fResult;
227 // static
228 Reference< chart2::data::XLabeledDataSequence > StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
229 const Reference< chart2::data::XDataSource > & xDataSource,
230 bool bPositiveValue,
231 bool bYError /* = true */ )
233 Reference< chart2::data::XLabeledDataSequence > xResult;
234 if( !xDataSource.is())
235 return xResult;
237 OUString aRole;
238 Reference< chart2::data::XLabeledDataSequence > xLSeq(
239 lcl_getErrorBarLabeledSequence( xDataSource, bPositiveValue, bYError, aRole ));
240 if( xLSeq.is())
241 xResult.set( xLSeq );
243 return xResult;
246 // static
247 Reference< chart2::data::XDataSequence > StatisticsHelper::getErrorDataSequenceFromDataSource(
248 const Reference< chart2::data::XDataSource > & xDataSource,
249 bool bPositiveValue,
250 bool bYError /* = true */ )
252 Reference< chart2::data::XLabeledDataSequence > xLSeq(
253 StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
254 xDataSource, bPositiveValue,
255 bYError ));
256 if( !xLSeq.is())
257 return Reference< chart2::data::XDataSequence >();
259 return xLSeq->getValues();
262 // static
263 double StatisticsHelper::getErrorFromDataSource(
264 const Reference< chart2::data::XDataSource > & xDataSource,
265 sal_Int32 nIndex,
266 bool bPositiveValue,
267 bool bYError /* = true */ )
269 double fResult = 0.0;
270 ::rtl::math::setNan( & fResult );
272 Reference< chart2::data::XDataSequence > xValues(
273 StatisticsHelper::getErrorDataSequenceFromDataSource( xDataSource, bPositiveValue, bYError ));
275 Reference< chart2::data::XNumericalDataSequence > xNumValues( xValues, uno::UNO_QUERY );
276 if( xNumValues.is())
278 Sequence< double > aData( xNumValues->getNumericalData());
279 if( nIndex < aData.getLength())
280 fResult = aData[nIndex];
282 else if( xValues.is())
284 Sequence< uno::Any > aData( xValues->getData());
285 if( nIndex < aData.getLength())
286 aData[nIndex] >>= fResult;
289 return fResult;
292 // static
293 void StatisticsHelper::setErrorDataSequence(
294 const Reference< chart2::data::XDataSource > & xDataSource,
295 const Reference< chart2::data::XDataProvider > & xDataProvider,
296 const OUString & rNewRange,
297 bool bPositiveValue,
298 bool bYError /* = true */,
299 OUString * pXMLRange /* = 0 */ )
301 Reference< chart2::data::XDataSink > xDataSink( xDataSource, uno::UNO_QUERY );
302 if( ! ( xDataSink.is() && xDataProvider.is()))
303 return;
305 OUString aRole;
306 Reference< chart2::data::XLabeledDataSequence > xLSeq(
307 lcl_getErrorBarLabeledSequence( xDataSource, bPositiveValue, bYError, aRole ));
308 Reference< chart2::data::XDataSequence > xNewSequence(
309 xDataProvider->createDataSequenceByRangeRepresentation( rNewRange ));
310 if( xNewSequence.is())
312 if( pXMLRange )
313 lcl_setXMLRangePropertyAtDataSequence( xNewSequence, *pXMLRange );
314 if( xLSeq.is())
316 lcl_setRole( xNewSequence, aRole );
317 xLSeq->setValues( xNewSequence );
319 else
320 lcl_addSequenceToDataSource( xDataSource, xNewSequence, aRole );
324 // static
325 Reference< beans::XPropertySet > StatisticsHelper::addErrorBars(
326 const Reference< chart2::XDataSeries > & xDataSeries,
327 const Reference< uno::XComponentContext > & xContext,
328 sal_Int32 nStyle,
329 bool bYError /* = true */ )
331 Reference< beans::XPropertySet > xErrorBar;
332 Reference< beans::XPropertySet > xSeriesProp( xDataSeries, uno::UNO_QUERY );
333 if( !xSeriesProp.is())
334 return xErrorBar;
336 const OUString aPropName( bYError ? C2U("ErrorBarY") : C2U("ErrorBarX"));
337 if( !( xSeriesProp->getPropertyValue( aPropName ) >>= xErrorBar ) ||
338 !xErrorBar.is())
340 xErrorBar.set( createErrorBar( xContext ));
343 OSL_ASSERT( xErrorBar.is());
344 if( xErrorBar.is())
346 xErrorBar->setPropertyValue( C2U("ErrorBarStyle"), uno::makeAny( nStyle ));
349 xSeriesProp->setPropertyValue( aPropName, uno::makeAny( xErrorBar ));
351 return xErrorBar;
354 // static
355 Reference< beans::XPropertySet > StatisticsHelper::getErrorBars(
356 const Reference< chart2::XDataSeries > & xDataSeries,
357 bool bYError /* = true */ )
359 Reference< beans::XPropertySet > xSeriesProp( xDataSeries, uno::UNO_QUERY );
360 Reference< beans::XPropertySet > xErrorBar;
361 const OUString aPropName( bYError ? C2U("ErrorBarY") : C2U("ErrorBarX"));
363 if ( xSeriesProp.is())
364 xSeriesProp->getPropertyValue( aPropName ) >>= xErrorBar;
366 return xErrorBar;
369 // static
370 bool StatisticsHelper::hasErrorBars(
371 const Reference< chart2::XDataSeries > & xDataSeries,
372 bool bYError /* = true */ )
374 Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError ));
375 sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE;
377 return ( xErrorBar.is() &&
378 ( xErrorBar->getPropertyValue( C2U("ErrorBarStyle")) >>= nStyle ) &&
379 nStyle != ::com::sun::star::chart::ErrorBarStyle::NONE );
382 // static
383 void StatisticsHelper::removeErrorBars(
384 const Reference< chart2::XDataSeries > & xDataSeries,
385 bool bYError /* = true */ )
387 Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError ));
388 if ( xErrorBar.is())
389 xErrorBar->setPropertyValue( C2U("ErrorBarStyle"), uno::makeAny(
390 ::com::sun::star::chart::ErrorBarStyle::NONE ));
393 // static
394 bool StatisticsHelper::usesErrorBarRanges(
395 const Reference< chart2::XDataSeries > & xDataSeries,
396 bool bYError /* = true */ )
398 Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError ));
399 sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE;
401 return ( xErrorBar.is() &&
402 ( xErrorBar->getPropertyValue( C2U("ErrorBarStyle")) >>= nStyle ) &&
403 nStyle == ::com::sun::star::chart::ErrorBarStyle::FROM_DATA );
406 } // namespace chart