<commit_before>/*************************************************************************
 *
 *  $RCSfile: SwXTextDefaults.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: mtg $ $Date: 2001-10-16 11:50:53 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): Martin Gallwey (gallwey@sun.com)
 *
 *
 ************************************************************************/
#ifdef PRECOMPILED
#include "core_pch.hxx"
#endif

#pragma hdrstop
#ifndef _SW_XTEXT_DEFAULTS_HXX
#include <SwXTextDefaults.hxx>
#endif

#ifndef _UNOMAP_HXX
#include <unomap.hxx>
#endif
#ifndef _VOS_MUTEX_HXX_
#include <vos/mutex.hxx>
#endif
#ifndef _SV_SVAPP_HXX
#include <vcl/svapp.hxx>
#endif
#ifndef _UNOPRNMS_HXX
#include <unoprnms.hxx>
#endif
#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_
#include <com/sun/star/beans/PropertyAttribute.hpp>
#endif
#ifndef _HINTIDS_HXX
#include <hintids.hxx>
#endif

using namespace rtl;
using namespace com::sun::star;
using namespace com::sun::star::uno;
using namespace com::sun::star::beans;
using namespace com::sun::star::lang;

SwXTextDefaults::SwXTextDefaults ( SwDoc * pNewDoc )
: pDoc (pNewDoc)
, aPropSet (aSwMapProvider.GetPropertyMap ( PROPERTY_MAP_TEXT_DEFAULT ) )
{
}
SwXTextDefaults::~SwXTextDefaults ()
{
}
Reference< XPropertySetInfo > SAL_CALL SwXTextDefaults::getPropertySetInfo(  )
        throw(RuntimeException)
{
    static uno::Reference < XPropertySetInfo > xRef = aPropSet.getPropertySetInfo();
    return xRef;
}
void SAL_CALL SwXTextDefaults::setPropertyValue( const OUString& rPropertyName, const Any& aValue )
        throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
{
    vos::OGuard aGuard( Application::GetSolarMutex());
    if (!pDoc)
        throw RuntimeException();
    const SfxItemPropertyMap *pMap = SfxItemPropertyMap::GetByName( aPropSet.getPropertyMap(), rPropertyName);
    if (!pMap)
        throw UnknownPropertyException();
    if ( pMap->nFlags & PropertyAttribute::READONLY)
        throw IllegalArgumentException();
    const SfxPoolItem& rItem = pDoc->GetDefault(pMap->nWID);
    SfxPoolItem * pNewItem = rItem.Clone();
    pNewItem->PutValue( aValue, pMap->nMemberId);
    pDoc->SetDefault(*pNewItem);
    delete pNewItem;
}
Any SAL_CALL SwXTextDefaults::getPropertyValue( const OUString& rPropertyName )
        throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
{
    vos::OGuard aGuard( Application::GetSolarMutex());
    if (!pDoc)
        throw RuntimeException();
    const SfxItemPropertyMap *pMap = SfxItemPropertyMap::GetByName( aPropSet.getPropertyMap(), rPropertyName);
    if (!pMap)
        throw UnknownPropertyException();
    if ( pMap->nFlags & PropertyAttribute::READONLY)
        throw RuntimeException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
    Any aRet;
    const SfxPoolItem& rItem = pDoc->GetDefault(pMap->nWID);
    rItem.QueryValue( aRet, pMap->nMemberId );
    return aRet;
}
void SAL_CALL SwXTextDefaults::addPropertyChangeListener( const OUString& rPropertyName, const Reference< XPropertyChangeListener >& xListener )
        throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
{
    DBG_WARNING ( "not implemented" );
}
void SAL_CALL SwXTextDefaults::removePropertyChangeListener( const OUString& rPropertyName, const Reference< XPropertyChangeListener >& aListener )
        throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
{
    DBG_WARNING ( "not implemented" );
}
void SAL_CALL SwXTextDefaults::addVetoableChangeListener( const OUString& rPropertyName, const Reference< XVetoableChangeListener >& aListener )
        throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
{
    DBG_WARNING ( "not implemented" );
}
void SAL_CALL SwXTextDefaults::removeVetoableChangeListener( const OUString& rPropertyName, const Reference< XVetoableChangeListener >& aListener )
        throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
{
    DBG_WARNING ( "not implemented" );
}
    // XPropertyState
PropertyState SAL_CALL SwXTextDefaults::getPropertyState( const OUString& rPropertyName )
        throw(UnknownPropertyException, RuntimeException)
{
    vos::OGuard aGuard( Application::GetSolarMutex());
    PropertyState eRet = PropertyState_DIRECT_VALUE;
    if (!pDoc)
        throw RuntimeException();
    const SfxItemPropertyMap *pMap = SfxItemPropertyMap::GetByName( aPropSet.getPropertyMap(), rPropertyName);
    if (!pMap)
        throw UnknownPropertyException();
    if ( pMap->nFlags & PropertyAttribute::READONLY)
        throw RuntimeException();

    const SfxPoolItem& rItem = pDoc->GetDefault(pMap->nWID);
    if (IsStaticDefaultItem ( &rItem ) )
        eRet = PropertyState_DEFAULT_VALUE;
    return eRet;
}
Sequence< PropertyState > SAL_CALL SwXTextDefaults::getPropertyStates( const Sequence< OUString >& rPropertyNames )
        throw(UnknownPropertyException, RuntimeException)
{
    const sal_Int32 nCount = rPropertyNames.getLength();
    const OUString * pNames = rPropertyNames.getConstArray();
    Sequence < PropertyState > aRet ( nCount );
    PropertyState *pState = aRet.getArray();

    for ( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++)
        pState[nIndex] = getPropertyState( pNames[nIndex] );

    return aRet;
}
void SAL_CALL SwXTextDefaults::setPropertyToDefault( const OUString& rPropertyName )
        throw(UnknownPropertyException, RuntimeException)
{
    if (!pDoc)
        throw RuntimeException();
    const SfxItemPropertyMap *pMap = SfxItemPropertyMap::GetByName( aPropSet.getPropertyMap(), rPropertyName);
    if (!pMap)
        throw UnknownPropertyException();
    if ( pMap->nFlags & PropertyAttribute::READONLY)
        throw RuntimeException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
   SfxItemPool rSet (pDoc->GetAttrPool());
   rSet.ResetPoolDefaultItem ( pMap->nWID );
}
Any SAL_CALL SwXTextDefaults::getPropertyDefault( const OUString& rPropertyName )
        throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
{
    if (!pDoc)
        throw RuntimeException();
    const SfxItemPropertyMap *pMap = SfxItemPropertyMap::GetByName( aPropSet.getPropertyMap(), rPropertyName);
    if (!pMap)
        throw UnknownPropertyException();
    if ( pMap->nFlags & PropertyAttribute::READONLY)
        throw RuntimeException();
    Any aRet;
    SfxItemPool rSet (pDoc->GetAttrPool());
    const SfxPoolItem *pItem = rSet.GetPoolDefaultItem ( pMap->nWID );
    pItem->QueryValue( aRet, pMap->nMemberId );
    return aRet;
}
<commit_msg>#95176# check readonly flag before setting properties, also provide info in exceptions<commit_after>/*************************************************************************
 *
 *  $RCSfile: SwXTextDefaults.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: mtg $ $Date: 2001-11-28 20:01:17 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): Martin Gallwey (gallwey@sun.com)
 *
 *
 ************************************************************************/
#ifdef PRECOMPILED
#include "core_pch.hxx"
#endif

#pragma hdrstop
#ifndef _SW_XTEXT_DEFAULTS_HXX
#include <SwXTextDefaults.hxx>
#endif

#ifndef _UNOMAP_HXX
#include <unomap.hxx>
#endif
#ifndef _VOS_MUTEX_HXX_
#include <vos/mutex.hxx>
#endif
#ifndef _SV_SVAPP_HXX
#include <vcl/svapp.hxx>
#endif
#ifndef _UNOPRNMS_HXX
#include <unoprnms.hxx>
#endif
#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_
#include <com/sun/star/beans/PropertyAttribute.hpp>
#endif
#ifndef _HINTIDS_HXX
#include <hintids.hxx>
#endif

using namespace rtl;
using namespace com::sun::star;
using namespace com::sun::star::uno;
using namespace com::sun::star::beans;
using namespace com::sun::star::lang;

SwXTextDefaults::SwXTextDefaults ( SwDoc * pNewDoc )
: pDoc (pNewDoc)
, aPropSet (aSwMapProvider.GetPropertyMap ( PROPERTY_MAP_TEXT_DEFAULT ) )
{
}
SwXTextDefaults::~SwXTextDefaults ()
{
}
Reference< XPropertySetInfo > SAL_CALL SwXTextDefaults::getPropertySetInfo(  )
        throw(RuntimeException)
{
    static uno::Reference < XPropertySetInfo > xRef = aPropSet.getPropertySetInfo();
    return xRef;
}
void SAL_CALL SwXTextDefaults::setPropertyValue( const OUString& rPropertyName, const Any& aValue )
        throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
{
    vos::OGuard aGuard( Application::GetSolarMutex());
    if (!pDoc)
        throw RuntimeException();
    const SfxItemPropertyMap *pMap = SfxItemPropertyMap::GetByName( aPropSet.getPropertyMap(), rPropertyName);
    if (!pMap)
        throw UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
    if ( pMap->nFlags & PropertyAttribute::READONLY)
        throw IllegalArgumentException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ), 0 );
    const SfxPoolItem& rItem = pDoc->GetDefault(pMap->nWID);
    SfxPoolItem * pNewItem = rItem.Clone();
    pNewItem->PutValue( aValue, pMap->nMemberId);
    pDoc->SetDefault(*pNewItem);
    delete pNewItem;
}
Any SAL_CALL SwXTextDefaults::getPropertyValue( const OUString& rPropertyName )
        throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
{
    vos::OGuard aGuard( Application::GetSolarMutex());
    if (!pDoc)
        throw RuntimeException();
    const SfxItemPropertyMap *pMap = SfxItemPropertyMap::GetByName( aPropSet.getPropertyMap(), rPropertyName);
    if (!pMap)
        throw UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
    Any aRet;
    const SfxPoolItem& rItem = pDoc->GetDefault(pMap->nWID);
    rItem.QueryValue( aRet, pMap->nMemberId );
    return aRet;
}
void SAL_CALL SwXTextDefaults::addPropertyChangeListener( const OUString& rPropertyName, const Reference< XPropertyChangeListener >& xListener )
        throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
{
    DBG_WARNING ( "not implemented" );
}
void SAL_CALL SwXTextDefaults::removePropertyChangeListener( const OUString& rPropertyName, const Reference< XPropertyChangeListener >& aListener )
        throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
{
    DBG_WARNING ( "not implemented" );
}
void SAL_CALL SwXTextDefaults::addVetoableChangeListener( const OUString& rPropertyName, const Reference< XVetoableChangeListener >& aListener )
        throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
{
    DBG_WARNING ( "not implemented" );
}
void SAL_CALL SwXTextDefaults::removeVetoableChangeListener( const OUString& rPropertyName, const Reference< XVetoableChangeListener >& aListener )
        throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
{
    DBG_WARNING ( "not implemented" );
}
    // XPropertyState
PropertyState SAL_CALL SwXTextDefaults::getPropertyState( const OUString& rPropertyName )
        throw(UnknownPropertyException, RuntimeException)
{
    vos::OGuard aGuard( Application::GetSolarMutex());
    PropertyState eRet = PropertyState_DIRECT_VALUE;
    if (!pDoc)
        throw RuntimeException();
    const SfxItemPropertyMap *pMap = SfxItemPropertyMap::GetByName( aPropSet.getPropertyMap(), rPropertyName);
    if (!pMap)
        throw UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
    if ( pMap->nFlags & PropertyAttribute::READONLY)
        throw RuntimeException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );

    const SfxPoolItem& rItem = pDoc->GetDefault(pMap->nWID);
    if (IsStaticDefaultItem ( &rItem ) )
        eRet = PropertyState_DEFAULT_VALUE;
    return eRet;
}
Sequence< PropertyState > SAL_CALL SwXTextDefaults::getPropertyStates( const Sequence< OUString >& rPropertyNames )
        throw(UnknownPropertyException, RuntimeException)
{
    const sal_Int32 nCount = rPropertyNames.getLength();
    const OUString * pNames = rPropertyNames.getConstArray();
    Sequence < PropertyState > aRet ( nCount );
    PropertyState *pState = aRet.getArray();

    for ( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++)
        pState[nIndex] = getPropertyState( pNames[nIndex] );

    return aRet;
}
void SAL_CALL SwXTextDefaults::setPropertyToDefault( const OUString& rPropertyName )
        throw(UnknownPropertyException, RuntimeException)
{
    if (!pDoc)
        throw RuntimeException();
    const SfxItemPropertyMap *pMap = SfxItemPropertyMap::GetByName( aPropSet.getPropertyMap(), rPropertyName);
    if (!pMap)
        throw UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
    if ( pMap->nFlags & PropertyAttribute::READONLY)
        throw RuntimeException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
   SfxItemPool rSet (pDoc->GetAttrPool());
   rSet.ResetPoolDefaultItem ( pMap->nWID );
}
Any SAL_CALL SwXTextDefaults::getPropertyDefault( const OUString& rPropertyName )
        throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
{
    if (!pDoc)
        throw RuntimeException();
    const SfxItemPropertyMap *pMap = SfxItemPropertyMap::GetByName( aPropSet.getPropertyMap(), rPropertyName);
    if (!pMap)
        throw UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
    if ( pMap->nFlags & PropertyAttribute::READONLY)
        throw RuntimeException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
    Any aRet;
    SfxItemPool rSet (pDoc->GetAttrPool());
    const SfxPoolItem *pItem = rSet.GetPoolDefaultItem ( pMap->nWID );
    pItem->QueryValue( aRet, pMap->nMemberId );
    return aRet;
}
<|endoftext|>


<commit_before>/*
    Copyright 2008 Brain Research Institute, Melbourne, Australia

    Written by Robert E. Smith, 2013.

    This file is part of MRtrix.

    MRtrix is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    MRtrix is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with MRtrix.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "command.h"
#include "args.h"
#include "exception.h"
#include "mrtrix.h"
#include "progressbar.h"

#include "image/buffer.h"
#include "image/buffer_scratch.h"
#include "image/copy.h"
#include "image/loop.h"
#include "image/position.h"
#include "image/threaded_loop.h"
#include "image/utils.h"
#include "image/value.h"

#include "math/math.h"
#include "math/SH.h"
#include "math/vector.h"

#include "thread_queue.h"

#include "dwi/directions/set.h"
#include "dwi/gradient.h"
#include "dwi/shells.h"
#include "dwi/sdeconv/constrained.h"
#include "dwi/sdeconv/rf_estimation.h"

using namespace MR;
using namespace MR::DWI;
using namespace MR::DWI::RF;
using namespace App;

#define DWI2RESPONSE_DEFAULT_MAX_ITERS 20
#define DWI2RESPONSE_DEFAULT_MAX_CHANGE 0.5

#define DWI2RESPONSE_DEFAULT_VOLUME_RATIO 0.15
#define DWI2RESPONSE_DEFAULT_DISPERSION_MULTIPLIER 1.0
#define DWI2RESPONSE_DEFAULT_INTEGRAL_STDEV_MULTIPLIER 2.0

const OptionGroup TermOption = OptionGroup ("Options for terminating the optimisation algorithm")

    + Option ("max_iters", "maximum number of iterations per pass (set to zero to disable)")
      + Argument ("value").type_integer (0, DWI2RESPONSE_DEFAULT_MAX_ITERS, 1e6)

    + Option ("max_change", "maximum percentile change in any response function coefficient; "
                            "if no individual coefficient changes by more than this fraction, the algorithm is terminated.")
      + Argument ("value").type_float (0.0, DWI2RESPONSE_DEFAULT_MAX_CHANGE, 100.0);

const OptionGroup SFOption = OptionGroup ("Thresholds for single-fibre voxel selection")

    + Option ("volume_ratio", "required volume ratio between largest FOD lobe and the sum of all other positive lobes in the voxel")
      + Argument ("value").type_float (0.0, DWI2RESPONSE_DEFAULT_VOLUME_RATIO, 1.0)

    + Option ("dispersion_multiplier", "dispersion of FOD lobe must not exceed some threshold as determined by this factor and FOD dispersion statistics. "
                                       "The threshold is: (mean + (multiplier * (mean - min))). "
                                       "Criterion is only applied in second pass of RF estimation.")
      + Argument ("value").type_float (0.0, DWI2RESPONSE_DEFAULT_DISPERSION_MULTIPLIER, 100.0)

    + Option ("integral_multiplier", "integral of FOD lobe must not be outside some range as determined by this factor and FOD lobe integral statistics. "
                                     "The range is: (mean +- (multiplier * stdev)). "
                                     "Criterion is only applied in second pass of RF estimation.")
      + Argument ("value").type_float (0.0, DWI2RESPONSE_DEFAULT_INTEGRAL_STDEV_MULTIPLIER, 1.0);

void usage () {

  AUTHOR = "Robert E. Smith (robert.smith@florey.edu.au)";

  DESCRIPTION
    + "generate an appropriate response function from the image data for spherical deconvolution";

  REFERENCES
    + "Tax, C. M.; Jeurissen, B.; Vos, S. B.; Viergever, M. A. & Leemans, A. "
    "Recursive calibration of the fiber response function for spherical deconvolution of diffusion MRI data. "
    "NeuroImage, 2014, 86, 67-80";

  ARGUMENTS
    + Argument ("dwi_in",       "the input diffusion-weighted images").type_image_in()
    + Argument ("response_out", "the output rotational harmonic coefficients").type_file_out();

  OPTIONS

    + DWI::GradImportOptions()
    + DWI::ShellOption

    + Option ("mask", "provide an initial mask image")
      + Argument ("image").type_image_in()

    + Option ("lmax", "specify the maximum harmonic degree of the response function to estimate")
      + Argument ("value").type_integer (4, 8, 20)

    + Option ("sf", "output a mask highlighting the final selection of single-fibre voxels")
      + Argument ("image").type_image_out()

    + Option ("test_all", "by default, only those voxels selected as single-fibre in the previous iteration are evaluated. "
                          "Set this option to re-test all voxels at every iteration (slower).")

    + TermOption
    + SFOption;

  // TODO More options:
  // * Response function estimation method - simple averaging (a la 0.2) or Bayesian w. Rician noise correction
  //     Have a final pass after optimisation that estimates the final RF using the more advanced method
  //     (with or without Rician bias correction)
  //     (currently can just use this binary to derive the mask, then feed to get_response)

}

void run ()
{

  Image::Header H (argument[0]);

  Image::Info info (H);
  info.set_ndim (3);
  Image::BufferScratch<bool> mask (info);
  auto v_mask = mask.voxel();

  std::string mask_path;
  Options opt = get_options ("mask");
  if (opt.size()) {
    mask_path = std::string(opt[0][0]);
    Image::Buffer<bool> in (mask_path);
    if (!Image::dimensions_match (H, in, 0, 3))
      throw Exception ("Input mask image does not match DWI");
    if (!(in.ndim() == 3 || (in.ndim() == 4 && in.dim(3) == 1)))
      throw Exception ("Input mask image must be a 3D image");
    auto v_in = in.voxel();
    Image::copy (v_in, v_mask, 0, 3);
  } else {
    for (auto l = Image::LoopInOrder (v_mask) (v_mask); l; ++l)
      v_mask.value() = true;
  }

  DWI::CSDeconv<float>::Shared shared (H);

  const size_t max_lmax = Math::SH::LforN (shared.dwis.size());
  if (max_lmax < 4)
    throw Exception ("Selected b-value shell does not have an adequate number of directions (" + str(shared.dwis.size()) + ") to run dwi2response (need at least 15 for lmax=4)");
  size_t lmax = std::min (size_t(8), max_lmax);
  opt = get_options ("lmax");
  if (opt.size()) {
    const size_t desired_lmax = int(opt[0][0]);
    if (desired_lmax % 2)
      throw Exception ("lmax must be an even number");
    if (desired_lmax > max_lmax)
      throw Exception ("Image data do not support estimating response function above an lmax of " + str(max_lmax));
    lmax = desired_lmax;
  }
  shared.lmax = lmax;

  Image::BufferPreload<float> dwi (H, Image::Stride::contiguous_along_axis (3));
  DWI::Directions::Set directions (1281);

  Math::Vector<float> response (lmax/2+1);
  response.zero();

  {
    // Initialise response function
    // Use lmax = 2, get the DWI intensity mean and standard deviation within the mask and
    //   use these as the first two coefficients
    auto v_dwi = dwi.voxel();
    double sum = 0.0, sq_sum = 0.0;
    size_t count = 0;
    Image::LoopInOrder loop (dwi, "initialising response function... ", 0, 3);
    for (auto l = loop (v_dwi, v_mask); l; ++l) {
      if (v_mask.value()) {
        for (size_t volume_index = 0; volume_index != shared.dwis.size(); ++volume_index) {
          v_dwi[3] = shared.dwis[volume_index];
          const float value = v_dwi.value();
          sum += value;
          sq_sum += Math::pow2 (value);
          ++count;
        }
      }
    }
    response[0] = sum / double (count);
    response[1] = - 0.5 * std::sqrt ((sq_sum / double(count)) - Math::pow2 (response[0]));
    // Account for scaling in SH basis
    response *= std::sqrt (4.0 * Math::pi);
  }
  INFO ("Initial response function is [" + str(response, 2) + "]");

  // Algorithm termination options
  opt = get_options ("max_iters");
  const size_t max_iters = opt.size() ? int(opt[0][0]) : DWI2RESPONSE_DEFAULT_MAX_ITERS;
  opt = get_options ("max_change");
  const float max_change = 0.01 * (opt.size() ? float(opt[0][0]) : DWI2RESPONSE_DEFAULT_MAX_CHANGE);

  // Should all voxels (potentially within a user-specified mask) be tested at every iteration?
  opt = get_options ("test_all");
  const bool reset_mask = opt.size();

  // Single-fibre voxel selection options
  opt = get_options ("volume_ratio");
  const float volume_ratio = opt.size() ? float(opt[0][0]) : DWI2RESPONSE_DEFAULT_VOLUME_RATIO;
  opt = get_options ("dispersion_multiplier");
  const float dispersion_multiplier = opt.size() ? float(opt[0][0]) : DWI2RESPONSE_DEFAULT_DISPERSION_MULTIPLIER;
  opt = get_options ("integral_multiplier");
  const float integral_multiplier = opt.size() ? float(opt[0][0]) : DWI2RESPONSE_DEFAULT_INTEGRAL_STDEV_MULTIPLIER;

  SFThresholds thresholds (volume_ratio); // Only threshold the lobe volume ratio for now; other two are not yet used

  size_t total_iter = 0;
  bool first_pass = true;
  size_t prev_sf_count = 0;
  {
    bool iterate = true;
    size_t iter = 0;
    ProgressBar progress ("optimising response function.. ");
    do {

      ++iter;

      {
        MR::LogLevelLatch latch (0);
        shared.set_response (response);
        shared.init();
      }

      ++progress;

      if (reset_mask) {
        if (mask_path.size()) {
          Image::Buffer<bool> in (mask_path);
          auto v_in = in.voxel();
          Image::copy (v_in, v_mask, 0, 3);
        } else {
          for (auto l = Image::LoopInOrder(v_mask) (v_mask); l; ++l)
            v_mask.value() = true;
        }
        ++progress;
      }

      std::vector<FODSegResult> seg_results;
      {
        FODCalcAndSeg processor (dwi, mask, shared, directions, lmax, seg_results);
        Image::ThreadedLoop loop (mask, 0, 3);
        loop.run (processor);
      }

      ++progress;

      if (!first_pass)
        thresholds.update (seg_results, dispersion_multiplier, integral_multiplier, iter);

      ++progress;

      Response output (lmax);
      mask.zero();
      {
        SFSelector selector (seg_results, thresholds, mask);
        ResponseEstimator estimator (dwi, shared, lmax, output);
        Thread::run_queue (selector, FODSegResult(), Thread::multi (estimator));
      }
      if (!output.get_count())
        throw Exception ("Cannot estimate response function; all voxels have been excluded from selection");
      const Math::Vector<float> new_response = output.result();
      const size_t sf_count = output.get_count();

      ++progress;

      if (App::log_level >= 2)
        std::cerr << "\n";
      INFO ("Iteration " + str(iter) + ", " + str(sf_count) + " SF voxels, new response function: [" + str(new_response, 2) + "]");

      if (sf_count == prev_sf_count) {
        INFO ("terminating due to convergence of single-fibre voxel selection");
        iterate = false;
      }
      if (iter == max_iters) {
        INFO ("terminating due to completing maximum number of iterations");
        iterate = false;
      }
      bool rf_changed = false;
      for (size_t i = 0; i != response.size(); ++i) {
        if (std::abs ((new_response[i] - response[i]) / new_response[i]) > max_change)
          rf_changed = true;
      }
      if (!rf_changed) {
        INFO ("terminating due to negligible changes in the response function coefficients");
        iterate = false;
      }

      if (!iterate && first_pass) {
        iterate = true;
        first_pass = false;
        INFO ("commencing second-pass of response function estimation");
        total_iter = iter;
        iter = 0;
      }

      response = new_response;
      prev_sf_count = sf_count;

      //v_mask.save ("mask_pass_" + str(first_pass?1:2) + "_iter_" + str(iter) + ".mif");

    } while (iterate);

    total_iter += iter;

  }

  INFO ("final response function: [" + str(response, 2) + "] (reached after " + str(total_iter) + " iterations using " + str(prev_sf_count) + " voxels)");
  response.save (argument[1]);

  opt = get_options ("sf");
  if (opt.size())
    v_mask.save (std::string (opt[0][0]));

}

<commit_msg>dwi2response: Fix -integral_multiplier option range<commit_after>/*
    Copyright 2008 Brain Research Institute, Melbourne, Australia

    Written by Robert E. Smith, 2013.

    This file is part of MRtrix.

    MRtrix is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    MRtrix is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with MRtrix.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "command.h"
#include "args.h"
#include "exception.h"
#include "mrtrix.h"
#include "progressbar.h"

#include "image/buffer.h"
#include "image/buffer_scratch.h"
#include "image/copy.h"
#include "image/loop.h"
#include "image/position.h"
#include "image/threaded_loop.h"
#include "image/utils.h"
#include "image/value.h"

#include "math/math.h"
#include "math/SH.h"
#include "math/vector.h"

#include "thread_queue.h"

#include "dwi/directions/set.h"
#include "dwi/gradient.h"
#include "dwi/shells.h"
#include "dwi/sdeconv/constrained.h"
#include "dwi/sdeconv/rf_estimation.h"

using namespace MR;
using namespace MR::DWI;
using namespace MR::DWI::RF;
using namespace App;

#define DWI2RESPONSE_DEFAULT_MAX_ITERS 20
#define DWI2RESPONSE_DEFAULT_MAX_CHANGE 0.5

#define DWI2RESPONSE_DEFAULT_VOLUME_RATIO 0.15
#define DWI2RESPONSE_DEFAULT_DISPERSION_MULTIPLIER 1.0
#define DWI2RESPONSE_DEFAULT_INTEGRAL_STDEV_MULTIPLIER 2.0

const OptionGroup TermOption = OptionGroup ("Options for terminating the optimisation algorithm")

    + Option ("max_iters", "maximum number of iterations per pass (set to zero to disable)")
      + Argument ("value").type_integer (0, DWI2RESPONSE_DEFAULT_MAX_ITERS, 1e6)

    + Option ("max_change", "maximum percentile change in any response function coefficient; "
                            "if no individual coefficient changes by more than this fraction, the algorithm is terminated.")
      + Argument ("value").type_float (0.0, DWI2RESPONSE_DEFAULT_MAX_CHANGE, 100.0);

const OptionGroup SFOption = OptionGroup ("Thresholds for single-fibre voxel selection")

    + Option ("volume_ratio", "required volume ratio between largest FOD lobe and the sum of all other positive lobes in the voxel")
      + Argument ("value").type_float (0.0, DWI2RESPONSE_DEFAULT_VOLUME_RATIO, 1.0)

    + Option ("dispersion_multiplier", "dispersion of FOD lobe must not exceed some threshold as determined by this factor and FOD dispersion statistics. "
                                       "The threshold is: (mean + (multiplier * (mean - min))). "
                                       "Criterion is only applied in second pass of RF estimation.")
      + Argument ("value").type_float (0.0, DWI2RESPONSE_DEFAULT_DISPERSION_MULTIPLIER, 100.0)

    + Option ("integral_multiplier", "integral of FOD lobe must not be outside some range as determined by this factor and FOD lobe integral statistics. "
                                     "The range is: (mean +- (multiplier * stdev)). "
                                     "Criterion is only applied in second pass of RF estimation.")
      + Argument ("value").type_float (0.0, DWI2RESPONSE_DEFAULT_INTEGRAL_STDEV_MULTIPLIER, 1e6);

void usage () {

  AUTHOR = "Robert E. Smith (robert.smith@florey.edu.au)";

  DESCRIPTION
    + "generate an appropriate response function from the image data for spherical deconvolution";

  REFERENCES
    + "Tax, C. M.; Jeurissen, B.; Vos, S. B.; Viergever, M. A. & Leemans, A. "
    "Recursive calibration of the fiber response function for spherical deconvolution of diffusion MRI data. "
    "NeuroImage, 2014, 86, 67-80";

  ARGUMENTS
    + Argument ("dwi_in",       "the input diffusion-weighted images").type_image_in()
    + Argument ("response_out", "the output rotational harmonic coefficients").type_file_out();

  OPTIONS

    + DWI::GradImportOptions()
    + DWI::ShellOption

    + Option ("mask", "provide an initial mask image")
      + Argument ("image").type_image_in()

    + Option ("lmax", "specify the maximum harmonic degree of the response function to estimate")
      + Argument ("value").type_integer (4, 8, 20)

    + Option ("sf", "output a mask highlighting the final selection of single-fibre voxels")
      + Argument ("image").type_image_out()

    + Option ("test_all", "by default, only those voxels selected as single-fibre in the previous iteration are evaluated. "
                          "Set this option to re-test all voxels at every iteration (slower).")

    + TermOption
    + SFOption;

  // TODO More options:
  // * Response function estimation method - simple averaging (a la 0.2) or Bayesian w. Rician noise correction
  //     Have a final pass after optimisation that estimates the final RF using the more advanced method
  //     (with or without Rician bias correction)
  //     (currently can just use this binary to derive the mask, then feed to get_response)

}

void run ()
{

  Image::Header H (argument[0]);

  Image::Info info (H);
  info.set_ndim (3);
  Image::BufferScratch<bool> mask (info);
  auto v_mask = mask.voxel();

  std::string mask_path;
  Options opt = get_options ("mask");
  if (opt.size()) {
    mask_path = std::string(opt[0][0]);
    Image::Buffer<bool> in (mask_path);
    if (!Image::dimensions_match (H, in, 0, 3))
      throw Exception ("Input mask image does not match DWI");
    if (!(in.ndim() == 3 || (in.ndim() == 4 && in.dim(3) == 1)))
      throw Exception ("Input mask image must be a 3D image");
    auto v_in = in.voxel();
    Image::copy (v_in, v_mask, 0, 3);
  } else {
    for (auto l = Image::LoopInOrder (v_mask) (v_mask); l; ++l)
      v_mask.value() = true;
  }

  DWI::CSDeconv<float>::Shared shared (H);

  const size_t max_lmax = Math::SH::LforN (shared.dwis.size());
  if (max_lmax < 4)
    throw Exception ("Selected b-value shell does not have an adequate number of directions (" + str(shared.dwis.size()) + ") to run dwi2response (need at least 15 for lmax=4)");
  size_t lmax = std::min (size_t(8), max_lmax);
  opt = get_options ("lmax");
  if (opt.size()) {
    const size_t desired_lmax = int(opt[0][0]);
    if (desired_lmax % 2)
      throw Exception ("lmax must be an even number");
    if (desired_lmax > max_lmax)
      throw Exception ("Image data do not support estimating response function above an lmax of " + str(max_lmax));
    lmax = desired_lmax;
  }
  shared.lmax = lmax;

  Image::BufferPreload<float> dwi (H, Image::Stride::contiguous_along_axis (3));
  DWI::Directions::Set directions (1281);

  Math::Vector<float> response (lmax/2+1);
  response.zero();

  {
    // Initialise response function
    // Use lmax = 2, get the DWI intensity mean and standard deviation within the mask and
    //   use these as the first two coefficients
    auto v_dwi = dwi.voxel();
    double sum = 0.0, sq_sum = 0.0;
    size_t count = 0;
    Image::LoopInOrder loop (dwi, "initialising response function... ", 0, 3);
    for (auto l = loop (v_dwi, v_mask); l; ++l) {
      if (v_mask.value()) {
        for (size_t volume_index = 0; volume_index != shared.dwis.size(); ++volume_index) {
          v_dwi[3] = shared.dwis[volume_index];
          const float value = v_dwi.value();
          sum += value;
          sq_sum += Math::pow2 (value);
          ++count;
        }
      }
    }
    response[0] = sum / double (count);
    response[1] = - 0.5 * std::sqrt ((sq_sum / double(count)) - Math::pow2 (response[0]));
    // Account for scaling in SH basis
    response *= std::sqrt (4.0 * Math::pi);
  }
  INFO ("Initial response function is [" + str(response, 2) + "]");

  // Algorithm termination options
  opt = get_options ("max_iters");
  const size_t max_iters = opt.size() ? int(opt[0][0]) : DWI2RESPONSE_DEFAULT_MAX_ITERS;
  opt = get_options ("max_change");
  const float max_change = 0.01 * (opt.size() ? float(opt[0][0]) : DWI2RESPONSE_DEFAULT_MAX_CHANGE);

  // Should all voxels (potentially within a user-specified mask) be tested at every iteration?
  opt = get_options ("test_all");
  const bool reset_mask = opt.size();

  // Single-fibre voxel selection options
  opt = get_options ("volume_ratio");
  const float volume_ratio = opt.size() ? float(opt[0][0]) : DWI2RESPONSE_DEFAULT_VOLUME_RATIO;
  opt = get_options ("dispersion_multiplier");
  const float dispersion_multiplier = opt.size() ? float(opt[0][0]) : DWI2RESPONSE_DEFAULT_DISPERSION_MULTIPLIER;
  opt = get_options ("integral_multiplier");
  const float integral_multiplier = opt.size() ? float(opt[0][0]) : DWI2RESPONSE_DEFAULT_INTEGRAL_STDEV_MULTIPLIER;

  SFThresholds thresholds (volume_ratio); // Only threshold the lobe volume ratio for now; other two are not yet used

  size_t total_iter = 0;
  bool first_pass = true;
  size_t prev_sf_count = 0;
  {
    bool iterate = true;
    size_t iter = 0;
    ProgressBar progress ("optimising response function.. ");
    do {

      ++iter;

      {
        MR::LogLevelLatch latch (0);
        shared.set_response (response);
        shared.init();
      }

      ++progress;

      if (reset_mask) {
        if (mask_path.size()) {
          Image::Buffer<bool> in (mask_path);
          auto v_in = in.voxel();
          Image::copy (v_in, v_mask, 0, 3);
        } else {
          for (auto l = Image::LoopInOrder(v_mask) (v_mask); l; ++l)
            v_mask.value() = true;
        }
        ++progress;
      }

      std::vector<FODSegResult> seg_results;
      {
        FODCalcAndSeg processor (dwi, mask, shared, directions, lmax, seg_results);
        Image::ThreadedLoop loop (mask, 0, 3);
        loop.run (processor);
      }

      ++progress;

      if (!first_pass)
        thresholds.update (seg_results, dispersion_multiplier, integral_multiplier, iter);

      ++progress;

      Response output (lmax);
      mask.zero();
      {
        SFSelector selector (seg_results, thresholds, mask);
        ResponseEstimator estimator (dwi, shared, lmax, output);
        Thread::run_queue (selector, FODSegResult(), Thread::multi (estimator));
      }
      if (!output.get_count())
        throw Exception ("Cannot estimate response function; all voxels have been excluded from selection");
      const Math::Vector<float> new_response = output.result();
      const size_t sf_count = output.get_count();

      ++progress;

      if (App::log_level >= 2)
        std::cerr << "\n";
      INFO ("Iteration " + str(iter) + ", " + str(sf_count) + " SF voxels, new response function: [" + str(new_response, 2) + "]");

      if (sf_count == prev_sf_count) {
        INFO ("terminating due to convergence of single-fibre voxel selection");
        iterate = false;
      }
      if (iter == max_iters) {
        INFO ("terminating due to completing maximum number of iterations");
        iterate = false;
      }
      bool rf_changed = false;
      for (size_t i = 0; i != response.size(); ++i) {
        if (std::abs ((new_response[i] - response[i]) / new_response[i]) > max_change)
          rf_changed = true;
      }
      if (!rf_changed) {
        INFO ("terminating due to negligible changes in the response function coefficients");
        iterate = false;
      }

      if (!iterate && first_pass) {
        iterate = true;
        first_pass = false;
        INFO ("commencing second-pass of response function estimation");
        total_iter = iter;
        iter = 0;
      }

      response = new_response;
      prev_sf_count = sf_count;

      //v_mask.save ("mask_pass_" + str(first_pass?1:2) + "_iter_" + str(iter) + ".mif");

    } while (iterate);

    total_iter += iter;

  }

  INFO ("final response function: [" + str(response, 2) + "] (reached after " + str(total_iter) + " iterations using " + str(prev_sf_count) + " voxels)");
  response.save (argument[1]);

  opt = get_options ("sf");
  if (opt.size())
    v_mask.save (std::string (opt[0][0]));

}

<|endoftext|>


<commit_before>// Canberra CNF (aka CAM format) with spectral data from Genie software
// Licence: Lesser GNU Public License 2.1 (LGPL)
// $Id$

#define BUILDING_XYLIB
#include "canberra_cnf.h"

#include <memory>
#include <ctime>
#include <cstring>
#include <boost/cstdint.hpp>

#include "util.h"

using namespace std;
using namespace xylib::util;
using boost::uint16_t;
using boost::uint32_t;
using boost::uint64_t;

namespace xylib {

const FormatInfo CanberraCnfDataSet::fmt_info(
    "canberra_cnf",
    "Canberra CNF",
    "cnf",
    true,                       // whether binary
    false,                      // whether has multi-blocks
    &CanberraCnfDataSet::ctor,
    &CanberraCnfDataSet::check
);

bool CanberraCnfDataSet::check(istream &f)
{
    int chan_offset = 0;
    f.ignore(112);
    int pos = 112;
    char buf[48];
    while (!f.eof()) {
        f.read(buf, 48);
        if (f.gcount() != 48)
            return false;
        pos += 48;
        if (buf[0] == 5 && ((buf[1] == 0x20 && buf[2] == 0x01) ||
                             buf[1] == 0 || buf[2] == 0)) {
            chan_offset = from_le<uint32_t>(buf+10);
            break;
        }
    }
    if (chan_offset <= pos)
        return false;
    f.ignore(chan_offset - pos);
    f.read(buf, 48);
    return (!f.eof() && f.gcount() == 48 && buf[0] == 5 && buf[1] == 0x20);
}

static
Column* read_energy_callibration(const char* p, Block *blk, int n_channels)
{
    // energy calibration
    p += 2*4+28;
    double coef[3];
    for (int i = 0; i != 3; ++i)
        coef[i] = from_pdp11(p + 4*i);
    if (coef[1] == 0.)
        return NULL;
    for (int i = 0; i != 3; ++i)
        blk->meta["energy calib " + S(i)] = S(coef[i]);
    if (coef[2] != 0.) { // quadr term
        VecColumn *vc = new VecColumn;
        // FIXME should it be from 0 or from 1?
        for (int i = 0; i < n_channels; i++) {
            double x = coef[0] + coef[1] * i + coef[2] * i * i;
            vc->add_val(x);
        }
        return vc;
    }
    else
        return new StepColumn(coef[0], coef[1]);
}

static
bool is_printable(const string &s)
{
    for (size_t i = 0; i != s.size(); ++i)
        if (!isprint(s[i]))
                return false;
    return true;
}

// comment from Stefan Schneider-Kennedy:
// > 8 byte little endian. Number of 100ns intervals since 1859.
// > Like Microsoft's FILETIME with an offset.
static
string convert_date(const char* p)
{
    uint64_t d;
    memcpy(&d, p, sizeof(d));
    le_to_host(&d, sizeof(d));
    time_t t = d / 1e7 - 3506716800; // time since the Epoch
    char s[64];
    int r = strftime(s, sizeof(s), "%a, %Y-%m-%d %H:%M:%S", gmtime(&t));
    if (r == 0)
        throw FormatError("reading date failed.");
    return string(s);
}

// comment from Stefan Schneider-Kennedy:
// > 8 byte little endian. 2^(64) - number of 100ns intervals since timing
// > started. Like Microsoft's FILETIME. Round to nearest second.
static
float convert_time(const char* p)
{
    uint64_t d;
    memcpy(&d, p, sizeof(d));
    le_to_host(&d, sizeof(d));
    return (~d) * 1.0e-7;
}

void CanberraCnfDataSet::load_data(std::istream &f)
{
    string file_string;
    file_string.reserve(128*1024);
    file_string.assign((istreambuf_iterator<char>(f)),
                       istreambuf_iterator<char>());
    const char* beg = file_string.c_str();
    const char* end = beg + file_string.size();

    int acq_offset = 0, sam_offset = 0, eff_offset = 0, enc_offset = 0,
        chan_offset = 0;

    // we have here 48-byte blocks with meta data
    for (const char* ptr = beg+112; ptr+48 < end; ptr += 48) {
        uint32_t offset = from_le<uint32_t>(ptr+10);
        if ((ptr[1] == 0x20 && ptr[2] == 0x01) || ptr[1] == 0 || ptr[2] == 0) {
            switch (ptr[0]) {
                case 0:
                    if (acq_offset == 0)
                        acq_offset = offset;
                    else
                        enc_offset = offset;
                    break;
                case 1:
                    if (sam_offset == 0)
                        sam_offset = offset;
                    break;
                case 2:
                    if (eff_offset == 0)
                        eff_offset = offset;
                    break;
                case 5:
                    if (chan_offset == 0)
                        chan_offset = offset;
                    break;
                default:
                    break;
            }
            if (acq_offset != 0 && sam_offset != 0 &&
                        eff_offset != 0 && chan_offset != 0)
                break;
        }
    }
    if (enc_offset == 0)
        enc_offset = acq_offset;

    auto_ptr<Block> blk(new Block);

    // sample data - split name into name and description
    // (this was not in code from JF, it's my guess - MW)
    const char* sam_ptr = beg + sam_offset;
    string name;
    if (sam_ptr+0x30+80 >= end || sam_ptr[0] != 1 || sam_ptr[1] != 0x20)
        fprintf(stderr, "Warning. Sample data not found.\n");
    else {
        string name = str_trim(string(sam_ptr+0x30, 32));
        if (!name.empty() && is_printable(name))
            blk->set_name(name);
        string desc = str_trim(string(sam_ptr+0x30+32, 48));
        if (!desc.empty() && is_printable(desc))
            blk->meta["description"] = desc;
    }

    // go to acquisition data
    const char* acq_ptr = beg + acq_offset;
    if (acq_ptr+48+128+10+4 >= end || acq_ptr[0] != 0 || acq_ptr[1] != 0x20)
        throw FormatError("Acquisition data not found.");
    uint16_t offset1 = from_le<uint16_t>(acq_ptr+34);
    uint16_t offset2 = from_le<uint16_t>(acq_ptr+36);

    const char* pha_ptr = acq_ptr + 48 + 128;
    if (pha_ptr[0] != 'P' || pha_ptr[1] != 'H' || pha_ptr[2] != 'A')
        fprintf(stderr, "Warning. PHA keyword not found.\n");

    int n_channels = from_le<uint16_t>(pha_ptr+10) * 256;
    if (n_channels < 256 || n_channels > 16384)
        throw FormatError("Unexpected number of channels" + S(n_channels));

    // dates and times
    const char* date_ptr = acq_ptr+48+offset2+1;
    format_assert(this, date_ptr + 3*8 < end);
    blk->meta["date and time"] = convert_date(date_ptr); // when taken
    float real_time = convert_time(date_ptr + 8);
    blk->meta["real time (s)"] = format1<float, 16>("%.2f", real_time);
    float live_time = convert_time(date_ptr + 16);
    blk->meta["live time (s)"] = format1<float, 16>("%.2f", live_time);

    format_assert(this, beg + enc_offset+48+32 + offset1 < end);
    Column *xcol = read_energy_callibration(beg + enc_offset+48+32 + offset1,
                                            blk.get(), n_channels);
    if (xcol == NULL)
        xcol = read_energy_callibration(beg + enc_offset+48+32,
                                        blk.get(), n_channels);
    if (xcol == NULL) {
        fprintf(stderr, "Warning. Energy Calibration not found.\n");
        xcol = new StepColumn(1, 1);
    }

    // code from JF is also reading detector name, but it's not needed here
    // detector name was 232 bytes after energy calibration

    // channel data
    const char* chan_ptr = beg + chan_offset;
    if (chan_ptr+512+4*n_channels > end || chan_ptr[0] != 5 ||
                                           chan_ptr[1] != 0x20)
        throw FormatError("Channel data not found.");
    VecColumn *ycol = new VecColumn;
    // the two first channels sometimes contain live and real time
    for (int i = 0; i < 2; ++i) {
        uint32_t y = from_le<uint32_t>(chan_ptr+512+4*i);
        if ((int) y == iround(real_time) || (int) y == iround(live_time))
            y = 0;
        ycol->add_val(y);
    }
    for (int i = 2; i < n_channels; ++i) {
        uint32_t y = from_le<uint32_t>(chan_ptr+512+4*i);
        ycol->add_val(y);
    }

    blk->add_column(xcol);
    blk->add_column(ycol);
    add_block(blk.release());
}

} // namespace xylib

<commit_msg>CNF: first channel is 1, not 0<commit_after>// Canberra CNF (aka CAM format) with spectral data from Genie software
// Licence: Lesser GNU Public License 2.1 (LGPL)
// $Id$

#define BUILDING_XYLIB
#include "canberra_cnf.h"

#include <memory>
#include <ctime>
#include <cstring>
#include <boost/cstdint.hpp>

#include "util.h"

using namespace std;
using namespace xylib::util;
using boost::uint16_t;
using boost::uint32_t;
using boost::uint64_t;

namespace xylib {

const FormatInfo CanberraCnfDataSet::fmt_info(
    "canberra_cnf",
    "Canberra CNF",
    "cnf",
    true,                       // whether binary
    false,                      // whether has multi-blocks
    &CanberraCnfDataSet::ctor,
    &CanberraCnfDataSet::check
);

bool CanberraCnfDataSet::check(istream &f)
{
    int chan_offset = 0;
    f.ignore(112);
    int pos = 112;
    char buf[48];
    while (!f.eof()) {
        f.read(buf, 48);
        if (f.gcount() != 48)
            return false;
        pos += 48;
        if (buf[0] == 5 && ((buf[1] == 0x20 && buf[2] == 0x01) ||
                             buf[1] == 0 || buf[2] == 0)) {
            chan_offset = from_le<uint32_t>(buf+10);
            break;
        }
    }
    if (chan_offset <= pos)
        return false;
    f.ignore(chan_offset - pos);
    f.read(buf, 48);
    return (!f.eof() && f.gcount() == 48 && buf[0] == 5 && buf[1] == 0x20);
}

static
Column* read_energy_callibration(const char* p, Block *blk, int n_channels)
{
    // energy calibration
    p += 2*4+28;
    double coef[3];
    for (int i = 0; i != 3; ++i)
        coef[i] = from_pdp11(p + 4*i);
    if (coef[1] == 0.)
        return NULL;
    for (int i = 0; i != 3; ++i)
        blk->meta["energy calib " + S(i)] = S(coef[i]);
    if (coef[2] != 0.) { // quadr term
        VecColumn *vc = new VecColumn;
        // Comparing results with FitzPeaks and and Cambio 4.0
        // the first channel should have number 1 (not 0).
        for (int i = 1; i <= n_channels; i++) {
            double x = coef[0] + coef[1] * i + coef[2] * i * i;
            vc->add_val(x);
        }
        return vc;
    }
    else
        // since we start from ch1, the first value is coef[0] + coef[1]
        return new StepColumn(coef[0]+coef[1], coef[1]);
}

static
bool is_printable(const string &s)
{
    for (size_t i = 0; i != s.size(); ++i)
        if (!isprint(s[i]))
                return false;
    return true;
}

// comment from Stefan Schneider-Kennedy:
// > 8 byte little endian. Number of 100ns intervals since 1859.
// > Like Microsoft's FILETIME with an offset.
static
string convert_date(const char* p)
{
    uint64_t d;
    memcpy(&d, p, sizeof(d));
    le_to_host(&d, sizeof(d));
    time_t t = d / 1e7 - 3506716800; // time since the Epoch
    char s[64];
    int r = strftime(s, sizeof(s), "%a, %Y-%m-%d %H:%M:%S", gmtime(&t));
    if (r == 0)
        throw FormatError("reading date failed.");
    return string(s);
}

// comment from Stefan Schneider-Kennedy:
// > 8 byte little endian. 2^(64) - number of 100ns intervals since timing
// > started. Like Microsoft's FILETIME. Round to nearest second.
static
float convert_time(const char* p)
{
    uint64_t d;
    memcpy(&d, p, sizeof(d));
    le_to_host(&d, sizeof(d));
    return (~d) * 1.0e-7;
}

void CanberraCnfDataSet::load_data(std::istream &f)
{
    string file_string;
    file_string.reserve(128*1024);
    file_string.assign((istreambuf_iterator<char>(f)),
                       istreambuf_iterator<char>());
    const char* beg = file_string.c_str();
    const char* end = beg + file_string.size();

    int acq_offset = 0, sam_offset = 0, eff_offset = 0, enc_offset = 0,
        chan_offset = 0;

    // we have here 48-byte blocks with meta data
    for (const char* ptr = beg+112; ptr+48 < end; ptr += 48) {
        uint32_t offset = from_le<uint32_t>(ptr+10);
        if ((ptr[1] == 0x20 && ptr[2] == 0x01) || ptr[1] == 0 || ptr[2] == 0) {
            switch (ptr[0]) {
                case 0:
                    if (acq_offset == 0)
                        acq_offset = offset;
                    else
                        enc_offset = offset;
                    break;
                case 1:
                    if (sam_offset == 0)
                        sam_offset = offset;
                    break;
                case 2:
                    if (eff_offset == 0)
                        eff_offset = offset;
                    break;
                case 5:
                    if (chan_offset == 0)
                        chan_offset = offset;
                    break;
                default:
                    break;
            }
            if (acq_offset != 0 && sam_offset != 0 &&
                        eff_offset != 0 && chan_offset != 0)
                break;
        }
    }
    if (enc_offset == 0)
        enc_offset = acq_offset;

    auto_ptr<Block> blk(new Block);

    // sample data - split name into name and description
    // (this was not in code from JF, it's my guess - MW)
    const char* sam_ptr = beg + sam_offset;
    string name;
    if (sam_ptr+0x30+80 >= end || sam_ptr[0] != 1 || sam_ptr[1] != 0x20)
        fprintf(stderr, "Warning. Sample data not found.\n");
    else {
        string name = str_trim(string(sam_ptr+0x30, 32));
        if (!name.empty() && is_printable(name))
            blk->set_name(name);
        string desc = str_trim(string(sam_ptr+0x30+32, 48));
        if (!desc.empty() && is_printable(desc))
            blk->meta["description"] = desc;
    }

    // go to acquisition data
    const char* acq_ptr = beg + acq_offset;
    if (acq_ptr+48+128+10+4 >= end || acq_ptr[0] != 0 || acq_ptr[1] != 0x20)
        throw FormatError("Acquisition data not found.");
    uint16_t offset1 = from_le<uint16_t>(acq_ptr+34);
    uint16_t offset2 = from_le<uint16_t>(acq_ptr+36);

    const char* pha_ptr = acq_ptr + 48 + 128;
    if (pha_ptr[0] != 'P' || pha_ptr[1] != 'H' || pha_ptr[2] != 'A')
        fprintf(stderr, "Warning. PHA keyword not found.\n");

    int n_channels = from_le<uint16_t>(pha_ptr+10) * 256;
    if (n_channels < 256 || n_channels > 16384)
        throw FormatError("Unexpected number of channels" + S(n_channels));

    // dates and times
    const char* date_ptr = acq_ptr+48+offset2+1;
    format_assert(this, date_ptr + 3*8 < end);
    blk->meta["date and time"] = convert_date(date_ptr); // when taken
    float real_time = convert_time(date_ptr + 8);
    blk->meta["real time (s)"] = format1<float, 16>("%.2f", real_time);
    float live_time = convert_time(date_ptr + 16);
    blk->meta["live time (s)"] = format1<float, 16>("%.2f", live_time);

    format_assert(this, beg + enc_offset+48+32 + offset1 < end);
    Column *xcol = read_energy_callibration(beg + enc_offset+48+32 + offset1,
                                            blk.get(), n_channels);
    if (xcol == NULL)
        xcol = read_energy_callibration(beg + enc_offset+48+32,
                                        blk.get(), n_channels);
    if (xcol == NULL) {
        fprintf(stderr, "Warning. Energy Calibration not found.\n");
        xcol = new StepColumn(1, 1);
    }

    // code from JF is also reading detector name, but it's not needed here
    // detector name was 232 bytes after energy calibration

    // channel data
    const char* chan_ptr = beg + chan_offset;
    if (chan_ptr+512+4*n_channels > end || chan_ptr[0] != 5 ||
                                           chan_ptr[1] != 0x20)
        throw FormatError("Channel data not found.");
    VecColumn *ycol = new VecColumn;
    // the two first channels sometimes contain live and real time
    for (int i = 0; i < 2; ++i) {
        uint32_t y = from_le<uint32_t>(chan_ptr+512+4*i);
        if ((int) y == iround(real_time) || (int) y == iround(live_time))
            y = 0;
        ycol->add_val(y);
    }
    for (int i = 2; i < n_channels; ++i) {
        uint32_t y = from_le<uint32_t>(chan_ptr+512+4*i);
        ycol->add_val(y);
    }

    blk->add_column(xcol);
    blk->add_column(ycol);
    add_block(blk.release());
}

} // namespace xylib

<|endoftext|>


<commit_before>// Canberra CNF (aka CAM format) with spectral data from Genie software
// Licence: Lesser GNU Public License 2.1 (LGPL)
// $Id$

#define BUILDING_XYLIB
#include "canberra_cnf.h"

#include <memory>
#include <ctime>
#include <cstring>
#include <boost/cstdint.hpp>

#include "util.h"

using namespace std;
using namespace xylib::util;
using boost::uint16_t;
using boost::uint32_t;
using boost::uint64_t;

namespace xylib {

const FormatInfo CanberraCnfDataSet::fmt_info(
    "canberra_cnf",
    "Canberra CNF",
    "cnf",
    true,                       // whether binary
    false,                      // whether has multi-blocks
    &CanberraCnfDataSet::ctor,
    &CanberraCnfDataSet::check
);

bool CanberraCnfDataSet::check(istream &f)
{
    int chan_offset = 0;
    f.ignore(112);
    int pos = 112;
    char buf[48];
    while (!f.eof()) {
        f.read(buf, 48);
        if (f.gcount() != 48)
            return false;
        pos += 48;
        if (buf[0] == 5 && ((buf[1] == 0x20 && buf[2] == 0x01) ||
                             buf[1] == 0 || buf[2] == 0)) {
            chan_offset = from_le<uint32_t>(buf+10);
            break;
        }
    }
    if (chan_offset <= pos)
        return false;
    f.ignore(chan_offset - pos);
    f.read(buf, 48);
    return (!f.eof() && f.gcount() == 48 && buf[0] == 5 && buf[1] == 0x20);
}

static
Column* read_energy_callibration(const char* p, Block *blk, int n_channels)
{
    // energy calibration
    p += 2*4+28;
    double coef[3];
    for (int i = 0; i != 3; ++i)
        coef[i] = from_pdp11(p + 4*i);
    if (coef[1] == 0.)
        return NULL;
    for (int i = 0; i != 3; ++i)
        blk->meta["energy calib " + S(i)] = S(coef[i]);
    if (coef[2] != 0.) { // quadr term
        VecColumn *vc = new VecColumn;
        // FIXME should it be from 0 or from 1?
        for (int i = 0; i < n_channels; i++) {
            double x = coef[0] + coef[1] * i + coef[2] * i * i;
            vc->add_val(x);
        }
        return vc;
    }
    else
        return new StepColumn(coef[0], coef[1]);
}

static
bool is_printable(const string &s)
{
    for (size_t i = 0; i != s.size(); ++i)
        if (!isprint(s[i]))
                return false;
    return true;
}

// comment from Stefan Schneider-Kennedy:
// > 8 byte little endian. Number of 100ns intervals since 1859.
// > Like Microsoft's FILETIME with an offset.
static
string convert_date(const char* p)
{
    uint64_t d;
    memcpy(&d, p, sizeof(d));
    le_to_host(&d, sizeof(d));
    time_t t = d / 1e7 - 3506716800; // time since the Epoch
    char s[64];
    int r = strftime(s, sizeof(s), "%a, %Y-%m-%d %H:%M:%S", gmtime(&t));
    if (r == 0)
        throw FormatError("reading date failed.");
    return string(s);
}

// comment from Stefan Schneider-Kennedy:
// > 8 byte little endian. 2^(64) - number of 100ns intervals since timing
// > started. Like Microsoft's FILETIME. Round to nearest second.
static
float convert_time(const char* p)
{
    uint64_t d;
    memcpy(&d, p, sizeof(d));
    le_to_host(&d, sizeof(d));
    return (~d) * 1.0e-7;
}

void CanberraCnfDataSet::load_data(std::istream &f)
{
    string file_string;
    file_string.reserve(128*1024);
    file_string.assign((istreambuf_iterator<char>(f)),
                       istreambuf_iterator<char>());
    const char* beg = file_string.c_str();
    const char* end = beg + file_string.size();

    int acq_offset = 0, sam_offset = 0, eff_offset = 0, enc_offset = 0,
        chan_offset = 0;

    // we have here 48-byte blocks with meta data
    for (const char* ptr = beg+112; ptr+48 < end; ptr += 48) {
        uint32_t offset = from_le<uint32_t>(ptr+10);
        if ((ptr[1] == 0x20 && ptr[2] == 0x01) || ptr[1] == 0 || ptr[2] == 0) {
            switch (ptr[0]) {
                case 0:
                    if (acq_offset == 0)
                        acq_offset = offset;
                    else
                        enc_offset = offset;
                    break;
                case 1:
                    if (sam_offset == 0)
                        sam_offset = offset;
                    break;
                case 2:
                    if (eff_offset == 0)
                        eff_offset = offset;
                    break;
                case 5:
                    if (chan_offset == 0)
                        chan_offset = offset;
                    break;
                default:
                    break;
            }
            if (acq_offset != 0 && sam_offset != 0 &&
                        eff_offset != 0 && chan_offset != 0)
                break;
        }
    }
    if (enc_offset == 0)
        enc_offset = acq_offset;

    auto_ptr<Block> blk(new Block);

    // sample data - split name into name and description
    // (this was not in code from JF, it's my guess - MW)
    const char* sam_ptr = beg + sam_offset;
    string name;
    if (sam_ptr+0x30+80 >= end || sam_ptr[0] != 1 || sam_ptr[1] != 0x20)
        fprintf(stderr, "Warning. Sample data not found.\n");
    else {
        string name = str_trim(string(sam_ptr+0x30, 32));
        if (!name.empty() && is_printable(name))
            blk->set_name(name);
        string desc = str_trim(string(sam_ptr+0x30+32, 48));
        if (!desc.empty() && is_printable(desc))
            blk->meta["description"] = desc;
    }

    // go to acquisition data
    const char* acq_ptr = beg + acq_offset;
    if (acq_ptr+48+128+10+4 >= end || acq_ptr[0] != 0 || acq_ptr[1] != 0x20)
        throw FormatError("Acquisition data not found.");
    uint16_t offset1 = from_le<uint16_t>(acq_ptr+34);
    uint16_t offset2 = from_le<uint16_t>(acq_ptr+36);

    const char* pha_ptr = acq_ptr + 48 + 128;
    if (pha_ptr[0] != 'P' || pha_ptr[1] != 'H' || pha_ptr[2] != 'A')
        fprintf(stderr, "Warning. PHA keyword not found.\n");

    int n_channels = from_le<uint16_t>(pha_ptr+10) * 256;
    if (n_channels < 256 || n_channels > 16384)
        throw FormatError("Unexpected number of channels" + S(n_channels));

    // dates and times
    const char* date_ptr = acq_ptr+48+offset2+1;
    format_assert(this, date_ptr + 3*8 < end);
    blk->meta["date and time"] = convert_date(date_ptr); // when taken
    float real_time = convert_time(date_ptr + 8);
    blk->meta["real time (s)"] = format1<float, 16>("%.2f", real_time);
    float live_time = convert_time(date_ptr + 16);
    blk->meta["live time (s)"] = format1<float, 16>("%.2f", live_time);

    format_assert(this, beg + enc_offset+48+32 + offset1 < end);
    Column *xcol = read_energy_callibration(beg + enc_offset+48+32 + offset1,
                                            blk.get(), n_channels);
    if (xcol == NULL)
        xcol = read_energy_callibration(beg + enc_offset+48+32,
                                        blk.get(), n_channels);
    if (xcol == NULL) {
        fprintf(stderr, "Warning. Energy Calibration not found.\n");
        xcol = new StepColumn(1, 1);
    }

    // code from JF is also reading detector name, but it's not needed here
    // detector name was 232 bytes after energy calibration

    // channel data
    const char* chan_ptr = beg + chan_offset;
    if (chan_ptr+512+4*n_channels > end || chan_ptr[0] != 5 ||
                                           chan_ptr[1] != 0x20)
        throw FormatError("Channel data not found.");
    VecColumn *ycol = new VecColumn;
    // the two first channels sometimes contain live and real time
    for (int i = 0; i < 2; ++i) {
        uint32_t y = from_le<uint32_t>(chan_ptr+512+4*i);
        if (y == iround(real_time) || y == iround(live_time))
            y = 0;
        ycol->add_val(y);
    }
    for (int i = 2; i < n_channels; ++i) {
        uint32_t y = from_le<uint32_t>(chan_ptr+512+4*i);
        ycol->add_val(y);
    }

    blk->add_column(xcol);
    blk->add_column(ycol);
    add_block(blk.release());
}

} // namespace xylib

<commit_msg>avoid two compiler warnings<commit_after>// Canberra CNF (aka CAM format) with spectral data from Genie software
// Licence: Lesser GNU Public License 2.1 (LGPL)
// $Id$

#define BUILDING_XYLIB
#include "canberra_cnf.h"

#include <memory>
#include <ctime>
#include <cstring>
#include <boost/cstdint.hpp>

#include "util.h"

using namespace std;
using namespace xylib::util;
using boost::uint16_t;
using boost::uint32_t;
using boost::uint64_t;

namespace xylib {

const FormatInfo CanberraCnfDataSet::fmt_info(
    "canberra_cnf",
    "Canberra CNF",
    "cnf",
    true,                       // whether binary
    false,                      // whether has multi-blocks
    &CanberraCnfDataSet::ctor,
    &CanberraCnfDataSet::check
);

bool CanberraCnfDataSet::check(istream &f)
{
    int chan_offset = 0;
    f.ignore(112);
    int pos = 112;
    char buf[48];
    while (!f.eof()) {
        f.read(buf, 48);
        if (f.gcount() != 48)
            return false;
        pos += 48;
        if (buf[0] == 5 && ((buf[1] == 0x20 && buf[2] == 0x01) ||
                             buf[1] == 0 || buf[2] == 0)) {
            chan_offset = from_le<uint32_t>(buf+10);
            break;
        }
    }
    if (chan_offset <= pos)
        return false;
    f.ignore(chan_offset - pos);
    f.read(buf, 48);
    return (!f.eof() && f.gcount() == 48 && buf[0] == 5 && buf[1] == 0x20);
}

static
Column* read_energy_callibration(const char* p, Block *blk, int n_channels)
{
    // energy calibration
    p += 2*4+28;
    double coef[3];
    for (int i = 0; i != 3; ++i)
        coef[i] = from_pdp11(p + 4*i);
    if (coef[1] == 0.)
        return NULL;
    for (int i = 0; i != 3; ++i)
        blk->meta["energy calib " + S(i)] = S(coef[i]);
    if (coef[2] != 0.) { // quadr term
        VecColumn *vc = new VecColumn;
        // FIXME should it be from 0 or from 1?
        for (int i = 0; i < n_channels; i++) {
            double x = coef[0] + coef[1] * i + coef[2] * i * i;
            vc->add_val(x);
        }
        return vc;
    }
    else
        return new StepColumn(coef[0], coef[1]);
}

static
bool is_printable(const string &s)
{
    for (size_t i = 0; i != s.size(); ++i)
        if (!isprint(s[i]))
                return false;
    return true;
}

// comment from Stefan Schneider-Kennedy:
// > 8 byte little endian. Number of 100ns intervals since 1859.
// > Like Microsoft's FILETIME with an offset.
static
string convert_date(const char* p)
{
    uint64_t d;
    memcpy(&d, p, sizeof(d));
    le_to_host(&d, sizeof(d));
    time_t t = d / 1e7 - 3506716800; // time since the Epoch
    char s[64];
    int r = strftime(s, sizeof(s), "%a, %Y-%m-%d %H:%M:%S", gmtime(&t));
    if (r == 0)
        throw FormatError("reading date failed.");
    return string(s);
}

// comment from Stefan Schneider-Kennedy:
// > 8 byte little endian. 2^(64) - number of 100ns intervals since timing
// > started. Like Microsoft's FILETIME. Round to nearest second.
static
float convert_time(const char* p)
{
    uint64_t d;
    memcpy(&d, p, sizeof(d));
    le_to_host(&d, sizeof(d));
    return (~d) * 1.0e-7;
}

void CanberraCnfDataSet::load_data(std::istream &f)
{
    string file_string;
    file_string.reserve(128*1024);
    file_string.assign((istreambuf_iterator<char>(f)),
                       istreambuf_iterator<char>());
    const char* beg = file_string.c_str();
    const char* end = beg + file_string.size();

    int acq_offset = 0, sam_offset = 0, eff_offset = 0, enc_offset = 0,
        chan_offset = 0;

    // we have here 48-byte blocks with meta data
    for (const char* ptr = beg+112; ptr+48 < end; ptr += 48) {
        uint32_t offset = from_le<uint32_t>(ptr+10);
        if ((ptr[1] == 0x20 && ptr[2] == 0x01) || ptr[1] == 0 || ptr[2] == 0) {
            switch (ptr[0]) {
                case 0:
                    if (acq_offset == 0)
                        acq_offset = offset;
                    else
                        enc_offset = offset;
                    break;
                case 1:
                    if (sam_offset == 0)
                        sam_offset = offset;
                    break;
                case 2:
                    if (eff_offset == 0)
                        eff_offset = offset;
                    break;
                case 5:
                    if (chan_offset == 0)
                        chan_offset = offset;
                    break;
                default:
                    break;
            }
            if (acq_offset != 0 && sam_offset != 0 &&
                        eff_offset != 0 && chan_offset != 0)
                break;
        }
    }
    if (enc_offset == 0)
        enc_offset = acq_offset;

    auto_ptr<Block> blk(new Block);

    // sample data - split name into name and description
    // (this was not in code from JF, it's my guess - MW)
    const char* sam_ptr = beg + sam_offset;
    string name;
    if (sam_ptr+0x30+80 >= end || sam_ptr[0] != 1 || sam_ptr[1] != 0x20)
        fprintf(stderr, "Warning. Sample data not found.\n");
    else {
        string name = str_trim(string(sam_ptr+0x30, 32));
        if (!name.empty() && is_printable(name))
            blk->set_name(name);
        string desc = str_trim(string(sam_ptr+0x30+32, 48));
        if (!desc.empty() && is_printable(desc))
            blk->meta["description"] = desc;
    }

    // go to acquisition data
    const char* acq_ptr = beg + acq_offset;
    if (acq_ptr+48+128+10+4 >= end || acq_ptr[0] != 0 || acq_ptr[1] != 0x20)
        throw FormatError("Acquisition data not found.");
    uint16_t offset1 = from_le<uint16_t>(acq_ptr+34);
    uint16_t offset2 = from_le<uint16_t>(acq_ptr+36);

    const char* pha_ptr = acq_ptr + 48 + 128;
    if (pha_ptr[0] != 'P' || pha_ptr[1] != 'H' || pha_ptr[2] != 'A')
        fprintf(stderr, "Warning. PHA keyword not found.\n");

    int n_channels = from_le<uint16_t>(pha_ptr+10) * 256;
    if (n_channels < 256 || n_channels > 16384)
        throw FormatError("Unexpected number of channels" + S(n_channels));

    // dates and times
    const char* date_ptr = acq_ptr+48+offset2+1;
    format_assert(this, date_ptr + 3*8 < end);
    blk->meta["date and time"] = convert_date(date_ptr); // when taken
    float real_time = convert_time(date_ptr + 8);
    blk->meta["real time (s)"] = format1<float, 16>("%.2f", real_time);
    float live_time = convert_time(date_ptr + 16);
    blk->meta["live time (s)"] = format1<float, 16>("%.2f", live_time);

    format_assert(this, beg + enc_offset+48+32 + offset1 < end);
    Column *xcol = read_energy_callibration(beg + enc_offset+48+32 + offset1,
                                            blk.get(), n_channels);
    if (xcol == NULL)
        xcol = read_energy_callibration(beg + enc_offset+48+32,
                                        blk.get(), n_channels);
    if (xcol == NULL) {
        fprintf(stderr, "Warning. Energy Calibration not found.\n");
        xcol = new StepColumn(1, 1);
    }

    // code from JF is also reading detector name, but it's not needed here
    // detector name was 232 bytes after energy calibration

    // channel data
    const char* chan_ptr = beg + chan_offset;
    if (chan_ptr+512+4*n_channels > end || chan_ptr[0] != 5 ||
                                           chan_ptr[1] != 0x20)
        throw FormatError("Channel data not found.");
    VecColumn *ycol = new VecColumn;
    // the two first channels sometimes contain live and real time
    for (int i = 0; i < 2; ++i) {
        uint32_t y = from_le<uint32_t>(chan_ptr+512+4*i);
        if ((int) y == iround(real_time) || (int) y == iround(live_time))
            y = 0;
        ycol->add_val(y);
    }
    for (int i = 2; i < n_channels; ++i) {
        uint32_t y = from_le<uint32_t>(chan_ptr+512+4*i);
        ycol->add_val(y);
    }

    blk->add_column(xcol);
    blk->add_column(ycol);
    add_block(blk.release());
}

} // namespace xylib

<|endoftext|>


<commit_before>#line 2 "togo/tool_build/generator_compiler.cpp"
/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.
*/

#include <togo/tool_build/config.hpp>
#include <togo/tool_build/types.hpp>
#include <togo/tool_build/generator_compiler.hpp>
#include <togo/tool_build/gfx_compiler.hpp>

namespace togo {
namespace tool_build {

void generator_compiler::register_standard(
	GfxCompiler& gfx_compiler
) {
	using namespace generator_compiler;
	gfx_compiler::register_generator_compiler(gfx_compiler, test_proxy);
}

} // namespace tool_build
} // namespace togo
<commit_msg>tool_build/generator_compiler: fully-qualify reference to generator_compiler::test_proxy.<commit_after>#line 2 "togo/tool_build/generator_compiler.cpp"
/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.
*/

#include <togo/tool_build/config.hpp>
#include <togo/tool_build/types.hpp>
#include <togo/tool_build/generator_compiler.hpp>
#include <togo/tool_build/gfx_compiler.hpp>

namespace togo {
namespace tool_build {

void generator_compiler::register_standard(
	GfxCompiler& gfx_compiler
) {
	using namespace generator_compiler;
	gfx_compiler::register_generator_compiler(gfx_compiler, generator_compiler::test_proxy);
}

} // namespace tool_build
} // namespace togo
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: pyuno_util.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2004-09-08 16:52:57 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Ralph Thomas
 *
 *   Copyright: 2000 by Sun Microsystems, Inc.
 *
 *   All Rights Reserved.
 *
 *   Contributor(s): Ralph Thomas, Joerg Budischewski
 *
 *
 ************************************************************************/
#include <osl/thread.h>

#include <typelib/typedescription.hxx>

#include <rtl/strbuf.hxx>
#include <rtl/ustrbuf.hxx>

#include <com/sun/star/beans/XMaterialHolder.hpp>

#include "pyuno_impl.hxx"

using rtl::OUStringToOString;
using rtl::OUString;
using rtl::OString;
using rtl::OStringBuffer;
using rtl::OUStringBuffer;

using com::sun::star::uno::TypeDescription;
using com::sun::star::uno::Sequence;
using com::sun::star::uno::Reference;
using com::sun::star::uno::XInterface;
using com::sun::star::uno::Any;
using com::sun::star::uno::Type;
using com::sun::star::uno::UNO_QUERY;
using com::sun::star::uno::TypeClass;
using com::sun::star::uno::RuntimeException;
using com::sun::star::uno::XComponentContext;
using com::sun::star::lang::XSingleServiceFactory;
using com::sun::star::script::XTypeConverter;
using com::sun::star::beans::XMaterialHolder;

#define USTR_ASCII(x) OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
namespace pyuno
{
PyRef ustring2PyUnicode( const OUString & str )
{
    PyRef ret;
#if Py_UNICODE_SIZE == 2
    ret = PyRef( PyUnicode_FromUnicode( str.getStr(), str.getLength() ), SAL_NO_ACQUIRE );
#else
#if Py_UNICODE_SIZE == 4
    OString o = OUStringToOString( str, RTL_TEXTENCODING_UCS4 );
    ret = PyRef( PyUnicode_FromUnicode( (Py_UNICODE*)o.getStr(), o.getLength() ), SAL_NO_ACQUIRE );
#else
#error Py_UNICODE_SIZE
    OUStringBuffer buf;
    buf.appendAscii( "pyuno string conversion routines can't deal with sizeof(Py_UNICODE) ==" );
    buf.append( (sal_Int32) sizeof( Py_UNICODE ) );
    throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface > ( ) );
#endif
#endif
    return ret;
}

PyRef ustring2PyString( const OUString &str )
{
    OString o = OUStringToOString( str, osl_getThreadTextEncoding() );
    return PyRef( PyString_FromString( o.getStr() ), SAL_NO_ACQUIRE );
}

OUString pyString2ustring( PyObject *pystr )
{
    OUString ret;
    if( PyUnicode_Check( pystr ) )
    {
        ret = OUString( (sal_Unicode * ) PyUnicode_AS_UNICODE( pystr ) );
    }
    else
    {
        char *name = PyString_AsString(pystr );
        ret = OUString( name, strlen(name), osl_getThreadTextEncoding() );
    }
    return ret;
}

PyRef getObjectFromUnoModule( const Runtime &runtime, const char * func )
    throw ( RuntimeException )
{
    PyRef object(PyDict_GetItemString( runtime.getImpl()->cargo->getUnoModule().get(), (char*)func ) );
    if( !object.is() )
    {
        OUStringBuffer buf;
        buf.appendAscii( "couldn't find core function " );
        buf.appendAscii( func );
        throw RuntimeException(buf.makeStringAndClear(),Reference< XInterface >());
    }
    return object;
}

}
<commit_msg>INTEGRATION: CWS systempython2 (1.2.14); FILE MERGED 2005/02/21 09:35:47 cmc 1.2.14.2: #i41994# dec ref 2005/02/18 08:50:37 cmc 1.2.14.1: #i41994# systempython post pyunofixes1<commit_after>/*************************************************************************
 *
 *  $RCSfile: pyuno_util.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: vg $ $Date: 2005-02-24 14:25:40 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Ralph Thomas
 *
 *   Copyright: 2000 by Sun Microsystems, Inc.
 *
 *   All Rights Reserved.
 *
 *   Contributor(s): Ralph Thomas, Joerg Budischewski
 *
 *
 ************************************************************************/
#include <osl/thread.h>

#include <typelib/typedescription.hxx>

#include <rtl/strbuf.hxx>
#include <rtl/ustrbuf.hxx>

#include <com/sun/star/beans/XMaterialHolder.hpp>

#include "pyuno_impl.hxx"

using rtl::OUStringToOString;
using rtl::OUString;
using rtl::OString;
using rtl::OStringBuffer;
using rtl::OUStringBuffer;

using com::sun::star::uno::TypeDescription;
using com::sun::star::uno::Sequence;
using com::sun::star::uno::Reference;
using com::sun::star::uno::XInterface;
using com::sun::star::uno::Any;
using com::sun::star::uno::Type;
using com::sun::star::uno::UNO_QUERY;
using com::sun::star::uno::TypeClass;
using com::sun::star::uno::RuntimeException;
using com::sun::star::uno::XComponentContext;
using com::sun::star::lang::XSingleServiceFactory;
using com::sun::star::script::XTypeConverter;
using com::sun::star::beans::XMaterialHolder;

#define USTR_ASCII(x) OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
namespace pyuno
{
PyRef ustring2PyUnicode( const OUString & str )
{
    PyRef ret;
#if Py_UNICODE_SIZE == 2
    ret = PyRef( PyUnicode_FromUnicode( str.getStr(), str.getLength() ), SAL_NO_ACQUIRE );
#else
    OString sUtf8(OUStringToOString(str, RTL_TEXTENCODING_UTF8));
    ret = PyRef( PyUnicode_DecodeUTF8( sUtf8.getStr(), sUtf8.getLength(), NULL) , SAL_NO_ACQUIRE );
#endif
    return ret;
}

PyRef ustring2PyString( const OUString &str )
{
    OString o = OUStringToOString( str, osl_getThreadTextEncoding() );
    return PyRef( PyString_FromString( o.getStr() ), SAL_NO_ACQUIRE );
}

OUString pyString2ustring( PyObject *pystr )
{
    OUString ret;
    if( PyUnicode_Check( pystr ) )
    {
#if Py_UNICODE_SIZE == 2
    ret = OUString( (sal_Unicode * ) PyUnicode_AS_UNICODE( pystr ) );
#else
    PyObject* pUtf8 = PyUnicode_AsUTF8String(pystr);
    ret = OUString(PyString_AsString(pUtf8), PyString_Size(pUtf8), RTL_TEXTENCODING_UTF8);
    Py_DECREF(pUtf8);
#endif
    }
    else
    {
        char *name = PyString_AsString(pystr );
        ret = OUString( name, strlen(name), osl_getThreadTextEncoding() );
    }
    return ret;
}

PyRef getObjectFromUnoModule( const Runtime &runtime, const char * func )
    throw ( RuntimeException )
{
    PyRef object(PyDict_GetItemString( runtime.getImpl()->cargo->getUnoModule().get(), (char*)func ) );
    if( !object.is() )
    {
        OUStringBuffer buf;
        buf.appendAscii( "couldn't find core function " );
        buf.appendAscii( func );
        throw RuntimeException(buf.makeStringAndClear(),Reference< XInterface >());
    }
    return object;
}

}
<|endoftext|>


<commit_before>#include "zmqrpcsocket.h"

#include "remotemethod.h"

#include <QDataStream>
#include <QStringList>
#include <QByteArray>
#include <QDebug>
#include <QMetaMethod>
#include <QString>

ZMQRPCSocket::ZMQRPCSocket(QObject *parent) :
    ZMQSocket(parent)
{
    connect(this, &ZMQRPCSocket::messageReceived,
            this, [this](const QList<QByteArray> &message)
    {
        RemoteMethod method;

        QByteArray last = message.last();
        QDataStream out(&last, QIODevice::ReadOnly);
        out.setVersion(QDataStream::Qt_5_0);

        out >> method;

        // Try to invoke matching javascript functions inside this object

        QList<QGenericArgument> args;
        QList<QVariant>::const_iterator i;
        for(i = method.args.constBegin(); i != method.args.constEnd(); ++i){
            args << Q_ARG(QVariant, (*i));
        }

        const QMetaObject *mo = this->metaObject();

        QString signature = QString("%1()").arg(QString(method.method));
        for (int i = 0; i < method.args.count(); ++i){
            signature.insert(signature.length() - 1, "QVariant,");
        }
        signature.remove(signature.length() -2, 1);

        bool result = false;
        int index = mo->indexOfMethod(qPrintable(signature));
        if (index != -1) {
            QMetaMethod method = mo->method(index);
            result = method.invoke(this,
                                   args.value(0, QGenericArgument()),
                                   args.value(1, QGenericArgument()),
                                   args.value(2, QGenericArgument()),
                                   args.value(3, QGenericArgument()),
                                   args.value(4, QGenericArgument()),
                                   args.value(5, QGenericArgument()),
                                   args.value(6, QGenericArgument()),
                                   args.value(7, QGenericArgument()),
                                   args.value(8, QGenericArgument()),
                                   args.value(9, QGenericArgument()));
        }

        if (result)
            return;

        //TODO: search for a pure C++ method with a matching signature
    });
}

void ZMQRPCSocket::invokeRemoteMethod(const QByteArray &method, const QVariantList &args)
{
    invokeRemoteMethod(QList<QByteArray>(), method, args);
}

void ZMQRPCSocket::invokeRemoteMethod(const QList<QByteArray> &prevParts, const QByteArray &method, const QVariantList &args)
{
    RemoteMethod m;
    m.method = method;
    m.args = args;

    QByteArray content;
    QList<QByteArray> message;
    message << prevParts;

    QDataStream stream(&content, QIODevice::WriteOnly);

    stream.setVersion(QDataStream::Qt_5_0);
    stream << m;

    message << content;

    sendMessage(message);
}
<commit_msg>Fix invocation of methods with no arguments<commit_after>#include "zmqrpcsocket.h"

#include "remotemethod.h"

#include <QDataStream>
#include <QStringList>
#include <QByteArray>
#include <QDebug>
#include <QMetaMethod>
#include <QString>

ZMQRPCSocket::ZMQRPCSocket(QObject *parent) :
    ZMQSocket(parent)
{
    connect(this, &ZMQRPCSocket::messageReceived,
            this, [this](const QList<QByteArray> &message)
    {
        RemoteMethod method;

        QByteArray last = message.last();
        QDataStream out(&last, QIODevice::ReadOnly);
        out.setVersion(QDataStream::Qt_5_0);

        out >> method;

        // Try to invoke matching javascript functions inside this object

        QList<QGenericArgument> args;
        QList<QVariant>::const_iterator i;
        for(i = method.args.constBegin(); i != method.args.constEnd(); ++i){
            args << Q_ARG(QVariant, (*i));
        }

        const QMetaObject *mo = this->metaObject();

        QString signature = QString("%1()").arg(QString(method.method));

        if (method.args.count()) {
            for (int i = 0; i < method.args.count(); ++i){
                signature.insert(signature.length() - 1, "QVariant,");
            }
            signature.remove(signature.length() -2, 1);
        }

        bool result = false;
        int index = mo->indexOfMethod(qPrintable(signature));
        if (index != -1) {
            QMetaMethod method = mo->method(index);
            result = method.invoke(this,
                                   args.value(0, QGenericArgument()),
                                   args.value(1, QGenericArgument()),
                                   args.value(2, QGenericArgument()),
                                   args.value(3, QGenericArgument()),
                                   args.value(4, QGenericArgument()),
                                   args.value(5, QGenericArgument()),
                                   args.value(6, QGenericArgument()),
                                   args.value(7, QGenericArgument()),
                                   args.value(8, QGenericArgument()),
                                   args.value(9, QGenericArgument()));
        }

        if (result)
            return;

        //TODO: search for a pure C++ method with a matching signature
    });
}

void ZMQRPCSocket::invokeRemoteMethod(const QByteArray &method, const QVariantList &args)
{
    invokeRemoteMethod(QList<QByteArray>(), method, args);
}

void ZMQRPCSocket::invokeRemoteMethod(const QList<QByteArray> &prevParts, const QByteArray &method, const QVariantList &args)
{
    RemoteMethod m;
    m.method = method;
    m.args = args;

    QByteArray content;
    QList<QByteArray> message;
    message << prevParts;

    QDataStream stream(&content, QIODevice::WriteOnly);

    stream.setVersion(QDataStream::Qt_5_0);
    stream << m;

    message << content;

    sendMessage(message);
}
<|endoftext|>