WorkspaceOpOverloads.cpp 20.5 KB
Newer Older
1
2
3
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
4
5
6
7
8
9
#include "MantidAPI/WorkspaceOpOverloads.h"
#include "MantidAPI/Algorithm.h"
#include "MantidAPI/AlgorithmManager.h"
#include "MantidKernel/Property.h"
#include "MantidKernel/Exception.h"
#include "MantidAPI/IWorkspaceProperty.h"
Nick Draper's avatar
re #75  
Nick Draper committed
10
#include "MantidAPI/WorkspaceFactory.h"
11
#include "MantidAPI/SpectraAxis.h"
12
#include <numeric>
13
#include "MantidAPI/IMDWorkspace.h"
14
#include "MantidAPI/IMDHistoWorkspace.h"
15
16
17
18

namespace Mantid
{
namespace API
19
{
20
21
namespace OperatorOverloads
{
22

23
24
25
26
27
28
29
  /** Performs a binary operation on two workspaces
   *  @param algorithmName :: The name of the binary operation to perform
   *  @param lhs :: left hand side workspace shared pointer
   *  @param rhs :: right hand side workspace shared pointer
   *  @param lhsAsOutput :: If true, indicates that the lhs input is the same workspace as the output one
   *  @param child :: If true the algorithm is run as a child
   *  @param name :: If child is true and this is not an inplace operation then this name is used as output
30
   *  @param rethrow :: A flag indicating whether to rethrow exceptions
31
32
   *  @return The result in a workspace shared pointer
   */
33
34
35
  template<typename LHSType, typename RHSType, typename ResultType>
  ResultType executeBinaryOperation(const std::string & algorithmName, const LHSType lhs, const RHSType rhs, bool lhsAsOutput,
      bool child, const std::string &name, bool rethrow)
36
  {
37
38
39
40
41
42
    IAlgorithm_sptr alg = AlgorithmManager::Instance().createUnmanaged(algorithmName);
    alg->setChild(child);
    alg->setRethrows(rethrow);
    alg->initialize();

    if( child )
43
    {
44
45
      alg->setProperty<LHSType>("LHSWorkspace",lhs);
      alg->setProperty<RHSType>("RHSWorkspace",rhs);
46
47
48
49
50
      // Have to set a text name for the output workspace if the algorithm is a child even
      // though it will not be used.
      alg->setPropertyValue("OutputWorkspace","��NotApplicable");
      if( lhsAsOutput )
      {
51
        alg->setProperty<LHSType>("OutputWorkspace",lhs);
52
      }
53
    }
54
    // If this is not a child algorithm then we need names for the properties
55
56
    else
    {
57
58
59
60
61
62
63
64
65
66
      alg->setPropertyValue("LHSWorkspace",lhs->getName());
      alg->setPropertyValue("RHSWorkspace",rhs->getName());
      if( lhsAsOutput )
      {
        alg->setPropertyValue("OutputWorkspace",lhs->getName());
      }
      else
      {
        alg->setPropertyValue("OutputWorkspace",name);
      }
67
    }
68

69
    alg->execute();
70

71
    if (alg->isExecuted())
72
    {
73
      // Get the output workspace property
74
      if (child)
75
76
77
78
79
      {
        return alg->getProperty("OutputWorkspace");
      }
      else
      {
80
81
82
        API::Workspace_sptr result = API::AnalysisDataService::Instance().retrieve(
            alg->getPropertyValue("OutputWorkspace"));
        return boost::dynamic_pointer_cast<typename ResultType::element_type>(result);
83
      }
84
85
86
    }
    else
    {
87
88
      std::string message = "Error while executing operation: " + algorithmName;
      throw std::runtime_error(message);
89
    }
90
91
92
93
94

    throw Kernel::Exception::NotFoundError("Required output workspace property not found on sub algorithm" ,"OutputWorkspace");

    //Horendous code inclusion to satisfy compilers that all code paths return a value
    // in reality the above code should either throw or return successfully.
95
    return ResultType();
96
97
  }

98
99
100
101
102
103
104
105
  template DLLExport MatrixWorkspace_sptr executeBinaryOperation(const std::string &, const MatrixWorkspace_sptr, const MatrixWorkspace_sptr, bool,
      bool, const std::string &, bool);
  template DLLExport WorkspaceGroup_sptr executeBinaryOperation(const std::string &, const WorkspaceGroup_sptr, const WorkspaceGroup_sptr, bool,
      bool, const std::string &, bool);
  template DLLExport WorkspaceGroup_sptr executeBinaryOperation(const std::string &, const WorkspaceGroup_sptr, const MatrixWorkspace_sptr, bool,
      bool, const std::string &, bool);
  template DLLExport WorkspaceGroup_sptr executeBinaryOperation(const std::string &, const MatrixWorkspace_sptr, const WorkspaceGroup_sptr, bool,
      bool, const std::string &, bool);
106

107
108
109
110
111
112
113
114
115
116
117
118
  template DLLExport IMDWorkspace_sptr executeBinaryOperation(const std::string &, const IMDWorkspace_sptr, const IMDWorkspace_sptr, bool,
      bool, const std::string &, bool);
  template DLLExport WorkspaceGroup_sptr executeBinaryOperation(const std::string &, const WorkspaceGroup_sptr, const IMDWorkspace_sptr, bool,
      bool, const std::string &, bool);
  template DLLExport WorkspaceGroup_sptr executeBinaryOperation(const std::string &, const IMDWorkspace_sptr, const WorkspaceGroup_sptr, bool,
      bool, const std::string &, bool);

  template DLLExport IMDWorkspace_sptr executeBinaryOperation(const std::string &, const IMDWorkspace_sptr, const MatrixWorkspace_sptr, bool,
      bool, const std::string &, bool);
  template DLLExport IMDWorkspace_sptr executeBinaryOperation(const std::string &, const MatrixWorkspace_sptr, const IMDWorkspace_sptr, bool,
      bool, const std::string &, bool);

119
120
121
122
123
124
125
  template DLLExport IMDHistoWorkspace_sptr executeBinaryOperation(const std::string &, const IMDHistoWorkspace_sptr, const IMDHistoWorkspace_sptr, bool,
      bool, const std::string &, bool);
  template DLLExport IMDHistoWorkspace_sptr executeBinaryOperation(const std::string &, const IMDHistoWorkspace_sptr, const MatrixWorkspace_sptr, bool,
      bool, const std::string &, bool);
  template DLLExport IMDHistoWorkspace_sptr executeBinaryOperation(const std::string &, const MatrixWorkspace_sptr, const IMDHistoWorkspace_sptr, bool,
      bool, const std::string &, bool);

126
127
128
129
130
131
132
133
} // namespace OperatorOverloads



/** Performs a comparison operation on two workspaces, using the CheckWorkspacesMatch algorithm
 *
 *  @param lhs :: left hand side workspace shared pointer
 *  @param rhs :: right hand side workspace shared pointer
134
 *  @param tolerance :: acceptable difference for floating point numbers
135
136
 *  @return bool, true if workspaces match
 */
137
bool equals(const MatrixWorkspace_sptr lhs, const MatrixWorkspace_sptr rhs, double tolerance)
138
139
140
141
142
143
144
{
  IAlgorithm_sptr alg = AlgorithmManager::Instance().createUnmanaged("CheckWorkspacesMatch");
  alg->setChild(true);
  alg->setRethrows(false);
  alg->initialize();
  alg->setProperty<MatrixWorkspace_sptr>("Workspace1",lhs);
  alg->setProperty<MatrixWorkspace_sptr>("Workspace2",rhs);
145
146
  alg->setProperty<MatrixWorkspace_sptr>("Workspace2",rhs);
  alg->setProperty<double>("Tolerance", tolerance);
147
148
149
150
151
152
  // Rest: use default

  alg->execute();
  if (alg->isExecuted())
  {
    return (alg->getPropertyValue("Result") == "Success!");
153
154
155
  }
  else
  {
156
    std::string message = "Error while executing operation: CheckWorkspacesMatch";
157
    throw std::runtime_error(message);
158
  }
159
160
  return false;
}
161
162
163



164

165
/** Creates a temporary single value workspace the error is set to zero
166
 *  @param rhsValue :: the value to use
167
 *  @return The value in a workspace shared pointer
168
 */
169
static MatrixWorkspace_sptr createWorkspaceSingleValue(const double& rhsValue)
170
{
171
  MatrixWorkspace_sptr retVal = WorkspaceFactory::Instance().create("WorkspaceSingleValue",1,1,1);
172
173
174
175
  retVal->dataY(0)[0]=rhsValue;

  return retVal;
}
176

177
178
using OperatorOverloads::executeBinaryOperation;

179
/** Adds two workspaces
180
 *  @param lhs :: left hand side workspace shared pointer
181
182
 *  @param rhs :: right hand side workspace shared pointer
 *  @return The result in a workspace shared pointer
183
184
185
 */
MatrixWorkspace_sptr operator+(const MatrixWorkspace_sptr lhs, const MatrixWorkspace_sptr rhs)
{
186
  return executeBinaryOperation<MatrixWorkspace_sptr,MatrixWorkspace_sptr,MatrixWorkspace_sptr>("Plus",lhs,rhs);
187
188
189
}

/** Adds a workspace to a single value
190
191
 *  @param lhs ::      left hand side workspace shared pointer
 *  @param rhsValue :: the single value
192
 *  @return The result in a workspace shared pointer
193
194
195
 */
MatrixWorkspace_sptr operator+(const MatrixWorkspace_sptr lhs, const double& rhsValue)
{
196
  return executeBinaryOperation<MatrixWorkspace_sptr,MatrixWorkspace_sptr,MatrixWorkspace_sptr>("Plus",lhs,createWorkspaceSingleValue(rhsValue));
197
198
199
}

/** Subtracts two workspaces
200
 *  @param lhs :: left hand side workspace shared pointer
201
202
 *  @param rhs :: right hand side workspace shared pointer
 *  @return The result in a workspace shared pointer
203
204
205
 */
MatrixWorkspace_sptr operator-(const MatrixWorkspace_sptr lhs, const MatrixWorkspace_sptr rhs)
{
206
  return executeBinaryOperation<MatrixWorkspace_sptr,MatrixWorkspace_sptr,MatrixWorkspace_sptr>("Minus",lhs,rhs);
207
208
209
}

/** Subtracts  a single value from a workspace
210
211
 *  @param lhs ::      left hand side workspace shared pointer
 *  @param rhsValue :: the single value
212
 *  @return The result in a workspace shared pointer
213
214
215
 */
MatrixWorkspace_sptr operator-(const MatrixWorkspace_sptr lhs, const double& rhsValue)
{
216
  return executeBinaryOperation<MatrixWorkspace_sptr,MatrixWorkspace_sptr,MatrixWorkspace_sptr>("Minus",lhs,createWorkspaceSingleValue(rhsValue));
217
218
}

219
/** Subtracts a workspace from a single value
220
221
 *  @param lhsValue :: the single value
 *  @param rhs :: right-hand side workspace shared pointer
222
 *  @return The result in a workspace shared pointer
223
224
225
 */
MatrixWorkspace_sptr operator-(const double& lhsValue, const MatrixWorkspace_sptr rhs)
{
226
  return executeBinaryOperation<MatrixWorkspace_sptr,MatrixWorkspace_sptr,MatrixWorkspace_sptr>("Minus",createWorkspaceSingleValue(lhsValue),rhs);
227
}
228
/** Multiply two workspaces
229
 *  @param lhs :: left hand side workspace shared pointer
230
231
 *  @param rhs :: right hand side workspace shared pointer
 *  @return The result in a workspace shared pointer
232
233
234
 */
MatrixWorkspace_sptr operator*(const MatrixWorkspace_sptr lhs, const MatrixWorkspace_sptr rhs)
{
235
  return executeBinaryOperation<MatrixWorkspace_sptr,MatrixWorkspace_sptr,MatrixWorkspace_sptr>("Multiply",lhs,rhs);
236
237
238
}

/** Multiply a workspace and a single value
239
240
 *  @param lhs ::      left hand side workspace shared pointer
 *  @param rhsValue :: the single value
241
 *  @return The result in a workspace shared pointer
242
243
244
 */
MatrixWorkspace_sptr operator*(const MatrixWorkspace_sptr lhs, const double& rhsValue)
{
245
  return executeBinaryOperation<MatrixWorkspace_sptr,MatrixWorkspace_sptr,MatrixWorkspace_sptr>("Multiply",lhs,createWorkspaceSingleValue(rhsValue));
246
247
}

248
/** Multiply a workspace and a single value. Allows you to write, e.g., 2*workspace.
249
250
 *  @param lhsValue :: the single value
 *  @param rhs ::      workspace shared pointer
251
 *  @return The result in a workspace shared pointer
252
 */
253
MatrixWorkspace_sptr operator*(const double& lhsValue, const MatrixWorkspace_sptr rhs)
254
{
255
  return executeBinaryOperation<MatrixWorkspace_sptr,MatrixWorkspace_sptr,MatrixWorkspace_sptr>("Multiply",createWorkspaceSingleValue(lhsValue),rhs);
256
257
}

258
/** Divide two workspaces
259
 *  @param lhs :: left hand side workspace shared pointer
260
261
 *  @param rhs :: right hand side workspace shared pointer
 *  @return The result in a workspace shared pointer
262
263
264
 */
MatrixWorkspace_sptr operator/(const MatrixWorkspace_sptr lhs, const MatrixWorkspace_sptr rhs)
{
265
  return executeBinaryOperation<MatrixWorkspace_sptr,MatrixWorkspace_sptr,MatrixWorkspace_sptr>("Divide",lhs,rhs);
266
267
268
}

/** Divide a workspace by a single value
269
270
 *  @param lhs ::      left hand side workspace shared pointer
 *  @param rhsValue :: the single value
271
 *  @return The result in a workspace shared pointer
272
273
274
 */
MatrixWorkspace_sptr operator/(const MatrixWorkspace_sptr lhs, const double& rhsValue)
{
275
  return executeBinaryOperation<MatrixWorkspace_sptr,MatrixWorkspace_sptr,MatrixWorkspace_sptr>("Divide",lhs,createWorkspaceSingleValue(rhsValue));
276
}
Nick Draper's avatar
re #75  
Nick Draper committed
277

278
/** Divide a single value and a workspace. Allows you to write, e.g., 2/workspace.
279
280
 *  @param lhsValue :: the single value
 *  @param rhs ::      workspace shared pointer
281
 *  @return The result in a workspace shared pointer
282
283
284
 */
MatrixWorkspace_sptr operator/(const double& lhsValue, const MatrixWorkspace_sptr rhs)
{
285
  return executeBinaryOperation<MatrixWorkspace_sptr,MatrixWorkspace_sptr,MatrixWorkspace_sptr>("Divide",createWorkspaceSingleValue(lhsValue),rhs);
286
287
}

288
/** Adds two workspaces
289
 *  @param lhs :: left hand side workspace shared pointer
290
291
 *  @param rhs :: right hand side workspace shared pointer
 *  @return The result in a workspace shared pointer
292
 */
293
MatrixWorkspace_sptr operator+=(const MatrixWorkspace_sptr lhs, const MatrixWorkspace_sptr rhs)
294
{
295
  return executeBinaryOperation<MatrixWorkspace_sptr,MatrixWorkspace_sptr,MatrixWorkspace_sptr>("Plus",lhs,rhs,true);
296
}
Nick Draper's avatar
re #75  
Nick Draper committed
297

298
/** Adds a single value to a workspace
299
300
 *  @param lhs ::      workspace shared pointer
 *  @param rhsValue :: the single value
301
 *  @return The result in a workspace shared pointer
302
 */
303
MatrixWorkspace_sptr operator+=(const MatrixWorkspace_sptr lhs, const double& rhsValue)
304
{
305
  return executeBinaryOperation<MatrixWorkspace_sptr,MatrixWorkspace_sptr,MatrixWorkspace_sptr>("Plus",lhs,createWorkspaceSingleValue(rhsValue),true);
306
}
Nick Draper's avatar
re #75  
Nick Draper committed
307

308
/** Subtracts two workspaces
309
 *  @param lhs :: left hand side workspace shared pointer
310
311
 *  @param rhs :: right hand side workspace shared pointer
 *  @return The result in a workspace shared pointer
312
 */
313
MatrixWorkspace_sptr operator-=(const MatrixWorkspace_sptr lhs, const MatrixWorkspace_sptr rhs)
314
{
315
  return executeBinaryOperation<MatrixWorkspace_sptr,MatrixWorkspace_sptr,MatrixWorkspace_sptr>("Minus",lhs,rhs,true);
316
317
318
}

/** Subtracts a single value from a workspace
319
320
 *  @param lhs ::      workspace shared pointer
 *  @param rhsValue :: the single value
321
 *  @return The result in a workspace shared pointer
322
 */
323
MatrixWorkspace_sptr operator-=(const MatrixWorkspace_sptr lhs, const double& rhsValue)
324
{
325
  return executeBinaryOperation<MatrixWorkspace_sptr,MatrixWorkspace_sptr,MatrixWorkspace_sptr>("Minus",lhs,createWorkspaceSingleValue(rhsValue),true);
326
327
328
}

/** Multiply two workspaces
329
 *  @param lhs :: left hand side workspace shared pointer
330
331
 *  @param rhs :: right hand side workspace shared pointer
 *  @return The result in a workspace shared pointer
332
 */
333
MatrixWorkspace_sptr operator*=(const MatrixWorkspace_sptr lhs, const MatrixWorkspace_sptr rhs)
334
{
335
  return executeBinaryOperation<MatrixWorkspace_sptr,MatrixWorkspace_sptr,MatrixWorkspace_sptr>("Multiply",lhs,rhs,true);
336
337
338
}

/** Multiplies a workspace by a single value
339
340
 *  @param lhs ::      workspace shared pointer
 *  @param rhsValue :: the single value
341
 *  @return The result in a workspace shared pointer
342
 */
343
MatrixWorkspace_sptr operator*=(const MatrixWorkspace_sptr lhs, const double& rhsValue)
344
{
345
  return executeBinaryOperation<MatrixWorkspace_sptr,MatrixWorkspace_sptr,MatrixWorkspace_sptr>("Multiply",lhs,createWorkspaceSingleValue(rhsValue),true);
346
347
348
}

/** Divide two workspaces
349
 *  @param lhs :: left hand side workspace shared pointer
350
351
 *  @param rhs :: right hand side workspace shared pointer
 *  @return The result in a workspace shared pointer
352
 */
353
MatrixWorkspace_sptr operator/=(const MatrixWorkspace_sptr lhs, const MatrixWorkspace_sptr rhs)
354
{
355
  return executeBinaryOperation<MatrixWorkspace_sptr,MatrixWorkspace_sptr,MatrixWorkspace_sptr>("Divide",lhs,rhs,true);
356
357
358
}

/** Divides a workspace by a single value
359
360
 *  @param lhs ::      workspace shared pointer
 *  @param rhsValue :: the single value
361
 *  @return The result in a workspace shared pointer
362
 */
363
MatrixWorkspace_sptr operator/=(const MatrixWorkspace_sptr lhs, const double& rhsValue)
364
{
365
  return executeBinaryOperation<MatrixWorkspace_sptr,MatrixWorkspace_sptr,MatrixWorkspace_sptr>("Divide",lhs,createWorkspaceSingleValue(rhsValue),true);
366
367
}

368

369
370
371
//----------------------------------------------------------------------
// Now the WorkspaceHelpers methods
//----------------------------------------------------------------------
372
373

/** Checks whether a workspace has common bins (or values) in X
374
 *  @param WS :: The workspace to check
375
376
 *  @return True if the bins match
 */
377
bool WorkspaceHelpers::commonBoundaries(const MatrixWorkspace_const_sptr WS)
378
379
380
{
  if ( !WS->blocksize() || WS->getNumberHistograms() < 2) return true;
  // Quickest check is to see if they are actually all the same vector
381
382
  if ( sharedXData(WS) ) return true;

383
384
  // But even if they're not they could still match...
  const double commonSum = std::accumulate(WS->readX(0).begin(),WS->readX(0).end(),0.);
385
386
  // If this results in infinity or NaN, then we can't tell - return false
  if ( commonSum == std::numeric_limits<double>::infinity() || commonSum != commonSum ) return false;
387
  const size_t numHist = WS->getNumberHistograms();
Doucet, Mathieu's avatar
Doucet, Mathieu committed
388
  for (size_t j = 1; j < numHist; ++j)
389
390
  {
    const double sum = std::accumulate(WS->readX(j).begin(),WS->readX(j).end(),0.);
391
392
393
    // If this results in infinity or NaN, then we can't tell - return false
    if ( sum == std::numeric_limits<double>::infinity() || sum != sum ) return false;

394
    if ( std::abs(commonSum-sum)/std::max<double>(commonSum,sum) > 1.0E-7 ) return false;
395
396
397
398
  }
  return true;
}

399
/** Checks whether the bins (X values) of two workspace are the same
400
401
402
 *  @param ws1 :: The first workspace
 *  @param ws2 :: The second workspace
 *  @param firstOnly :: If true, only the first spectrum is checked. If false (the default), all spectra
403
404
405
 *                   are checked and the two workspaces must have the same number of spectra
 *  @return True if the test passes
 */
406
bool WorkspaceHelpers::matchingBins(const MatrixWorkspace_const_sptr ws1,
407
                                          const MatrixWorkspace_const_sptr ws2, const bool firstOnly)
408
{
409
410
  // First of all, the first vector must be the same size
  if ( ws1->readX(0).size() != ws2->readX(0).size() ) return false;
411
412
413
414

  // Now check the first spectrum
  const double firstWS = std::accumulate(ws1->readX(0).begin(),ws1->readX(0).end(),0.);
  const double secondWS = std::accumulate(ws2->readX(0).begin(),ws2->readX(0).end(),0.);
415
  if ( std::abs(firstWS-secondWS)/std::max<double>(firstWS,secondWS) > 1.0E-7 ) return false;
416

417
418
419
420
421
  // If we were only asked to check the first spectrum, return now
  if (firstOnly) return true;

  // Check that total size of workspace is the same
  if ( ws1->size() != ws2->size() ) return false;
422
423
424
425
  // If that passes then check whether all the X vectors are shared
  if ( sharedXData(ws1) && sharedXData(ws2) ) return true;

  // If that didn't pass then explicitly check 1 in 10 of the vectors (min 10, max 100)
426
  const size_t numHist = ws1->getNumberHistograms();
Doucet, Mathieu's avatar
Doucet, Mathieu committed
427
  size_t numberToCheck = numHist / 10;
428
429
  if (numberToCheck<10) numberToCheck = 10;
  if (numberToCheck>100) numberToCheck = 100;
Doucet, Mathieu's avatar
Doucet, Mathieu committed
430
  size_t step = numHist / numberToCheck;
431
  if (!step) step=1;
Doucet, Mathieu's avatar
Doucet, Mathieu committed
432
  for (size_t i = step; i < numHist; i+=step)
433
434
435
  {
    const double firstWS = std::accumulate(ws1->readX(i).begin(),ws1->readX(i).end(),0.);
    const double secondWS = std::accumulate(ws2->readX(i).begin(),ws2->readX(i).end(),0.);
436
    if ( std::abs(firstWS-secondWS)/std::max<double>(firstWS,secondWS) > 1.0E-7 ) return false;
437
438
439
440
441
442
  }

  return true;
}

/// Checks whether all the X vectors in a workspace are the same one underneath
443
bool WorkspaceHelpers::sharedXData(const MatrixWorkspace_const_sptr WS)
444
445
{
  const double& first = WS->readX(0)[0];
446
  const size_t numHist = WS->getNumberHistograms();
Doucet, Mathieu's avatar
Doucet, Mathieu committed
447
  for (size_t i = 1; i < numHist; ++i)
448
449
  {
    if ( &first != &(WS->readX(i)[0]) ) return false;
450
451
452
453
  }
  return true;
}

454
455
456
/** Divides the data in a workspace by the bin width to make it a distribution.
 *  Can also reverse this operation (i.e. multiply by the bin width).
 *  Sets the isDistribution() flag accordingly.
457
458
 *  @param workspace :: The workspace on which to carry out the operation
 *  @param forwards :: If true (the default) divides by bin width, if false multiplies
459
 */
460
void WorkspaceHelpers::makeDistribution(MatrixWorkspace_sptr workspace, const bool forwards)
461
462
463
464
{
  // Check workspace isn't already in the correct state - do nothing if it is
  if ( workspace->isDistribution() == forwards ) return;

465
  const size_t numberOfSpectra = workspace->getNumberHistograms();
Laurent Chapon's avatar
Laurent Chapon committed
466

467
  std::vector<double> widths(workspace->readX(0).size());
Laurent Chapon's avatar
Laurent Chapon committed
468

Doucet, Mathieu's avatar
Doucet, Mathieu committed
469
  for (size_t i = 0; i < numberOfSpectra; ++i)
470
  {
471
472
473
	  const MantidVec& X=workspace->readX(i);
	  MantidVec& Y=workspace->dataY(i);
	  MantidVec& E=workspace->dataE(i);
Laurent Chapon's avatar
Laurent Chapon committed
474
475
	  std::adjacent_difference(X.begin(),X.end(),widths.begin()); // Calculate bin widths

476
477
    // RJT: I'll leave this in, but X should never be out of order. 
    // If it is there'll be problems elsewhere...
Laurent Chapon's avatar
Laurent Chapon committed
478
479
480
481
482
483
484
485
486
487
488
489
490
	  if (X.front()>X.back()) // If not ascending order
		  std::transform(widths.begin(),widths.end(),widths.begin(),std::negate<double>());

	  if (forwards)
	  {
		  std::transform(Y.begin(),Y.end(),widths.begin()+1,Y.begin(),std::divides<double>());
		  std::transform(E.begin(),E.end(),widths.begin()+1,E.begin(),std::divides<double>());
	  }
	  else
	  {
		  std::transform(Y.begin(),Y.end(),widths.begin()+1,Y.begin(),std::multiplies<double>());
		  std::transform(E.begin(),E.end(),widths.begin()+1,E.begin(),std::multiplies<double>());
	  }
491
492
493
494
  }
  workspace->isDistribution(forwards);
}

495
496
497
498




499
500
} // namespace API
} // namespace Mantid