1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <DataSeries.hxx>
22 #include <DataSeriesHelper.hxx>
23 #include <ErrorBar.hxx>
24 #include <unonames.hxx>
26 #include <rtl/ustrbuf.hxx>
27 #include <comphelper/processfactory.hxx>
28 #include <com/sun/star/chart2/XDataSeries.hpp>
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 <comphelper/diagnose_ex.hxx>
39 using ::com::sun::star::uno::Sequence
;
40 using ::com::sun::star::uno::Reference
;
41 using namespace ::com::sun::star
;
46 double lcl_getVariance( const Sequence
< double > & rData
, sal_Int32
& rOutValidCount
)
48 const sal_Int32 nCount
= rData
.getLength();
49 rOutValidCount
= nCount
;
52 double fQuadSum
= 0.0;
54 for( sal_Int32 i
= 0; i
< nCount
; ++i
)
56 const double fData
= rData
[i
];
57 if( std::isnan( fData
))
62 fQuadSum
+= fData
* fData
;
66 if( rOutValidCount
== 0 )
67 return std::numeric_limits
<double>::quiet_NaN();
69 const double fN
= static_cast< double >( rOutValidCount
);
70 return (fQuadSum
- fSum
*fSum
/fN
) / fN
;
73 uno::Reference
< chart2::data::XLabeledDataSequence
> lcl_getErrorBarLabeledSequence(
74 const Reference
< chart2::data::XDataSource
> & xDataSource
,
75 bool bPositiveValue
, bool bYError
,
76 OUString
& rOutRoleNameUsed
)
78 OUStringBuffer
aRole( "error-bars-");
84 OUString aPlainRole
= aRole
.makeStringAndClear();
85 aRole
.append( aPlainRole
+ "-" );
88 aRole
.append( "positive" );
90 aRole
.append( "negative" );
92 OUString aLongRole
= aRole
.makeStringAndClear();
93 uno::Reference
< chart2::data::XLabeledDataSequence
> xLSeq
=
94 ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource
, aLongRole
);
95 // try role without "-negative" or "-positive" postfix
97 rOutRoleNameUsed
= aLongRole
;
100 xLSeq
= ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource
, aPlainRole
);
102 rOutRoleNameUsed
= aPlainRole
;
104 rOutRoleNameUsed
= aLongRole
;
111 const Reference
< chart2::data::XDataSequence
> & xNewSequence
,
112 const OUString
& rRole
)
114 Reference
< beans::XPropertySet
> xSeqProp( xNewSequence
, uno::UNO_QUERY
);
116 xSeqProp
->setPropertyValue( "Role", uno::Any( rRole
));
119 void lcl_addSequenceToDataSource(
120 const Reference
< chart2::data::XDataSource
> & xDataSource
,
121 const Reference
< chart2::data::XDataSequence
> & xNewSequence
,
122 const OUString
& rRole
)
124 Reference
< chart2::data::XDataSink
> xSink( xDataSource
, uno::UNO_QUERY
);
125 Reference
< uno::XComponentContext
> xContext( comphelper::getProcessComponentContext() );
129 Reference
< chart2::data::XLabeledDataSequence
> xLSeq( chart2::data::LabeledDataSequence::create(xContext
), uno::UNO_QUERY_THROW
);
131 lcl_setRole( xNewSequence
, rRole
);
132 xLSeq
->setValues( xNewSequence
);
133 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aSequences(
134 xDataSource
->getDataSequences());
135 aSequences
.realloc( aSequences
.getLength() + 1 );
136 auto pSequences
= aSequences
.getArray();
137 pSequences
[ aSequences
.getLength() - 1 ] = xLSeq
;
138 xSink
->setData( aSequences
);
141 void lcl_setXMLRangePropertyAtDataSequence(
142 const Reference
< chart2::data::XDataSequence
> & xDataSequence
,
143 const OUString
& rXMLRange
)
147 static constexpr OUString
aXMLRangePropName( u
"CachedXMLRange"_ustr
);
148 Reference
< beans::XPropertySet
> xProp( xDataSequence
, uno::UNO_QUERY_THROW
);
149 Reference
< beans::XPropertySetInfo
> xInfo( xProp
->getPropertySetInfo());
150 if( xInfo
.is() && xInfo
->hasPropertyByName( aXMLRangePropName
))
151 xProp
->setPropertyValue( aXMLRangePropName
, uno::Any( rXMLRange
));
153 catch( const uno::Exception
& )
155 DBG_UNHANDLED_EXCEPTION("chart2");
159 } // anonymous namespace
164 double StatisticsHelper::getVariance(
165 const Sequence
< double > & rData
)
168 return lcl_getVariance( rData
, nValCount
);
171 double StatisticsHelper::getStandardDeviation( const Sequence
< double > & rData
)
173 double fResult
= getVariance( rData
);
174 if( ! std::isnan( fResult
))
175 fResult
= sqrt( fResult
);
180 double StatisticsHelper::getStandardError( const Sequence
< double > & rData
)
183 double fVar
= lcl_getVariance( rData
, nValCount
);
185 if( nValCount
== 0 || std::isnan( fVar
))
186 return std::numeric_limits
<double>::quiet_NaN();
187 // standard-deviation / sqrt(n)
188 return sqrt( fVar
) / sqrt( double(nValCount
) );
191 uno::Reference
< chart2::data::XLabeledDataSequence
> StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
192 const Reference
< chart2::data::XDataSource
> & xDataSource
,
194 bool bYError
/* = true */ )
196 uno::Reference
< chart2::data::XLabeledDataSequence
> xResult
;
197 if( !xDataSource
.is())
201 uno::Reference
< chart2::data::XLabeledDataSequence
> xLSeq
=
202 lcl_getErrorBarLabeledSequence( xDataSource
, bPositiveValue
, bYError
, aRole
);
209 Reference
< chart2::data::XDataSequence
> StatisticsHelper::getErrorDataSequenceFromDataSource(
210 const Reference
< chart2::data::XDataSource
> & xDataSource
,
212 bool bYError
/* = true */ )
214 uno::Reference
< chart2::data::XLabeledDataSequence
> xLSeq
=
215 StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
216 xDataSource
, bPositiveValue
,
219 return Reference
< chart2::data::XDataSequence
>();
221 return xLSeq
->getValues();
224 double StatisticsHelper::getErrorFromDataSource(
225 const Reference
< chart2::data::XDataSource
> & xDataSource
,
228 bool bYError
/* = true */ )
230 double fResult
= std::numeric_limits
<double>::quiet_NaN();
232 Reference
< chart2::data::XDataSequence
> xValues(
233 StatisticsHelper::getErrorDataSequenceFromDataSource( xDataSource
, bPositiveValue
, bYError
));
235 Reference
< chart2::data::XNumericalDataSequence
> xNumValues( xValues
, uno::UNO_QUERY
);
238 Sequence
< double > aData( xNumValues
->getNumericalData());
239 if( nIndex
< aData
.getLength())
240 fResult
= aData
[nIndex
];
242 else if( xValues
.is())
244 Sequence
< uno::Any
> aData( xValues
->getData());
245 if( nIndex
< aData
.getLength())
246 aData
[nIndex
] >>= fResult
;
252 void StatisticsHelper::setErrorDataSequence(
253 const Reference
< chart2::data::XDataSource
> & xDataSource
,
254 const Reference
< chart2::data::XDataProvider
> & xDataProvider
,
255 const OUString
& rNewRange
,
257 bool bYError
/* = true */,
258 OUString
const * pXMLRange
/* = 0 */ )
260 Reference
< chart2::data::XDataSink
> xDataSink( xDataSource
, uno::UNO_QUERY
);
261 if( ! ( xDataSink
.is() && xDataProvider
.is()))
265 Reference
< chart2::data::XLabeledDataSequence
> xLSeq(
266 lcl_getErrorBarLabeledSequence( xDataSource
, bPositiveValue
, bYError
, aRole
));
267 Reference
< chart2::data::XDataSequence
> xNewSequence(
268 xDataProvider
->createDataSequenceByRangeRepresentation( rNewRange
));
269 if( xNewSequence
.is())
272 lcl_setXMLRangePropertyAtDataSequence( xNewSequence
, *pXMLRange
);
275 lcl_setRole( xNewSequence
, aRole
);
276 xLSeq
->setValues( xNewSequence
);
279 lcl_addSequenceToDataSource( xDataSource
, xNewSequence
, aRole
);
283 Reference
< beans::XPropertySet
> StatisticsHelper::addErrorBars(
284 const rtl::Reference
< DataSeries
> & xDataSeries
,
286 bool bYError
/* = true */ )
288 Reference
< beans::XPropertySet
> xErrorBar
;
289 if( !xDataSeries
.is())
292 const OUString
aPropName(
293 bYError
? CHART_UNONAME_ERRORBAR_Y
: CHART_UNONAME_ERRORBAR_X
);
294 if( !( xDataSeries
->getPropertyValue( aPropName
) >>= xErrorBar
) ||
297 xErrorBar
.set( new ErrorBar
);
300 OSL_ASSERT( xErrorBar
.is());
303 xErrorBar
->setPropertyValue( "ErrorBarStyle", uno::Any( nStyle
));
306 xDataSeries
->setPropertyValue( aPropName
, uno::Any( xErrorBar
));
311 Reference
< beans::XPropertySet
> StatisticsHelper::getErrorBars(
312 const rtl::Reference
< DataSeries
> & xDataSeries
,
313 bool bYError
/* = true */ )
315 Reference
< beans::XPropertySet
> xErrorBar
;
316 const OUString
aPropName(
317 bYError
? CHART_UNONAME_ERRORBAR_Y
: CHART_UNONAME_ERRORBAR_X
);
319 if ( xDataSeries
.is())
320 xDataSeries
->getPropertyValue( aPropName
) >>= xErrorBar
;
325 bool StatisticsHelper::hasErrorBars(
326 const rtl::Reference
< DataSeries
> & xDataSeries
,
327 bool bYError
/* = true */ )
329 Reference
< beans::XPropertySet
> xErrorBar( getErrorBars( xDataSeries
, bYError
));
330 sal_Int32 nStyle
= css::chart::ErrorBarStyle::NONE
;
332 return ( xErrorBar
.is() &&
333 ( xErrorBar
->getPropertyValue( "ErrorBarStyle") >>= nStyle
) &&
334 nStyle
!= css::chart::ErrorBarStyle::NONE
);
337 void StatisticsHelper::removeErrorBars(
338 const rtl::Reference
< DataSeries
> & xDataSeries
,
339 bool bYError
/* = true */ )
341 Reference
< beans::XPropertySet
> xErrorBar( getErrorBars( xDataSeries
, bYError
));
343 xErrorBar
->setPropertyValue( "ErrorBarStyle", uno::Any(
344 css::chart::ErrorBarStyle::NONE
));
347 bool StatisticsHelper::usesErrorBarRanges(
348 const rtl::Reference
< DataSeries
> & xDataSeries
,
349 bool bYError
/* = true */ )
351 Reference
< beans::XPropertySet
> xErrorBar( getErrorBars( xDataSeries
, bYError
));
352 sal_Int32 nStyle
= css::chart::ErrorBarStyle::NONE
;
354 return ( xErrorBar
.is() &&
355 ( xErrorBar
->getPropertyValue( "ErrorBarStyle") >>= nStyle
) &&
356 nStyle
== css::chart::ErrorBarStyle::FROM_DATA
);
361 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */