text:
<?php

namespace Veonik\Bundle\BlogBundle\Form;

use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class PostType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title')
            ->add('slug')
            ->add('body', 'ckeditor')
            ->add('author', null, array(
                    'query_builder' => function (EntityRepository $entityRepository) {
                        return $entityRepository->createQueryBuilder('a')
                            ->where('a.active = true');
                    }
                ))
            ->add('author', null, array(
                'query_builder' => function (EntityRepository $entityRepository) {
                    return $entityRepository->createQueryBuilder('a')
                        ->where('a.active = true');
                }
            ))
            ->add('enableComments', 'checkbox', array('required' => false))
            ->add('active', null, array('required' => false, 'label' => 'Publish'))
            ->add('datePublished', 'date', array('required' => false, 'format' => 'MM/dd/yyyy', 'widget' => 'single_text'))
            ->add('tags', 'select2_tag', array(
                'class' => 'Veonik\Bundle\BlogBundle\Entity\Tag',
                'required' => false
            ))
            ->add('categories', 'select2_tag', array(
                'class' => 'Veonik\Bundle\BlogBundle\Entity\Category',
                'required' => false
            ));
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Veonik\Bundle\BlogBundle\Entity\Post'
        ));
    }

    public function getName()
    {
        return 'post';
    }
}


text:
"""bibliography processor
"""

def make_bibliography(aux_filename,
        bib_format=None,
        bib_encoding=None,
        output_encoding=None,
        output_backend=None,
        min_crossrefs=2,
        style=None,
        **kwargs
        ):
    """This functions extracts all nessessary information from .aux file
    and writes the bibliography.
    """

    from os import path
    from pybtex import auxfile
    from pybtex.plugin import find_plugin

    filename = path.splitext(aux_filename)[0]
    aux_data = auxfile.parse_file(aux_filename, output_encoding)

    bib_parser = find_plugin('pybtex.database.input', bib_format)
    bib_data = bib_parser(
        encoding=bib_encoding,
        wanted_entries=aux_data.citations,
        min_crossrefs=min_crossrefs,
    ).parse_files(aux_data.data, bib_parser.default_suffix)

    if style is None:
        style = aux_data.style
    style_cls = find_plugin('pybtex.style.formatting', style)
    style = style_cls(
            label_style=kwargs.get('label_style'),
            name_style=kwargs.get('name_style'),
            sorting_style=kwargs.get('sorting_style'),
            abbreviate_names=kwargs.get('abbreviate_names'),
            min_crossrefs=min_crossrefs,
    )
    formatted_bibliography = style.format_bibliography(bib_data, aux_data.citations)

    output_backend = find_plugin('pybtex.backends', output_backend)
    output_filename = filename + output_backend.default_suffix
    output_backend(output_encoding).write_to_file(formatted_bibliography, output_filename)

redpajama_set_name: RedPajamaGithub


text:
<?php

require_once(dirname(__FILE__).'/../bootstrap/functional.php');

$browser = new sfSympalTestFunctional(new sfBrowser());
$browser->signInAsAdmin();
$browser->get('/');

// Make sure we can click each menu item in the menu
$menuItems = Doctrine_Core::getTable('sfSympalMenuItem')->findAll();
foreach ($menuItems as $menuItem)
{
  if ($menuItem->level <= 0 || $menuItem->requires_auth || $menuItem->requires_no_auth || !($content = $menuItem->getContent()))
  {
    continue;
  }

  $browser->
    click($menuItem->getLabel())->
    with('response')->begin()->
      isStatusCode('200')->
    end()->
    with('request')->begin()->
      isParameter('module', 'sympal_content_renderer')->
      isParameter('action', 'index')->
    end()
  ;
}

$browser->
  get('/security/signin')->
  click('input[type="submit"]', array('signin' => array('username' => 'admin', 'password' => 'admin')), array('method' => 'post', '_with_csrf' => true))->
  with('response')->begin()->
    isRedirected()->
    followRedirect()->
  end()->
  with('user')->begin()->
    isAuthenticated()->
  end()->
  get('/admin/dashboard')->
  with('request')->begin()->
    isParameter('module', 'sympal_dashboard')->
    isParameter('action', 'index')->
  end()
;

$browser->signOut();

$browser->
  get('/register')->
  click('input[type="submit"]', array('sf_guard_user' => array('first_name' => 'Jonathan', 'last_name' => 'Wage', 'email_address' => 'jonathan.wage@sensio.com', 'username' => 'test', 'password' => 'test', 'password_again' => 'test')), array('method' => 'post', '_with_csrf' => true))->
  with('response')->begin()->
    isRedirected()->
    followRedirect()->
  end()
;

$browser->
  signOut()->
  click('Signin')->
  click('input[type="submit"]', array('signin' => array('username' => 'test', 'password' => 'test')), array('method' => 'post', '_with_csrf' => true))->
  with('user')->begin()->
    isAuthenticated()->
  end()->
  signOut()
;

$profiler = new Doctrine_Connection_Profiler();
$conn = Doctrine_Manager::connection();
$conn->addListener($profiler);

// Test base query count for pulling a page is 2
$browser->get('/pages/home');

$count = 0;
foreach ($profiler as $event)
{
  if ($event->getName() == 'execute')
  {
    $count++;
  }
}
$browser->test()->is($count, 1, 'Make sure we do not have more than 1 query');


text:
package inv

import (
	"github.com/cpmech/gosl/chk"
	"github.com/cpmech/gosl/io"
	"github.com/json-iterator/go"
)

// JSONInvoices is used for JSON file type
type JSONInvoices struct {
	FileType   string
	FileVesion int
	Invoices   []*Invoice
}

// JSONMarshaller collects the mathods marshalling or unmarshalling the csv-type data
type JSONMarshaller struct{}

// MarshalInvoices marshalls the csv-type data of invoices
func (JSONMarshaller) MarshalInvoices(fn string, invoices []*Invoice) error {
	prun("  > Writing data to .jsn or .json file %q ...\n", fn)
	j := JSONInvoices{
		FileType:   fileType,
		FileVesion: fileVesion,
		Invoices:   invoices,
	}
	// b, err := jsoniter.MarshalIndent(&j, "", "    ")
	b, err := jsoniter.Marshal(&j)
	if err != nil {
		return err
	}
	io.WriteBytesToFile(fn, b)
	return nil
}

// UnmarshalInvoices unmarshalls the csv-type data of invoices
func (JSONMarshaller) UnmarshalInvoices(fn string) ([]*Invoice, error) {
	prun("  > Reading data from .jsn or .json file %q ...\n", fn)
	b, err := io.ReadFile(fn)
	if err != nil {
		return nil, err
	}
	var j JSONInvoices
	err = jsoniter.Unmarshal(b, &j)
	if err != nil {
		return nil, err
	}
	if j.FileType != fileType {
		return nil, chk.Err("cannot read non-invoices json file")
	}
	if j.FileVesion > fileVesion {
		return nil, chk.Err("version %d is too new to read", j.FileVesion)
	}
	plog(GetInvoicesTable(j.Invoices))
	prun("    updating database ...\n")
	DBInsertFrom(j.Invoices)
	return j.Invoices, nil
}


text:
<?php

namespace WeiTest;

/**
 * @internal
 */
final class EventTest extends TestCase
{
    /**
     * @var \Wei\Event
     */
    protected $object;

    public function testEvent()
    {
        $event = $this->object;

        $results = $event->off('test')
            ->on('test', function () {
                return 'a';
            })
            ->on('test', function () {
                return 'b';
            })
            ->trigger('test');

        $this->assertEquals(['a', 'b'], $results);
    }

    public function testAddHandler()
    {
        $this->object->on('test', function () {
        });

        $this->assertTrue($this->object->has('test'));
    }

    public function testAddInvalidHandler()
    {
        $this->expectException(\InvalidArgumentException::class);

        $this->object->on('test', 'not callback');
    }

    public function testTriggerHandler()
    {
        $results = $event = $this->object->off('test')
            ->on('test', function () {
                return false;
            })
            ->trigger('test');
        $this->assertFalse($results[0]);

        $results = $this->object->off('test')
            ->on('test', function () {
                return false;
            })
            // won't be triggered
            ->on('test', function () {
                return 'second';
            })
            ->trigger('test');
        $this->assertEquals([false], $results);
    }

    public function testHasHandler()
    {
        $fn = function () {
        };
        $event = $this->object;

        $this->object->off('test')
            ->off('test.before')
            ->on('test', $fn)
            ->on('test.before', $fn);

        $this->assertTrue($event->has('test'));

        $this->assertTrue($event->has('test.before'));

        $this->assertFalse($event->has('test2'));

        $this->assertFalse($event->has('test2.ns3'));
    }

    public function testRemoveHandler()
    {
        $event = $this->object;

        $init = function () {
            $fn = function () {
            };
            $this->event->off('test')
                ->on('test', $fn)
                ->on('test.before', $fn)
                ->on('test.after', $fn)
                ->on('test.before.ns2', $fn);
        };

        $init();
        $this->assertTrue($event->has('test'));
        $this->object->off('test');
        $this->assertFalse($event->has('test'));

        $init();
        $this->assertTrue($event->has('test.before'));
        $this->object->off('test.before');
        $this->assertFalse($event->has('test.before'));

        $init();
        $this->assertTrue($event->has('test.before.ns2'));
        $this->object->off('test.before.ns2');
        $this->assertFalse($event->has('test.before.ns2'));
    }

    public function testArrayAsOnParameters()
    {
        $this->object->off('test')
            ->on([
                'test.before' => function () {
                },
                'test.after' => function () {
                },
            ]);

        $this->assertTrue($this->object->has('test.before'));
        $this->assertTrue($this->object->has('test.after'));
    }

    public function testArrayArgs()
    {
        $this->object->on('test', function ($arg) {
            return $arg;
        });

        $result = $this->object->trigger('test', ['test']);

        $this->assertEquals(['test'], $result);
    }

    public function testNotArrayArgs()
    {
        $this->object->on('test', function ($arg) {
            return $arg;
        });

        $result = $this->object->trigger('test', 'test');

        $this->assertEquals(['test'], $result);
    }

    public function testUntil()
    {
        $this->object->on(__FUNCTION__, function () {
            return null;
        });

        $this->object->on(__FUNCTION__, function () {
            return 'here';
        });

        $this->object->on(__FUNCTION__, function () {
            return 'not here';
        });

        $this->assertEquals('here', $this->object->until(__FUNCTION__));
    }
}


text:
@implementation DPPropertiesPanelCell

- (void)layoutSubviews
{
    [super layoutSubviews];
    self.contentView.backgroundColor = [UIColor clearColor];
    self.backgroundColor             = [UIColor clearColor];
}

@end


text:
RichCommon是一个基于android的基础框架库;其中包括基础Activity、Fragment、Adapter类,MVP基础框架,工具Util类,水印view, 可循环回收Imageview等View

##Usage

###For Gradle

```
dependencies {
    ......
    compile 'cn.jarlen.maven:richcommon:1.2.7'
    ......
}
```

###Using SNAPSHOT

add this to repositories section in build.gradle

```
repositories {
        maven { url 'https://raw.githubusercontent.com/jarlen/maven-repo/master/' }
        jcenter()

    }
```

##ChangeLogs

####发布richcommon1.2.7    2017-1-15

**1. 调整基于RecycleView列表多类型扩展**

编码每个类型的View,需继承**BaseRvMultiItemView**

```
public class MultiItemView1 extends BaseRvMultiItemView<Bean> {
    public MultiItemView1(Context context) {
        super(context);
    }

    @Override
    protected int getLayoutResId() {
        return R.layout.layout_rv_item_one;
    }

    @Override
    protected void onBindView(RvViewHolder viewHolder, Bean item) {
        Log.e("jarlen","onBindView--->"+viewHolder);
        TextView name = viewHolder.getView(R.id.name);
        name.setText(item.getName());
    }

    @Override
    protected boolean isForViewType(@NonNull Bean item,int position) {
        return 1 == item.getType();
    }
}
```

编码数据适配器Adapter,需继承**RvMultiAdapter**

```
private class MultiTestAdapter extends RvMultiAdapter<Bean>{

    public MultiTestAdapter(Context context) {
            super(context);
        }

        @Override
        protected void preMultiItemView(RvMultiItemManager itemManager) {
            itemManager.addMultiItemView(new MultiItemView1(mContext));
            itemManager.addMultiItemView(new MultiItemView2(mContext));
            itemManager.addMultiItemView(new MultiItemView3(mContext));
            itemManager.addMultiItemView(new MultiItemView4(mContext));
            itemManager.addMultiItemView(new MultiItemView0(mContext));
        }
    }
```

**Sample**

```
public class RvMultiActivity extends BaseActivity {

    private RecyclerView recyclerView;
    private MultiTestAdapter testAdapter;
    @Override
    protected int getLayoutId() {
        return R.layout.activity_rv_adapter;
    }

    @Override
    protected void onBindView() {
        recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
        testAdapter = new MultiTestAdapter(this);
        recyclerView.setAdapter(testAdapter);
        List<Bean> datas = new ArrayList<Bean>();
        for (int index = 0; index < 1000; index++) {
            Bean bean = new Bean();
            bean.setType(index % 3);
            bean.setName("test " + index);

            datas.add(bean);
        }
        testAdapter.addDataList(datas);
    }

    @Override
    protected void preBindView() {

    }
}
```

PS: 补充两点:

1、对于大多数多类型列表数据,每条数据格式不同,那么应该为JSONArray类型,每个item为JSONObject,可以将JSONArray分解成JSONObject数组使用。

2、很少相同的数据,那么item数据格式相同。那么无需转成JSONObject数组,直接转换成Bean List即可。

**2. 调整MVP模式框架,分离组合接口**,以下例子:

编码View层接口,需继承**IBaseView**

```
public interface IAddView extends IBaseView {
    void showAdd(String sum);
}
```

编码Presenter层接口,需继承**IBasePresenter**

```
public interface IAdd extends IBasePresenter {
    void add(String a, String b);
}
```

编码Presenter层业务,需继承**BaseActivityPresenter**,补充泛型参数(**IAddView**为View层接口),并实现**IAdd**接口

```
public class AddPresenter extends BaseActivityPresenter<IAddView> implements IAdd{
    @Override
    public void add(String a, String b) {
        int sum = Integer.valueOf(a) + Integer.valueOf(b);
        getProxyView().showAdd(""+sum);
    }
}
```

实现View层接口及界面所需参数,需继承**BaseMvpActivity**,补充泛型参数(**IAdd**为Presenter层接口,**IAddView**为View层接口),并实现**IAddView**接口

```
public class AddActivity extends BaseMvpActivity<IAdd, IAddView> implements IAddView, View.OnClickListener {

    private TextView result;
    private Button testBtn;
    private EditText inputOne;
    private EditText inputTwo;

    @Override
    public Class<AddPresenter> getPresenter() {
        return AddPresenter.class;
    }

    @Override
    public IAddView getProxyView() {
        return this;
    }

    @Override
    public int getLayoutId() {
        return R.layout.layout_mvp;
    }

    @Override
    public void onBindView(Bundle savedInstanceState) {
        result = (TextView) findViewById(R.id.result);
        testBtn = (Button) findViewById(R.id.testBtn);
        testBtn.setOnClickListener(this);
        inputOne = (EditText) findViewById(R.id.input_one);
        inputTwo = (EditText) findViewById(R.id.input_two);
    }

    @Override
    public void preBindView() {
    }

    @Override
    public void showAdd(String sum) {
        result.setText(sum);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.testBtn:
                Intent intent = new Intent(AddActivity.this, RvMultiActivity.class);
                startActivity(intent);
                getProxyPresenter().add(inputOne.getText().toString(), inputTwo.getText().toString());
                break;
            default:
                break;
        }
    }
}
```

**3. 调整基础Activity/Fragment基础类,不需要一定实现preBindView()接口**

####发布 richcommon1.2.4        2016-12-13

**RvCommonAdapter的扩展,支持多类型ItemView的列表 **

```
public int getLayoutResId(int viewType) {

            switch (viewType) {
                case 0:
                    return R.layout.layout_rv_item_one;
                case 1:
                    return R.layout.layout_rv_item_two;
                case 2:
                    return R.layout.layout_rv_item_three;
                case 3:
                    return R.layout.layout_rv_item_four;

                default:

                    return R.layout.layout_rv_item_one;

            }
        }

```

**CommonAdapter的扩展,支持多类型ItemView的列表 **

```
public int getLayoutResId(int position) {
                return R.layout.layout_list_item;
            }
```

**实现MVP基础架构**

**View : **基于activity、fragment

1. 支持泛型
2. Code量较少
3. 不用关心MVP之间的流程

--- 基于 Activity

1. 继承IBaseView, 编写View层显示接口

```
public interface AddView extends IBaseView {
    void showAdd(String sum);
}
```

2. 继承BaseMvpActivity, 实现VIew层接口

类头:
AddActivity extends BaseMvpActivity<AddPresenter, AddView> implements AddView

```
 @Override
    public void showAdd(String sum) {
        result.setText(sum);
    }
```
3. 继承 BaseActivityPresenter,实现业务层逻辑

```
public class AddPresenter extends BaseActivityPresenter<AddView> {

    public void add(String a, String b) {
        int sum = Integer.valueOf(a) + Integer.valueOf(b);
        getView().showAdd("" + sum);
    }
}
```

--- 基于 Fragment

1. 继承IBaseView, 编写View层显示接口
2. 继承BaseMvpFragment, 实现VIew层接口
3. 继承 BaseFragmentPresenter,实现业务层逻辑

####发布  richcommon1.2.3        2016-11-15

 进一步优化可复用的Adapter

 1.**支持泛型**

 2.**Code量更少**

* 基于**ListView**的Adapter的**CommonAdapter**

```
commonAdapter = new CommonAdapter<String>(this) {
            @Override
            public void onBindView(ViewHolder viewHolder, String item) {
                TextView tv = viewHolder.getView(R.id.tv);
                tv.setText(item);
            }

            @Override
            public int getLayoutResId() {
                return R.layout.layout_list_item;
            }
        };
mListView.setAdapter(commonAdapter);
```

* 基于**RecycleView.Adapter**的**RvCommonAdapter**

```
    @Override
    public void onBindView(RvViewHolder viewHolder, String item) {
        ImageView image = viewHolder.getView(R.id.iv_image);
        Bitmap bitmap = ImageUtils.getBitmapByPath(item);
        image.setImageBitmap(bitmap);
    }
```

* 基于**RecycleView.Adapter**的**RvViewHolder**

		与ViewHolder相似

####发布 richcommon1.2.2     2016-8-30
* 添加水印view、可循环回收的Imageview

##一、包:Adapter
###1、extends SimpleBaseAdapter 实现getView();

   * 支持泛型
   * 代码量少
   * 可结合ViewHolder使用

###2、ViewHolder 超级复用(getView)

   * 可复用
   * 代码量少
   * 与Adapter相结合

```
ViewHolder viewholder = ViewHolder.getViewHolder(Context context, ViewGroup parent,View convertView, int position, int layoutId);
TextView tv = viewholder.getView(resId);
return viewholder.getConvertView();
```

##二、utils

###1、AppUtil

* public static String getAppVersion(Context context)
* public static void uninstallApp(Context context, String packageName)
* public static boolean isAppInstalled(Context context, String packageName)
* public static ApplicationInfo getApplicationInfo(Context context, String packageName)
* public static List<PackageInfo> getPackageInfos(Context context)
* public static void startApp(Context ctx, String packageName)

###2、FileUtil

* public static boolean deleteFile(File file)
* public static boolean deleteFile(String filePath)
* public static boolean createFile(File file)
* public static boolean createFile(String filePath)
* public static boolean createDirectory(String dirPath)
* public static boolean moveFile(String srcPath, String dstPath, boolean isForce)
* public static boolean isGifImage(File srcPath)
* public static long getsize(File file)
* public static String getFileSHA1(String path)
* public static String getFileMD5(String path)
* public static String getFileSize(long length)

###3、PreferenceUtils

* public static PreferenceUtils newInstance(Context context, String name)

###4、SystemUtil

* public final static boolean isMainThread()
* public static long getMemoryUnused(Context mContext)
* public static int getUid(Context context)
* public static void reStartApp(Context context, Class<?> clazz)
* public static boolean isRooted()
* public static void lockScreen(Context context)
* public static String getIMEI(Context context)
* public static String getBluetoothMac()
* public static String getWlanMac(Context context)
* public static float getAndroidVersion()
* public static int dp2px(Context context, float dpValue)
* public static int px2dp(Context context, int px)
* public static int sp2px(Context context, float sp)
* public static int getStatusBarHeight(Context context)
* public static int getStatusBarHeight2(Context context)
* public static float getScreenInches(Context context)
* public static int getDensity(Context context)
* public static String getRomTotalSize(Context context)
* public static String getRomAvailableSize(Context context)
* public static void scanSdCard(Context context)
* public static void scanSdCard(Context context, String filePath, MediaScannerConnection.OnScanCompletedListener listener)

###5、TimeUtil

* public static int getToday()
* public static String getToday2()

###6、ToastUtil

* public static ToastUtil makeToast(Context ctx)
* public ToastUtil setText(String message)
* public ToastUtil setGravity(int gravity)
* public ToastUtil setImage(int picId)
* public ToastUtil setDuration(int duration)
* public void show()


text:
#include "mod_ox.h"
#include "proc_saml.h"
#include "oxd_main.h"

/*
* check oxd discovery infos in memcached.
* true : unchanged, false : changed
*/
static bool check_discovery_infos(mod_ox_config *s_cfg)
{
	bool ret = true;

	char *oxdhost = Get_Ox_Storage(s_cfg->OpenIDClientName, "oxd.oxdhost");
	char *discovery = Get_Ox_Storage(s_cfg->OpenIDClientName, "connect.discovery");
	char *redirect = Get_Ox_Storage(s_cfg->OpenIDClientName, "connect.redirect");
	char *clientname = Get_Ox_Storage(s_cfg->OpenIDClientName, "oxd.clientname");
	char *creditpath = Get_Ox_Storage(s_cfg->OpenIDClientName, "oxd.creditpath");
	char *uma_discovery = Get_Ox_Storage(s_cfg->OpenIDClientName, "uma.discovery");
	char *uma_resource = Get_Ox_Storage(s_cfg->OpenIDClientName, "uma.resource");
	char *uma_rshost = Get_Ox_Storage(s_cfg->OpenIDClientName, "uma.rshost");

	if (!oxdhost || !discovery || !redirect || !clientname || !uma_discovery || !uma_resource || !uma_rshost || (!creditpath && s_cfg->ClientCredsPath))
	{
		Set_Ox_Storage(s_cfg->OpenIDClientName, "oxd.oxdhost", s_cfg->OxdHostAddr, 0);
		Set_Ox_Storage(s_cfg->OpenIDClientName, "connect.discovery", s_cfg->OpenIDProvider, 0);
		Set_Ox_Storage(s_cfg->OpenIDClientName, "connect.redirect", s_cfg->OpenIDClientRedirectURIs, 0);
		Set_Ox_Storage(s_cfg->OpenIDClientName, "oxd.clientname", s_cfg->OpenIDClientName, 0);
		Set_Ox_Storage(s_cfg->OpenIDClientName, "oxd.creditpath", s_cfg->ClientCredsPath, 0);
		Set_Ox_Storage(s_cfg->OpenIDClientName, "uma.discovery", s_cfg->UmaAuthorizationServer, 0);
		Set_Ox_Storage(s_cfg->OpenIDClientName, "uma.resource", s_cfg->UmaResourceName, 0);
		Set_Ox_Storage(s_cfg->OpenIDClientName, "uma.rshost", s_cfg->uma_rs_host, 0);

		ret = false;
		goto EXIT_check_discovery_infos;
	}

	if (strcmp(oxdhost, s_cfg->OxdHostAddr) ||
		strcmp(discovery, s_cfg->OpenIDProvider) ||
		strcmp(redirect, s_cfg->OpenIDClientRedirectURIs) ||
		strcmp(clientname, s_cfg->OpenIDClientName) ||
		strcmp(uma_discovery, s_cfg->UmaAuthorizationServer) ||
		strcmp(uma_resource, s_cfg->UmaResourceName) ||
		strcmp(uma_rshost, s_cfg->uma_rs_host) ||
		(s_cfg->ClientCredsPath && strcmp(creditpath, s_cfg->ClientCredsPath)))
	{
		Set_Ox_Storage(s_cfg->OpenIDClientName, "oxd.oxdhost", s_cfg->OxdHostAddr, 0);
		Set_Ox_Storage(s_cfg->OpenIDClientName, "connect.discovery", s_cfg->OpenIDProvider, 0);
		Set_Ox_Storage(s_cfg->OpenIDClientName, "connect.redirect", s_cfg->OpenIDClientRedirectURIs, 0);
		Set_Ox_Storage(s_cfg->OpenIDClientName, "oxd.clientname", s_cfg->OpenIDClientName, 0);
		Set_Ox_Storage(s_cfg->OpenIDClientName, "oxd.creditpath", s_cfg->ClientCredsPath, 0);
		Set_Ox_Storage(s_cfg->OpenIDClientName, "uma.discovery", s_cfg->UmaAuthorizationServer, 0);
		Set_Ox_Storage(s_cfg->OpenIDClientName, "uma.resource", s_cfg->UmaResourceName, 0);
		Set_Ox_Storage(s_cfg->OpenIDClientName, "uma.rshost", s_cfg->uma_rs_host, 0);

		ret = false;
		goto EXIT_check_discovery_infos;
	}

EXIT_check_discovery_infos:
	if (oxdhost) free(oxdhost);
	if (discovery) free(discovery);
	if (redirect) free(redirect);
	if (clientname) free(clientname);
	if (creditpath) free(creditpath);
	if (uma_discovery) free(uma_discovery);
	if (uma_resource) free(uma_resource);
	if (uma_rshost) free(uma_rshost);

	return ret;
};

static void set_rpt_cookie(request_rec *r, mod_ox_config *s_cfg, opkele::params_t& params)
{
	// now set auth cookie, if we're doing session based auth
	std::string session_id, hostname, path, cookie_value, state, redirect_location, args;
	int expires_in;
	if(s_cfg->CookiePath != NULL)
		path = std::string(s_cfg->CookiePath);
	else
		modox::base_dir(std::string(r->uri), path);

	modox::make_rstring(32, session_id);
	expires_in = 0;

	modox::make_cookie_value(cookie_value, std::string(s_cfg->cookie_name), session_id, path, expires_in, false);
	apr_table_set(r->err_headers_out, "Set-Cookie", cookie_value.c_str());
	hostname = std::string(r->hostname);

	// save session values
	std::string session_str = session_id + ";";
	session_str += hostname + ";";
	session_str += path + ";";
	session_str += "identity;";
	session_str += "username";
	Set_Ox_Storage(s_cfg->OpenIDClientName, session_id.c_str(), session_str.c_str(), expires_in);

	r->args = NULL;

	return;
};

/*
* save session value after succeed in authorize.
*/
static void set_valid_session(request_rec *r, mod_ox_config *s_cfg) {
	// test for valid session
	std::string session_id = "";
	std::string session_key = "";
	std::string session_value = "";
	modox::get_session_id(r, std::string(s_cfg->cookie_name), session_key, session_id);
	modox::get_session_id(r, "_shibsession_", session_key, session_value);

	if(session_id != "" && session_key != "" && session_value != "")
	{
		std::string session_cookie = session_value;
		session_cookie += ".cookie";

		Set_Ox_Storage(s_cfg->OpenIDClientName, session_cookie.c_str(), session_key.c_str(), 0);
	}
};

/*
* start the process for authentication.
*/
int start_saml_session(request_rec *r, mod_ox_config *s_cfg, opkele::params_t& params)
{
	int ret;
	bool info_changed = false;

	modox::remove_openid_vars(params);

	ret = 0;
	if (check_discovery_infos(s_cfg) == true)	// unchanged
	{
		// Discovery & Register Client
		char *issuer = Get_Ox_Storage(s_cfg->OpenIDClientName, "oxd.issuer");
		char *authorization_endpoint = Get_Ox_Storage(s_cfg->OpenIDClientName, "oxd.authorization_endpoint");
		char *client_id = Get_Ox_Storage(s_cfg->OpenIDClientName, "oxd.client_id");
		char *client_secret = Get_Ox_Storage(s_cfg->OpenIDClientName, "oxd.client_secret");
		if ((issuer==NULL) || (authorization_endpoint==NULL) || (client_id==NULL) || (client_secret==NULL))
		{
			info_changed = true;
			ret = ox_discovery(s_cfg);
		}
		if (issuer) free(issuer);
		if (authorization_endpoint) free(authorization_endpoint);
		if (client_id) free(client_id);
		if (client_secret) free(client_secret);
		if (ret < 0) return show_error(r, s_cfg, "Oxd failed to discovery");

		// Obtain PAT & Register Resource
		char *pat_token = Get_Ox_Storage(s_cfg->OpenIDClientName, "uma.pat_token");
		if (pat_token==NULL)
		{
			if (ox_obtain_pat(s_cfg) < 0) return show_error(r, s_cfg, "Oxd failed to obtain PAT");
			if (ox_register_resources(s_cfg) < 0) return show_error(r, s_cfg, "Oxd failed to register Resource");
		}
		else
		{
			free(pat_token);

			std::string id = std::string(s_cfg->UmaResourceName); id += "_id";
			std::string rev = std::string(s_cfg->UmaResourceName); rev += "_rev";
			char *resource_id = Get_Ox_Storage(s_cfg->OpenIDClientName, id.c_str());
			char *resource_rev = Get_Ox_Storage(s_cfg->OpenIDClientName, rev.c_str());

			if (!resource_id || !resource_rev)
				ret = ox_register_resources(s_cfg);

			if (resource_id) free(resource_id);
			if (resource_rev) free(resource_rev);
			if (ret < 0) return show_error(r, s_cfg, "Oxd failed to register Resource");
		}

		// Obtain AAT Token
		char *aat_token = Get_Ox_Storage(s_cfg->OpenIDClientName, "uma.aat_token");
		if ((aat_token==NULL))
		{
			if (ox_obtain_aat(s_cfg) < 0) return show_error(r, s_cfg, "Oxd failed to obtain AAT");
		}
		else
			free(aat_token);

		// 5. Obtain RPT Token
		char *rpt_token = Get_Ox_Storage(s_cfg->OpenIDClientName, "uma.rpt_token");
		if ((rpt_token==NULL))
		{
			if (ox_obtain_rpt(s_cfg) < 0) return show_error(r, s_cfg, "Oxd failed to obtain RPT");
		}
		else
			free(rpt_token);
	}
	else	// changed
	{
		info_changed = true;
		// Discovery & Register Client
		if (ox_discovery(s_cfg) < 0) return show_error(r, s_cfg, "Oxd failed to discovery");
		// Obtain PAT
		if (ox_obtain_pat(s_cfg) < 0) return show_error(r, s_cfg, "Oxd failed to obtain PAT");
		// Register Resource
		if (ox_register_resources(s_cfg) < 0) return show_error(r, s_cfg, "Oxd failed to register Resource");
		// Obtain AAT
		if (ox_obtain_aat(s_cfg) < 0) return show_error(r, s_cfg, "Oxd failed to obtain AAT");
		// Obtain RPT
		if (ox_obtain_rpt(s_cfg) < 0) return show_error(r, s_cfg, "Oxd failed to obtain RPT");
	}

	set_rpt_cookie(r, s_cfg, params);

	params["target"] = "https://";
	params["target"] += r->hostname;
	params["target"] += r->uri;
	params["path"] = std::string(r->uri);
	params["attrs"] = std::string(s_cfg->uma_sent_user_claims);
	std::string auth_end;
	auth_end = std::string(s_cfg->SAMLRedirectUrl);

	return modox::http_redirect(r, params.append_query(auth_end, ""));
};

/*
* check to has session for shibd
*/
int has_saml_session(request_rec *r, mod_ox_config *s_cfg, opkele::params_t& params)
{
	// test for valid session
	std::string session_id = "";
	std::string session_key = "";
	std::string session_value = "";
	modox::get_session_id(r, std::string(s_cfg->cookie_name), session_key, session_id);
	modox::get_session_id(r, "_shibsession_", session_key, session_value);

	if(session_id != "" && session_key != "" && session_value != "")
	{
		modox::debug("found session_id in cookie: " + session_id);

		// Check valid session is saved
		std::string session_cookie = session_value;
		session_cookie += ".cookie";

		char *cookie_str = Get_Ox_Storage(s_cfg->OpenIDClientName, session_cookie.c_str());
		if (cookie_str != NULL)
		{
			if (!strcmp(cookie_str, session_key.c_str()))
			{
				free(cookie_str);
				return 1;
			}
			free(cookie_str);
		}

		// Check session value
		modox::session_t session;

		char *session_str = Get_Ox_Storage(s_cfg->OpenIDClientName, session_id.c_str());
		char *ptr6, *ptr7, *ptr8, *ptr9, *ptr10;
		ptr6 = strtok(session_str, ";");
		ptr7 = strtok(NULL, ";");
		ptr8 = strtok(NULL, ";");
		ptr9 = strtok(NULL, ";");
		ptr10 = strtok(NULL, ";");

		session.session_id = std::string(ptr6);
		session.hostname = std::string(ptr7);
		session.path = std::string(ptr8);
		session.identity = std::string(ptr9);
		session.username = std::string(ptr10);

		// if session found
		if(session.identity != "")
		{
			std::string uri_path;
			modox::base_dir(std::string(r->uri), uri_path);
			std::string valid_path(session.path);
			// if found session has a valid path
			if(valid_path == uri_path.substr(0, valid_path.size()) && strcmp(session.hostname.c_str(), r->hostname)==0)
			{
				const char* idchar = session.identity.c_str();
				r->user = apr_pstrdup(r->pool, idchar);

				if (session_str) free(session_str);
				return 0;
			}
		}

		if (session_str) free(session_str);
	}

	return -1;
};

/*
* check the validation of session
*/
int validate_saml_session(request_rec *r, mod_ox_config *s_cfg, opkele::params_t& params)
{
	if (ox_obtain_rpt(s_cfg) < 0)
		return HTTP_FORBIDDEN;

	if (ox_register_ticket(s_cfg) < 0)
		return HTTP_FORBIDDEN;

	// test for valid session
	std::string session_id = "";
	std::string session_key = "";
	std::string session_value = "";
	modox::get_session_id(r, std::string(s_cfg->cookie_name), session_key, session_id);
	modox::get_session_id(r, "_shibsession_", session_key, session_value);
	if (session_value != "")
	{
		if (ox_authorize_rpt(s_cfg, session_value.c_str()) < 0)
			return HTTP_FORBIDDEN;
	}

	if (ox_check_rpt_status(s_cfg) < 0)
		return HTTP_FORBIDDEN;

	set_valid_session(r, s_cfg);

	return 0;
};


text:
using namespace std;

template <class ImageType, int nSegmentationLabels>
class SegmentationPropagationModular{
public:
    typedef typename ImageType::PixelType PixelType;
    static const unsigned int D=ImageType::ImageDimension;
    typedef typename  ImageType::Pointer ImagePointerType;
    typedef typename  ImageType::IndexType IndexType;
    typedef typename  ImageType::PointType PointType;
    typedef typename  ImageType::OffsetType OffsetType;
    typedef typename  ImageType::SizeType SizeType;
    typedef typename  ImageType::ConstPointer ImageConstPointerType;
    typedef typename  ImageUtils<ImageType>::FloatImageType FloatImageType;
    typedef typename  FloatImageType::Pointer FloatImagePointerType;

    typedef  TransfUtils<ImageType,double> TransfUtilsType;

    typedef typename  TransfUtilsType::DisplacementType DisplacementType; typedef typename  TransfUtilsType::DeformationFieldType DeformationFieldType;
    typedef typename  DeformationFieldType::Pointer DeformationFieldPointerType;
    typedef typename  itk::ImageRegionIterator<ImageType> ImageIteratorType;
    typedef typename  itk::ImageRegionIterator<FloatImageType> FloatImageIteratorType;
    typedef typename  itk::ImageRegionIterator<DeformationFieldType> DeformationIteratorType;
    typedef typename  itk::ConstNeighborhoodIterator<ImageType> ImageNeighborhoodIteratorType;
    typedef   ImageNeighborhoodIteratorType * ImageNeighborhoodIteratorPointerType;
    typedef typename  ImageNeighborhoodIteratorType::RadiusType RadiusType;

    typedef itk::Vector<float,nSegmentationLabels> ProbabilisticPixelType;
    typedef itk::Image<ProbabilisticPixelType,D> ProbabilisticVectorImageType;
    typedef typename ProbabilisticVectorImageType::Pointer ProbabilisticVectorImagePointerType;
    typedef typename itk::ImageRegionIterator<ProbabilisticVectorImageType> ProbImageIteratorType;

    typedef std::vector<std::pair<string,ImagePointerType> > ImageListType;

    enum MetricType {NONE,MAD,NCC,MI,NMI,MSD};
    enum WeightingType {UNIFORM,GLOBAL,LOCAL};
protected:
    double m_sigma;
    RadiusType m_patchRadius;
public:
    int run(int argc, char ** argv){
        feenableexcept(FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW);
        ArgumentParser * as=new ArgumentParser(argc,argv);
        string deformationFileList,imageFileList,atlasSegmentationFileList,supportSamplesListFileName="",outputDir=".",outputSuffix="",weightListFilename="", imageFileListAtlas="";
        int verbose=0;
        double pWeight=1.0;
        double radius=3;
        int maxHops=1;
        bool uniformUpdate=true;
        string metricName="NCC";
        string weightingName="uniform";
        bool lateFusion=false;
        bool dontCacheDeformations=false;
        bool graphCut=false;
        double smoothness=1.0;
        double m_graphCutSigma=10;
        int useNAtlases=1000000;
        int useNTargets=1000000;
        double globalOneHopWeight=1.0;
        bool AREG= false;
        m_sigma=30;
        as->parameter ("A",atlasSegmentationFileList , "list of atlas segmentations <id> <file>", true);
        as->parameter ("T", deformationFileList, " list of deformations", true);
        as->parameter ("i", imageFileList, " list of target images", true);
        as->parameter ("iAtlas", imageFileListAtlas, " list of atlas images (if not set, target image filelist is assumed to contain both atlas and target images)", false);
        as->parameter ("W", weightListFilename,"list of weights for deformations",false);
        as->parameter ("metric", metricName,"metric to be used for global or local weighting, valid: NONE,SAD,MSD,NCC,MI,NMI",false);
        as->parameter ("weighting", weightingName,"internal weighting scheme {uniform,local,global}. non-uniform will only work with metric != NONE",false);
        as->parameter ("s", m_sigma,"sigma for exp(- metric/sigma)",false);
        as->parameter ("sigmaGC", m_graphCutSigma,"sigma for exp(- contrast/sigma) for graphcut smoothness",false);
        as->parameter ("radius", radius,"patch radius for local metrics",false);
        as->parameter ("O", outputDir,"outputdirectory (will be created + no overwrite checks!)",false);
        as->parameter ("radius", radius,"patch radius for NCC",false);
        as->parameter ("maxHops", maxHops,"maximum number of hops",false);
        as->parameter ("useNAtlases", useNAtlases,"use the first N atlases from the list",false);
        as->parameter ("useNTargets", useNTargets,"use the first N targets as intermediate images",false);
        as->parameter ("globalOneHopWeight", globalOneHopWeight,"global weight for one hop segmentations (vs. zero hop)",false);
        as->option ("AREG", AREG,"use AREG to select intermediate targets");
        as->option ("lateFusion", lateFusion,"fuse segmentations late. maxHops=1");
        as->option ("dontCacheDeformations", dontCacheDeformations,"read deformations only when needed to save memory. higher IO load!");
        as->option ("graphCut", graphCut,"use graph cuts to generate final segmentations instead of locally maximizing");
        as->parameter ("smoothness", smoothness,"smoothness parameter of graph cut optimizer",false);
        as->parameter ("verbose", verbose,"get verbose output",false);
        as->help();
        as->parse();
        string suffix;
        if (D==2)
            suffix=".png";
        else
            suffix=".nii.gz";

        //late fusion is only well defined for maximal 1 hop.
        //it requires to explicitly compute all n!/(n-nHops) deformation paths to each image and is therefore infeasible for nHops>1
        //also strange to implement
        if (lateFusion)
            maxHops==min(maxHops,1);

        for (unsigned int i = 0; i < ImageType::ImageDimension; ++i) m_patchRadius[i] = radius;

        mkdir(outputDir.c_str(),0755);
        logSetStage("IO");
        logSetVerbosity(verbose);

        MetricType metric;
        if (metricName=="NONE")
            metric=NONE;
        else if (metricName=="MSD")
            metric=MSD;
        else if (metricName=="MAD")
            metric=MAD;
        else if (metricName=="NCC")
            metric=NCC;
        else if (metricName=="NMI")
            metric=NMI;
        else if (metricName=="MI")
            metric=MI;
        else{
            LOG<<"don't understand "<<metricName<<", defaulting to NONE"<<endl;
            metric=NONE;
        }
        WeightingType weighting;
        if (weightingName=="uniform" || metric==NONE){
            weighting=UNIFORM;}
        else if (weightingName=="global")
            weighting=GLOBAL;
        else if (weightingName=="local"){
            weighting=LOCAL;
            if (metric==NMI || metric == MI ){
                LOG<<VAR(metric)<<" incompatibel with local weighing, aborting"<<endl;
                exit(0);
            }
        }
        else{
            LOG<<"don't understand "<<VAR(weightingName)<<", defaulting to uniform."<<endl;
            weighting=UNIFORM;
        }

        ImageListType *targetImages,*inputAtlasSegmentations, *atlasImages;
        map<string,int> *targetIDMap,*atlasSegmentationIDMap, *atlasIDMap;
        targetIDMap=new   map<string,int> ;
        atlasSegmentationIDMap=new   map<string,int> ;
        atlasIDMap=new   map<string,int> ;

        typedef typename ImageListType::iterator ImageListIteratorType;
        LOG<<"Reading atlas segmentations."<<endl;
        inputAtlasSegmentations = readImageList( atlasSegmentationFileList, atlasSegmentationIDMap );

        LOG<<VAR(atlasSegmentationIDMap)<<endl;

        SegmentationMapper<ImageType> segmentationMapper;
        //map segmentation labels to continuous discrete range
        for (ImageListIteratorType it=inputAtlasSegmentations->begin();it!=inputAtlasSegmentations->end();++it){
            it->second=segmentationMapper.ApplyMap(it->second);
        }

        int nAtlases = inputAtlasSegmentations->size();
        useNAtlases=min(useNAtlases,nAtlases);

        LOG<<"Reading input images."<<endl;
        targetImages = readImageList( imageFileList, targetIDMap );
        int nImages = targetImages->size();
        useNTargets=min(nImages,useNTargets);
        if (imageFileListAtlas != ""){
            atlasImages=readImageList(imageFileListAtlas, atlasIDMap);
        }else{
            for (ImageListIteratorType targetImageIterator=targetImages->begin();targetImageIterator!=targetImages->end();++targetImageIterator){
                string targetID = targetImageIterator->first;
                //add target image to atlas images if it is in the list of atlas segmentations
                if ( atlasSegmentationIDMap->find(targetID)!=atlasSegmentationIDMap->end()){
                    atlasImages->push_back(make_pair(targetID,targetImageIterator->second));
                }
            }
        }

        LOGV(2)<<VAR(metric)<<" "<<VAR(weighting)<<endl;
        LOGV(2)<<VAR(m_sigma)<<" "<<VAR(lateFusion)<<" "<<VAR(m_patchRadius)<<endl;

        if (dontCacheDeformations){
            LOG<<"Reading deformation file names."<<endl;
        }else{
            LOG<<"CACHING all deformations!"<<endl;
        }
        map< string, map <string, DeformationFieldPointerType> > deformationCache;
        map< string, map <string, string> > deformationFilenames;
        map<string, map<string, float> > globalWeights;
        {
            ifstream ifs(deformationFileList.c_str());
	    LOGV(3)<<"Reading deformation filenames from " << deformationFileList << endl;
            while (!ifs.eof()){
                string intermediateID,targetID,defFileName;
                ifs >> intermediateID;
		LOGV(3)<<VAR(intermediateID)<<endl;
                if (intermediateID!=""){
                    ifs >> targetID;
                    ifs >> defFileName;
                    //skip inter-atlas deformations
                    //if ( (    targetImages->find(intermediateID)==targetImages->end() && atlasImages->find(intermediateID)==targetImages->end()) || targetImages->find(targetID)==targetImages->end()  ){
                    if  (    false && atlasSegmentationIDMap->find(targetID)!=atlasSegmentationIDMap->end() ){
                        LOG<<intermediateID<<" or "<<targetID<<" not in image database, skipping"<<endl;
                        //exit(0);
                    }else{
                        if (!dontCacheDeformations){
                            LOGV(3)<<"Reading deformation "<<defFileName<<" for deforming "<<intermediateID<<" to "<<targetID<<endl;
                            deformationCache[intermediateID][targetID]=ImageUtils<DeformationFieldType>::readImage(defFileName);
                            globalWeights[intermediateID][targetID]=1.0;
                        }else{
                            LOGV(3)<<"Reading filename "<<defFileName<<" for deforming "<<intermediateID<<" to "<<targetID<<endl;
                            deformationFilenames[intermediateID][targetID]=defFileName;
                            globalWeights[intermediateID][targetID]=1.0;
                        }
                    }
                }
            }
        }

        if (weightListFilename!=""){
            ifstream ifs(weightListFilename.c_str());
            while (!ifs.eof()){
                string intermediateID,targetID;
                ifs >> intermediateID;
                ifs >> targetID;
                if (false)
                    LOG << intermediateID<<" or "<<targetID<<" not in image database while reading weights, skipping"<<endl;
                else{
                    ifs >> globalWeights[intermediateID][targetID];
                }
            }
        }

        logSetStage("Zero Hop");
        LOG<<"Computing"<<std::endl;
        map<string,ProbabilisticVectorImagePointerType> probabilisticSegmentations;

        //generate atlas probabilistic segmentations from atlas segmentations
        for (ImageListIteratorType atlasImageIterator=inputAtlasSegmentations->begin();atlasImageIterator!=inputAtlasSegmentations->end();++atlasImageIterator){
            //iterate over atlass
            string atlasID = atlasImageIterator->first;
            LOGV(3)<<VAR(atlasID)<<endl;
            probabilisticSegmentations[atlasID]=segmentationToProbabilisticVector(atlasImageIterator->second);
        }

#if 1
        if (AREG){
            LOG<<"Resorting intermediate targets based on ARE-G"<<endl;
            //re-sort target images to yield improving atlas reconstruction error
            double areG=1000000.0;
            int i=0;
            map<string,ProbabilisticVectorImagePointerType> probabilisticAtlasSelfSegmentations;
            int atlasN = 0;
            for (ImageListIteratorType atlasIterator=inputAtlasSegmentations->begin();atlasIterator!=inputAtlasSegmentations->end() && (atlasN<useNAtlases);++atlasIterator,++atlasN){//iterate over atlases
                probabilisticAtlasSelfSegmentations[atlasIterator->first]=  createEmptyProbImageFromImage(atlasIterator->second);
            }

            for (ImageListIteratorType targetImageIterator=targetImages->begin();targetImageIterator!=targetImages->end() && i<useNTargets;++targetImageIterator,++i){
                LOGV(2)<<"Processing "<<i<<"the intermediate image"<<endl;
                double bestARE=100000.0;
                string bestID;
                int bestIdx;
                int j=i;
                for (ImageListIteratorType targetImageIterator2=targetImageIterator;targetImageIterator2!=targetImages->end();++targetImageIterator2,++j){
                    string targetID = targetImageIterator2->first;
                    LOGV(2)<<"Probing image "<<targetID<<endl;
                    double localARE=0.0;
                    atlasN=0;
                    for (ImageListIteratorType atlasIterator=inputAtlasSegmentations->begin();atlasIterator!=inputAtlasSegmentations->end() && (atlasN<useNAtlases);++atlasIterator,++atlasN){//iterate over atlases
                        string atlasID = atlasIterator->first;
                        if (atlasID == targetID){
                            LOGV(2)<<"Target equals atlas, skipping.. " <<endl;
                            localARE=1.0;
                            continue;
                        }else{
                        ProbabilisticVectorImagePointerType probAtlasSeg=ImageUtils<ProbabilisticVectorImageType>::duplicate(probabilisticAtlasSelfSegmentations[atlasID]);
                        //todo: propagate atlas segmentation forward backward
                        //todo accumulate atlas segmentations
                        DeformationFieldPointerType firstDeformation,secondDeformation,deformation;
                        if (dontCacheDeformations){
                            firstDeformation = ImageUtils<DeformationFieldType>::readImage(deformationFilenames[atlasID][targetID]);
                            secondDeformation = ImageUtils<DeformationFieldType>::readImage(deformationFilenames[targetID][atlasID]);
                        }else{
                            firstDeformation = deformationCache[atlasID][targetID];
                            secondDeformation = deformationCache[targetID][atlasID];
                        }

                        deformation = TransfUtilsType::composeDeformations(secondDeformation,firstDeformation);
                        ProbabilisticVectorImagePointerType probSeg=probabilisticSegmentations[atlasID];
                        double weight = 1.0;
                        updateProbabilisticSegmentationLocalMetricNew(probAtlasSeg,probSeg,weight,targetImageIterator->second,(*atlasImages)[(*atlasIDMap)[atlasID]].second,deformation,metric);
                        ImagePointerType outputImage=probSegmentationToSegmentationLocal(probAtlasSeg);
                        double error=1.0-DICE(outputImage,atlasIterator->second);
                        LOGV(3)<<"Reconstructing "<<atlasID<<" using "<<targetID<<"; dice error: "<<error<<endl;
                        localARE+=error;
                        }
                    }

                    //check if ARE improved
                    if (localARE<bestARE){
                        bestID=targetImageIterator2->first;
                        bestIdx=j;
                        bestARE=localARE;
                    }
                }
                LOGV(1)<<"Found best: "<<VAR(bestARE)<<" "<< VAR(bestID)<< endl;
                LOGV(2)<<"Swapping.. "<<endl;
                //swap in best sample at position
                string oldID=targetImageIterator->first;
                int oldIdx=0;
                ImagePointerType tmp=targetImageIterator->second;
                (*targetImages)[i]=(*targetImages)[bestIdx];
                (*targetImages)[bestIdx].first=oldID;
                (*targetImages)[bestIdx].second=tmp;
                //update accumulated atlas probabilities
                int atlasN=0;
                for (ImageListIteratorType atlasIterator=inputAtlasSegmentations->begin();atlasIterator!=inputAtlasSegmentations->end() && (atlasN<useNAtlases);++atlasIterator,++atlasN){//iterate over atlases
                    string atlasID = atlasIterator->first;
                    string targetID = bestID;
                    //todo: propagate atlas segmentation forward backward
                    //todo accumulate atlas segmentations
                    DeformationFieldPointerType firstDeformation,secondDeformation,deformation;
                    if (dontCacheDeformations){
                        firstDeformation = ImageUtils<DeformationFieldType>::readImage(deformationFilenames[atlasID][targetID]);
                        secondDeformation = ImageUtils<DeformationFieldType>::readImage(deformationFilenames[targetID][atlasID]);
                    }else{
                        firstDeformation = deformationCache[atlasID][targetID];
                        secondDeformation = deformationCache[targetID][atlasID];
                    }

                    deformation = TransfUtilsType::composeDeformations(secondDeformation,firstDeformation);
                    ProbabilisticVectorImagePointerType probSeg=probabilisticSegmentations[atlasID];
                    double weight = 1.0;
                    updateProbabilisticSegmentationLocalMetricNew(probabilisticAtlasSelfSegmentations[atlasID],probSeg,weight,tmp,(*atlasImages)[(*atlasIDMap)[atlasID]].second,deformation,metric);
                }

            }
        }
#endif

        //generate zero-hop target segmentations
        for (ImageListIteratorType targetImageIterator=targetImages->begin();targetImageIterator!=targetImages->end();++targetImageIterator){                //iterate over targets
            string targetID= targetImageIterator->first;
            if (atlasSegmentationIDMap->find(targetID)==atlasSegmentationIDMap->end()){ //do not calculate segmentation for atlas images
                probabilisticSegmentations[targetID]=createEmptyProbImageFromImage( targetImageIterator->second);
                int atlasN=0;
                for (ImageListIteratorType atlasIterator=inputAtlasSegmentations->begin();
                     atlasIterator!=inputAtlasSegmentations->end() && atlasN<useNAtlases;
                     ++atlasIterator,++atlasN)
                    {//iterate over atlases
                        string atlasID=atlasIterator->first;
                        LOGV(4)<<VAR(atlasID)<<" "<<VAR(targetID)<<endl;
                        DeformationFieldPointerType deformation;
                        if (dontCacheDeformations){
                            deformation = ImageUtils<DeformationFieldType>::readImage(deformationFilenames[atlasID][targetID]);
                        }else{
                            deformation = deformationCache[atlasID][targetID];
                        }
                        ImagePointerType atlasSegmentation=atlasIterator->second;
                        ProbabilisticVectorImagePointerType probAtlasSegmentation=segmentationToProbabilisticVector(atlasSegmentation);
                        double weight=globalWeights[atlasID][targetID];

                        //update
                        if (weighting==UNIFORM || metric == NONE || (lateFusion && nAtlases==1)){
                            updateProbabilisticSegmentationUniform(probabilisticSegmentations[targetID],probAtlasSegmentation,weight,deformation);
                        }else{
                            ImagePointerType targetImage= targetImageIterator->second;
                            ImagePointerType atlasImage=(*atlasImages)[(*atlasIDMap)[atlasID]].second;
                            if (weighting==GLOBAL){
                                updateProbabilisticSegmentationGlobalMetric(probabilisticSegmentations[targetID],probAtlasSegmentation,weight,targetImage,atlasImage,deformation,metric);
                            }else if (weighting==LOCAL){
                                updateProbabilisticSegmentationLocalMetricNew(probabilisticSegmentations[targetID],probAtlasSegmentation,weight,targetImage,atlasImage,deformation,metric);
                            }

                        }
                    }
            }

        }//finished zero-hop segmentation
        LOG<<"done"<<endl;

        LOGV(1)<<"Storing zero-hop segmentations."<<endl;
        for (ImageListIteratorType targetImageIterator=targetImages->begin();targetImageIterator!=targetImages->end();++targetImageIterator){
            string targetID= targetImageIterator->first;
            if (atlasSegmentationIDMap->find(targetID)==atlasSegmentationIDMap->end()){
                ImagePointerType outputImage;
                if (graphCut)
                    outputImage=probSegmentationToSegmentationGraphcutMultiLabel(probabilisticSegmentations[targetID],targetImageIterator->second,smoothness*inputAtlasSegmentations->size(),m_graphCutSigma);
                else
                    outputImage=probSegmentationToSegmentationLocal(probabilisticSegmentations[targetID]);
                ostringstream tmpSegmentationFilename;
                tmpSegmentationFilename<<outputDir<<"/segmentation-weighting"<<weightingName<<"-metric"<<metricName<<"-target"<<targetID<<"-hop0"<<suffix;
                ImageUtils<ImageType>::writeImage(tmpSegmentationFilename.str().c_str(),segmentationMapper.MapInverse(outputImage));
                ostringstream tmpSegmentationFilename2;
                tmpSegmentationFilename2<<outputDir<<"/segmentation-weighting"<<weightingName<<"-metric"<<metricName<<"-target"<<targetID<<"-hop0-ProbImage.mha";
                LOGI(4,ImageUtils<ProbabilisticVectorImageType>::writeImage(tmpSegmentationFilename2.str().c_str(),probabilisticSegmentations[targetID]));

            }
        }

        bool converged=false; //no convergence check, yet
        logSetStage("Iterative improvement");
        for (int n=1;n<=maxHops && !converged;++n){
            LOG<<"hop "<<n<<endl;
            //initialize new prob segmentations
            map<string,ProbabilisticVectorImagePointerType> newProbabilisticTargetSegmentations;
            //iterate over atlases
            for (ImageListIteratorType atlasImageIterator=atlasImages->begin();atlasImageIterator!=atlasImages->end();++atlasImageIterator){
                string atlasID = atlasImageIterator->first;
                newProbabilisticTargetSegmentations[atlasID] = probabilisticSegmentations[atlasID];
            }
            //targets
            for (ImageListIteratorType targetImageIterator=targetImages->begin();targetImageIterator!=targetImages->end();++targetImageIterator){
                string targetID = targetImageIterator->first;
                if ( atlasSegmentationIDMap->find(targetID)==atlasSegmentationIDMap->end()){
                    //initialize with previous hop likelihood
                    newProbabilisticTargetSegmentations[targetID]=ImageUtils<ProbabilisticVectorImageType>::duplicate(probabilisticSegmentations[targetID]);
                }
            }

            //update!
            int atlasN=0;
            for (ImageListIteratorType atlasIterator=inputAtlasSegmentations->begin();atlasIterator!=inputAtlasSegmentations->end() && (atlasN<useNAtlases);++atlasIterator,++atlasN){//iterate over atlases
                string atlasID=atlasIterator->first;
                int intermediateN=0;
                for (ImageListIteratorType intermediateImageIterator=targetImages->begin();intermediateImageIterator!=targetImages->end() && (intermediateN<useNTargets);++intermediateImageIterator){//iterate over intermediate images
                    string intermediateID= intermediateImageIterator->first;
                    if ( (intermediateID==atlasID) || (atlasSegmentationIDMap->find(intermediateID) == atlasSegmentationIDMap->end()) ){
                        ++intermediateN;
                        //for late fusion, we do also need the deformation from the atlas to the intermediate image
                        DeformationFieldPointerType firstDeformation;
                        if (lateFusion){
                            if (intermediateID != atlasID){
                                if (dontCacheDeformations){
                                    LOGV(3)<<VAR(atlasID)<<" "<<VAR(intermediateID)<<" "<<VAR(deformationFilenames[atlasID][intermediateID])<<endl;
                                    firstDeformation = ImageUtils<DeformationFieldType>::readImage(deformationFilenames[atlasID][intermediateID]);
                                }else{
                                    LOGV(3)<<VAR(atlasID)<<" "<<VAR(intermediateID)<<endl;
                                    firstDeformation = deformationCache[atlasID][intermediateID];
                                }
                            }
                        }

                        for (ImageListIteratorType targetImageIterator=targetImages->begin();targetImageIterator!=targetImages->end();++targetImageIterator){//iterate over target images
                            string targetID= targetImageIterator->first;
                            if ( targetID != atlasID){ //don't update atlas segmentations! :)
                                if (targetID != intermediateID ){ // don't propagate segmentations to the intermediate image.. doesn't make sense, right?
                                    LOGV(3)<<"hop "<<n<<" "<<  VAR(atlasID) << " "<< VAR(intermediateID) <<" "<<VAR(targetID) << endl;

                                    //get auxiliary global weight
                                    double weight=globalWeights[intermediateID][targetID];

                                    //get deformation from intermediate to target image, cached or uncached
                                    DeformationFieldPointerType secondDeformation,deformation;
                                    if (dontCacheDeformations){
                                        LOGV(3)<<VAR(targetID)<<" "<<VAR(intermediateID)<<" "<<VAR(deformationFilenames[intermediateID][targetID])<<endl<<endl;
                                        secondDeformation = ImageUtils<DeformationFieldType>::readImage(deformationFilenames[intermediateID][targetID]);
                                    }else{
                                        LOGV(3)<<VAR(targetID)<<" "<<VAR(intermediateID)<<endl<<endl;
                                        secondDeformation = deformationCache[intermediateID][targetID];
                                    }

                                    ProbabilisticVectorImagePointerType probSeg;
                                    if (lateFusion) {
                                        if ( intermediateID == atlasID ){
                                            deformation = secondDeformation;
                                        }else{
                                            deformation = TransfUtilsType::composeDeformations(secondDeformation,firstDeformation);
                                            weight*=globalWeights[atlasID][intermediateID];
                                        }
                                        probSeg = probabilisticSegmentations[atlasID];
                                    }else{
                                        deformation = secondDeformation;
                                        probSeg = probabilisticSegmentations[intermediateID];
                                    }

                                    //weight*=globalOneHopWeight*1.0/min(useNAtlases,nAtlases);
                                    weight = 1.0/min(useNAtlases,nAtlases);

                                    //UPDATE
                                    if (weighting==UNIFORM || metric == NONE){
                                        updateProbabilisticSegmentationUniform(newProbabilisticTargetSegmentations[targetID],probSeg,weight,deformation);
                                    }else{
                                        ImagePointerType img1=targetImageIterator->second;
                                        ImagePointerType img2;
                                        if (lateFusion){
                                            img2=(*atlasImages)[(*atlasIDMap)[atlasID]].second;
                                        }else{
                                            img2=intermediateImageIterator->second;
                                        }
                                        if (weighting==GLOBAL){
                                            updateProbabilisticSegmentationGlobalMetric(newProbabilisticTargetSegmentations[targetID],probSeg,weight,img1,img2,deformation,metric);

                                        }else if (weighting==LOCAL){
                                            updateProbabilisticSegmentationLocalMetricNew(newProbabilisticTargetSegmentations[targetID],probSeg,weight,img1,img2,deformation,metric);
                                        }
                                    }
                                    if (verbose>=8){
                                        ImagePointerType outputIntermediateSegmentation = probSegmentationToSegmentationLocal(warpProbImage(probSeg,deformation));
                                        ostringstream tmpSegmentationFilename;
                                        tmpSegmentationFilename<<outputDir<<"/segmentation-intermediate-weighting"<<weightingName<<"-metric"<<metricName<<"-from-"<<atlasID<<"-over-"<<intermediateID<<"-to-"<<targetID<<"-hop"<<n<<suffix;
                                        ImageUtils<ImageType>::writeImage(tmpSegmentationFilename.str().c_str(),segmentationMapper.MapInverse(outputIntermediateSegmentation));
                                    }
                                }
                            }
                        }//for targetID
                    }//catch paths over intermediate atlases
                }//for intermediateID

                //iterating over atlases only makes sense for late fusion
                //in the early fusion case, multiple atlases are already incorporated in the zero hop segmentation
                if (!lateFusion)
                    break;

            }//for atlases

            LOG<<"done"<<endl;
            LOG<<"Storing output. and checking convergence"<<endl;
            for (ImageListIteratorType targetImageIterator=targetImages->begin();targetImageIterator!=targetImages->end();++targetImageIterator){
                string id= targetImageIterator->first;
                LOGV(4)<<VAR(id)<<endl;
                if (atlasSegmentationIDMap->find(id)==atlasSegmentationIDMap->end()){
                    ImagePointerType outputImage;

                    //ProbabilisticVectorImagePointerType normalizedProbs=normalizeProbs(newProbabilisticTargetSegmentations[id]);
                    ProbabilisticVectorImagePointerType normalizedProbs=normalizeProbsSimple(newProbabilisticTargetSegmentations[id],useNAtlases, useNTargets);
                    //ProbabilisticVectorImagePointerType normalizedProbs=(newProbabilisticTargetSegmentations[id]);

                    if (graphCut)
                        outputImage=probSegmentationToSegmentationGraphcut(newProbabilisticTargetSegmentations[id],smoothness*(nImages-nAtlases)*nAtlases);
                    else
                        outputImage=probSegmentationToSegmentationLocal(newProbabilisticTargetSegmentations[id]);
                    ostringstream tmpSegmentationFilename;
                    tmpSegmentationFilename<<outputDir<<"/segmentation-weighting"<<weightingName<<"-metric"<<metricName<<"-target"<<id<<"-hop"<<n<<suffix;
                    ImageUtils<ImageType>::writeImage(tmpSegmentationFilename.str().c_str(),segmentationMapper.MapInverse(outputImage));
                    ostringstream tmpSegmentationFilename2;
                    tmpSegmentationFilename2<<outputDir<<"/segmentation-weighting"<<weightingName<<"-metric"<<metricName<<"-target"<<id<<"-hop1-ProbImage.mha";
                    LOGI(4,ImageUtils<ProbabilisticVectorImageType>::writeImage(tmpSegmentationFilename2.str().c_str(),normalizedProbs));
                }
            }
            probabilisticSegmentations=newProbabilisticTargetSegmentations;
        }// hops
        return 1;
    }//run
protected:
    ImageListType * readImageList(string filename, map<string,int> * indexMap){
        ImageListType * result=new  ImageListType;
        ifstream ifs(filename.c_str());
        if (!ifs){
            LOG<<"could not read "<<filename<<endl;
            exit(0);
        }
        int c=0;
        while( ! ifs.eof() )
            {
                string imageID;
                ifs >> imageID;
                if (imageID!=""){
                    ImagePointerType img;
                    string imageFileName ;
                    ifs >> imageFileName;
                    LOGV(3)<<"Reading image "<<imageFileName<< " with ID "<<imageID<<endl;
                    img=ImageUtils<ImageType>::readImage(imageFileName);
                    if (indexMap->find(imageID)==indexMap->end()){
                        (*indexMap)[imageID]=c;
                        result->push_back(make_pair(imageID,img));
                        ++c;
                    }
                    else{
                        LOG<<"duplicate image ID "<<imageID<<", aborting"<<endl;
                        exit(0);
                    }
                }
            }
        return result;
    }
    ProbabilisticVectorImagePointerType segmentationToProbabilisticVector(ImagePointerType img){
        ProbabilisticVectorImagePointerType result=createEmptyProbImageFromImage(img);
        ProbImageIteratorType probIt(result,result->GetLargestPossibleRegion());
        ImageIteratorType imgIt(img,img->GetLargestPossibleRegion());
        for (imgIt.GoToBegin(),probIt.GoToBegin();!imgIt.IsAtEnd();++imgIt,++probIt){
            ProbabilisticPixelType p;
            p.Fill(0.0);
            p[int(imgIt.Get())]=1;
            probIt.Set(p);
        }
        return result;
    }

    ImagePointerType probSegmentationToSegmentationLocal( ProbabilisticVectorImagePointerType img){
        ImagePointerType result=ImageType::New();
        result->SetOrigin(img->GetOrigin());
        result->SetSpacing(img->GetSpacing());
        result->SetDirection(img->GetDirection());
        result->SetRegions(img->GetLargestPossibleRegion());
        result->Allocate();
        ImageIteratorType imgIt(result,result->GetLargestPossibleRegion());
        ProbImageIteratorType probIt(img,img->GetLargestPossibleRegion());
        for (imgIt.GoToBegin(),probIt.GoToBegin();!imgIt.IsAtEnd();++imgIt,++probIt){
            float maxProb=-std::numeric_limits<float>::max();
            int maxLabel=0;
            ProbabilisticPixelType p = probIt.Get();
            for (unsigned int s=0;s<nSegmentationLabels;++s){
                if (p[s]>maxProb){
                    maxLabel=s;
                    maxProb=p[s];
                }
            }
            if (D==2){
                imgIt.Set(1.0*std::numeric_limits<PixelType>::max()*maxLabel/(nSegmentationLabels-1));
            }else{
                imgIt.Set(maxLabel);
            }
        }
        return result;
    }
    ImagePointerType probSegmentationToProbImageLocal( ProbabilisticVectorImagePointerType img){
        ImagePointerType result=ImageType::New();
        result->SetOrigin(img->GetOrigin());
        result->SetSpacing(img->GetSpacing());
        result->SetDirection(img->GetDirection());
        result->SetRegions(img->GetLargestPossibleRegion());
        result->Allocate();
        ImageIteratorType imgIt(result,result->GetLargestPossibleRegion());
        ProbImageIteratorType probIt(img,img->GetLargestPossibleRegion());
        for (imgIt.GoToBegin(),probIt.GoToBegin();!imgIt.IsAtEnd();++imgIt,++probIt){
            float maxProb=-std::numeric_limits<float>::max();
            int maxLabel=0;
            ProbabilisticPixelType p = probIt.Get();
            double sump=0.0;
            for (unsigned int s=0;s<nSegmentationLabels;++s){
                if (p[s]>maxProb){
                    maxLabel=s;
                    maxProb=p[s];
                }
                sump+=p[s];
            }
            maxProb=p[1]/sump;
            if (D==2){
                imgIt.Set(1.0*std::numeric_limits<PixelType>::max()*pow(maxProb,1.0));
            }else{
                imgIt.Set(maxProb*maxLabel);
            }
        }
        return result;
    }

    ImagePointerType probSegmentationToSegmentationGraphcut( ProbabilisticVectorImagePointerType img, double smooth){
        ImagePointerType result=ImageType::New();
        result->SetOrigin(img->GetOrigin());
        result->SetSpacing(img->GetSpacing());
        result->SetDirection(img->GetDirection());
        result->SetRegions(img->GetLargestPossibleRegion());
        result->Allocate();
        typedef Graph<float,float,double> MRFType;
        typedef MRFType::node_id NodeType;
        MRFType* optimizer;
        SizeType size=img->GetLargestPossibleRegion().GetSize();
        int nNodes=1;
        for (unsigned int d=0;d<D;++d) {nNodes*=size[d];}
        int nEdges=D*nNodes;
        for (unsigned int d=0;d<D;++d) {nEdges-=size[d];}
        optimizer = new MRFType(nNodes,nEdges);
        optimizer->add_node(nNodes);
        ProbImageIteratorType probIt(img,img->GetLargestPossibleRegion());
        int i=0;
        for (probIt.GoToBegin();!probIt.IsAtEnd();++probIt,++i){
            IndexType idx=probIt.GetIndex();
            ProbabilisticPixelType localProbs=probIt.Get();
            ProbabilisticPixelType energies;
            for (unsigned int s=0;s<nSegmentationLabels;++s){
                energies[s]=0;
                for (unsigned int sprime=0;sprime<nSegmentationLabels;++sprime){
                    if (sprime!=s){
                        energies[s]+=localProbs[sprime];
                    }
                }
            }
            LOGV(7)<<VAR(i)<<" "<<VAR(energies)<<endl;
            optimizer->add_tweights(i,energies[0],energies[1]);
            for (unsigned  int d=0;d<D;++d){
                OffsetType off;
                off.Fill(0);
                off[d]+=1;
                IndexType neighborIndex=idx+off;
                bool inside2;
                int withinImageIndex2=ImageUtils<ImageType>::ImageIndexToLinearIndex(neighborIndex,size,inside2);
                if (inside2){
                    optimizer -> add_edge(i,withinImageIndex2,smooth,smooth);
                }
            }
        }
        optimizer->maxflow();
        ImageIteratorType imgIt(result,result->GetLargestPossibleRegion());
        i=0;
        for (imgIt.GoToBegin();!imgIt.IsAtEnd();++imgIt,++i){
            int maxLabel=optimizer->what_segment(i)== MRFType::SOURCE ;
            if (D==2){
                imgIt.Set(1.0*std::numeric_limits<PixelType>::max()*maxLabel/(nSegmentationLabels-1));
            }else{
                imgIt.Set(maxLabel);
            }
        }
        return result;
    }
    ProbabilisticVectorImagePointerType normalizeProbs(ProbabilisticVectorImagePointerType img){
        ProbImageIteratorType probIt(img,img->GetLargestPossibleRegion());
        ProbabilisticVectorImagePointerType result=ProbabilisticVectorImageType::New();
        result->SetOrigin(img->GetOrigin());
        result->SetSpacing(img->GetSpacing());
        result->SetDirection(img->GetDirection());
        result->SetRegions(img->GetLargestPossibleRegion());
        result->Allocate();
        ProbImageIteratorType resultIt(result,img->GetLargestPossibleRegion());
        resultIt.GoToBegin();
        for (probIt.GoToBegin();!probIt.IsAtEnd();++probIt,++resultIt){
            ProbabilisticPixelType localProbs=probIt.Get();
            double sum=0.0;
            //compute normalizing sum to normalize probabilities(if they're not yet normalized)
            for (int s2=0;s2<nSegmentationLabels;++s2){
                sum+=localProbs[s2];
            }
            for (int s2=0;s2<nSegmentationLabels;++s2){
                localProbs[s2]/=sum;
            }
            resultIt.Set(localProbs);
        }
        return result;
    }
    ProbabilisticVectorImagePointerType normalizeProbsSimple(ProbabilisticVectorImagePointerType img, int nAtlases, int nImages){
        ProbImageIteratorType probIt(img,img->GetLargestPossibleRegion());
        ProbabilisticVectorImagePointerType result=ProbabilisticVectorImageType::New();
        result->SetOrigin(img->GetOrigin());
        result->SetSpacing(img->GetSpacing());
        result->SetDirection(img->GetDirection());
        result->SetRegions(img->GetLargestPossibleRegion());
        result->Allocate();
        ProbImageIteratorType resultIt(result,img->GetLargestPossibleRegion());
        resultIt.GoToBegin();
        for (probIt.GoToBegin();!probIt.IsAtEnd();++probIt,++resultIt){
            ProbabilisticPixelType localProbs=probIt.Get();

            for (int s2=0;s2<nSegmentationLabels;++s2){
                localProbs[s2]/=nAtlases*(nImages-1);
            }
            resultIt.Set(localProbs);
        }
        return result;
    }
    ImagePointerType probSegmentationToSegmentationGraphcutMultiLabel( ProbabilisticVectorImagePointerType img, ImagePointerType segImg, double smooth, double sigma){
        ImagePointerType result=ImageType::New();
        result->SetOrigin(img->GetOrigin());
        result->SetSpacing(img->GetSpacing());
        result->SetDirection(img->GetDirection());
        result->SetRegions(img->GetLargestPossibleRegion());
        result->Allocate();

        typedef GCoptimizationGeneralGraph MRFType;
        //todo
        MRFType optimizer(result->GetBufferedRegion().GetNumberOfPixels(),nSegmentationLabels);

        ProbImageIteratorType probIt(img,img->GetLargestPossibleRegion());

        //going to use sparse labels
        //iterate over labels
        for (unsigned int s=0;s<nSegmentationLabels;++s){
            std::vector<GCoptimization::SparseDataCost> costs(result->GetBufferedRegion().GetNumberOfPixels());
            //GCoptimization::SparseDataCost costs[result->GetBufferedRegion().GetNumberOfPixels()];
            int n = 0;
            int i=0;
            for (probIt.GoToBegin();!probIt.IsAtEnd();++probIt,++i){
                ProbabilisticPixelType localProbs=probIt.Get();
                double prob=localProbs[s];
                double sum=0.0;
                //compute normalizing sum to normalize probabilities(if they're not yet normalized)
                for (int s2=0;s2<nSegmentationLabels;++s2){
                    sum+=localProbs[s2];
                }
                //only add site do label if prob > 0
                if (prob>0){
                    costs[n].site=i;
                    //LOGV(3)<<VAR(prob)<<" "<<VAR(sum)<<endl;
                    costs[n].cost=-log(prob/sum);
                    ++n;
                }
            }
            //resize to actual number of sites with label s
            costs.resize(n);
            optimizer.setDataCost(s,&costs[0],n);
        }
        float *smoothCosts = new float[nSegmentationLabels*nSegmentationLabels];
        for ( int l1 = 0; l1 < nSegmentationLabels; l1++ )
            for (int l2 = 0; l2 < nSegmentationLabels; l2++ )
                smoothCosts[l1+l2*nSegmentationLabels] =  (l1!=l2);
        optimizer.setSmoothCost(smoothCosts);
        int i=0;
        SizeType size=img->GetLargestPossibleRegion().GetSize();

        ImageIteratorType imageIt(segImg,segImg->GetLargestPossibleRegion());
        for (imageIt.GoToBegin();!imageIt.IsAtEnd();++imageIt,++i){
            IndexType idx=imageIt.GetIndex();
            double value=imageIt.Get();
            for (unsigned  int d=0;d<D;++d){
                OffsetType off;
                off.Fill(0);
                off[d]+=1;
                IndexType neighborIndex=idx+off;
                bool inside2;
                int withinImageIndex2=ImageUtils<ImageType>::ImageIndexToLinearIndex(neighborIndex,size,inside2);
                if (inside2){
                    double neighborvalue=segImg->GetPixel(neighborIndex);
                    double weight= exp(-fabs(value-neighborvalue)/sigma);
                    optimizer.setNeighbors(i,withinImageIndex2,smooth*weight);
                }
            }
        }
        LOGV(1)<<"solving graph cut"<<endl;
        optimizer.setVerbosity(mylog.getVerbosity());
        try{
            optimizer.expansion(20);
        }catch (GCException e){
            e.Report();
            exit(-1);
        }
        LOGV(1)<<"done"<<endl;
        ImageIteratorType imgIt(result,result->GetLargestPossibleRegion());
        i=0;
        for (imgIt.GoToBegin();!imgIt.IsAtEnd();++imgIt,++i){
            int maxLabel=optimizer.whatLabel(i) ;
            if (D==2){
                imgIt.Set(1.0*std::numeric_limits<PixelType>::max()*maxLabel/(nSegmentationLabels-1));
            }else{
                imgIt.Set(maxLabel);
            }
        }
        delete smoothCosts;
        return result;
    }

    void updateProbabilisticSegmentationUniform(ProbabilisticVectorImagePointerType accumulator, ProbabilisticVectorImagePointerType increment,double globalWeight,DeformationFieldPointerType deformation){
        ProbabilisticVectorImagePointerType deformedIncrement=warpProbImage(increment,deformation);
        ProbImageIteratorType accIt(accumulator,accumulator->GetLargestPossibleRegion());
        ProbImageIteratorType incIt(deformedIncrement,deformedIncrement->GetLargestPossibleRegion());
        for (accIt.GoToBegin(),incIt.GoToBegin();!incIt.IsAtEnd();++incIt,++accIt){
            accIt.Set(accIt.Get()+incIt.Get()*globalWeight);
        }
    }

    void updateProbabilisticSegmentationGlobalMetric(ProbabilisticVectorImagePointerType accumulator, ProbabilisticVectorImagePointerType increment,double globalWeight, ImagePointerType targetImage, ImagePointerType movingImage,DeformationFieldPointerType deformation,MetricType metric ){

        double metricWeight=0;
        typedef typename itk::LinearInterpolateImageFunction<ImageType> InterpolatorType;
        typename InterpolatorType::Pointer interpolator=InterpolatorType::New();
        interpolator->SetInputImage(movingImage);

        typedef typename itk::DisplacementFieldTransform<typename DisplacementType::ComponentType ,D> DTTransformType;
        typename DTTransformType::Pointer transf=DTTransformType::New();
        transf->SetDisplacementField(deformation);

        switch(metric){
        case NCC:{
            typedef typename itk::NormalizedCorrelationImageToImageMetric<
                ImageType,
                ImageType >    NCCMetricType;
            typename NCCMetricType::Pointer ncc=NCCMetricType::New();
            ncc->SetTransform(transf);
            ncc->SetFixedImage(targetImage);
            ncc->SetMovingImage(movingImage);
            ncc->SetInterpolator(interpolator);
            ncc->SetFixedImageRegion( targetImage->GetLargestPossibleRegion() );
            metricWeight=(1.0-ncc->GetValue(transf->GetParameters()))/2;
            break;
        }
        case MSD:{
            typedef typename itk::MeanSquaresImageToImageMetric<
                ImageType,
                ImageType >    MSDMetricType;
            typename MSDMetricType::Pointer msd=MSDMetricType::New();
            msd->SetFixedImageRegion( targetImage->GetLargestPossibleRegion() );
            msd->SetTransform(transf);
            msd->SetFixedImage(targetImage);
            msd->SetMovingImage(movingImage);
            msd->SetInterpolator(interpolator);
            msd->Initialize();
            metricWeight=(msd->GetValue(transf->GetParameters()));
            metricWeight/=m_sigma*m_sigma;
            metricWeight=exp(-metricWeight);
            break;
        }
        case MAD:{
            metricWeight=globalMAD(targetImage,movingImage,deformation);
            break;
        }
        case MI:{
            typedef itk::MattesMutualInformationImageToImageMetric<
                ImageType,
                ImageType >    MIMetricType;
            typename MIMetricType::Pointer       MImetric      = MIMetricType::New();
            MImetric->ReinitializeSeed( 76926294 );
            MImetric->SetNumberOfHistogramBins( 50 );
            MImetric->SetNumberOfSpatialSamples( 100*50 );
            MImetric->SetFixedImageRegion( targetImage->GetLargestPossibleRegion() );
            MImetric->SetTransform(transf);
            MImetric->SetFixedImage(targetImage);
            MImetric->SetMovingImage(movingImage);
            MImetric->SetInterpolator(interpolator);
            MImetric->Initialize();
            metricWeight=-MImetric->GetValue(transf->GetParameters());

            break;
        }
        case NMI:{
            typedef itk::NormalizedMutualInformationHistogramImageToImageMetric<
                ImageType,
                ImageType >    NMIMetricType;
            typename NMIMetricType::Pointer      NMImetric     = NMIMetricType::New();

            typename NMIMetricType::HistogramType::SizeType histSize;
            histSize[0] = 50;
            histSize[1] = 50;
            NMImetric->SetHistogramSize(histSize);
            NMImetric->SetFixedImageRegion( targetImage->GetLargestPossibleRegion() );
            NMImetric->SetTransform(transf);
            NMImetric->SetFixedImage(targetImage);
            NMImetric->SetMovingImage(movingImage);
            NMImetric->SetInterpolator(interpolator);
            NMImetric->Initialize();
            metricWeight=NMImetric->GetValue(transf->GetParameters());
            break;
        }
        }   //switch

        ProbabilisticVectorImagePointerType deformedIncrement=warpProbImage(increment,deformation);
        ProbImageIteratorType accIt(accumulator,accumulator->GetLargestPossibleRegion());
        ProbImageIteratorType incIt(deformedIncrement,deformedIncrement->GetLargestPossibleRegion());

        LOGV(10)<<VAR(metricWeight)<<endl;
        for (accIt.GoToBegin(),incIt.GoToBegin();!incIt.IsAtEnd();++incIt,++accIt){
            accIt.Set(accIt.Get()+incIt.Get()*globalWeight*metricWeight);
        }
    }
    void updateProbabilisticSegmentationLocalMetric(ProbabilisticVectorImagePointerType accumulator, ProbabilisticVectorImagePointerType increment,double globalWeight, ImagePointerType targetImage, ImagePointerType movingImage,DeformationFieldPointerType deformation,MetricType metric ){
        ProbabilisticVectorImagePointerType deformedIncrement=warpProbImage(increment,deformation);
        ProbImageIteratorType accIt(accumulator,accumulator->GetLargestPossibleRegion());
        ProbImageIteratorType incIt(deformedIncrement,deformedIncrement->GetLargestPossibleRegion());

        std::pair<ImagePointerType,ImagePointerType> deformedMoving = TransfUtilsType::warpImageWithMask(movingImage,deformation);

        ImageNeighborhoodIteratorPointerType tIt=new ImageNeighborhoodIteratorType(m_patchRadius,targetImage,targetImage->GetLargestPossibleRegion());
        ImageNeighborhoodIteratorPointerType aIt=new ImageNeighborhoodIteratorType(m_patchRadius,deformedMoving.first,deformedMoving.first->GetLargestPossibleRegion());
        ImageNeighborhoodIteratorPointerType mIt=new ImageNeighborhoodIteratorType(m_patchRadius,deformedMoving.second,deformedMoving.second->GetLargestPossibleRegion());
        accIt.GoToBegin();incIt.GoToBegin();tIt->GoToBegin();mIt->GoToBegin(); aIt->GoToBegin();
        for (;!accIt.IsAtEnd();++accIt,++incIt,++(*tIt),++(*mIt),++(*aIt)){
            double metricWeight=1;
            switch (metric){
            case MSD:
                metricWeight=localMSD(tIt,aIt,mIt);
                break;
            case MAD:
                metricWeight=localMAD(tIt,aIt,mIt);
                break;
            case NCC:
                metricWeight=localNCC(tIt,aIt,mIt);
                break;
            default:
                metricWeight=1;
            }
            LOGV(10)<<VAR(metricWeight)<<endl;

            accIt.Set(accIt.Get()+incIt.Get()*globalWeight*metricWeight);
        }
        delete tIt; delete aIt; delete mIt;
    }
    void updateProbabilisticSegmentationLocalMetricNew(ProbabilisticVectorImagePointerType accumulator, ProbabilisticVectorImagePointerType increment,double globalWeight, ImagePointerType targetImage, ImagePointerType movingImage,DeformationFieldPointerType deformation,MetricType metric ){
        ProbabilisticVectorImagePointerType deformedIncrement=warpProbImage(increment,deformation);
        ProbImageIteratorType accIt(accumulator,accumulator->GetLargestPossibleRegion());
        ProbImageIteratorType incIt(deformedIncrement,deformedIncrement->GetLargestPossibleRegion());

        std::pair<ImagePointerType,ImagePointerType> deformedMoving = TransfUtilsType::warpImageWithMask(movingImage,deformation);
        FloatImagePointerType metricImage;
        switch (metric){
        case MSD:
            metricImage=Metrics<ImageType,FloatImageType>::LSSDAutoNorm(deformedMoving.first, targetImage,m_patchRadius[0],m_sigma);
            break;
        case MAD:
            metricImage=Metrics<ImageType,FloatImageType>::LSADAutoNorm(deformedMoving.first, targetImage,m_patchRadius[0],m_sigma);
            break;
        case NCC:
            metricImage=Metrics<ImageType,FloatImageType>::efficientLNCC(deformedMoving.first, targetImage,m_patchRadius[0], m_sigma);
            break;
        default:
            LOG<<"no valid metric, aborting"<<endl;
            exit(0);
        }
        LOGI(8,ImageUtils<FloatImageType>::writeImage("weightImage.nii",metricImage));
        FloatImageIteratorType weightIt(metricImage,metricImage->GetLargestPossibleRegion());
        weightIt.GoToBegin();
        accIt.GoToBegin();incIt.GoToBegin();
        for (;!accIt.IsAtEnd();++accIt,++incIt, ++weightIt){
            accIt.Set(accIt.Get()+incIt.Get()*globalWeight*weightIt.Get());
        }
    }
    ProbabilisticVectorImagePointerType createEmptyProbImageFromImage(ImagePointerType input){
        ProbabilisticVectorImagePointerType output=ProbabilisticVectorImageType::New();
        output->SetOrigin(input->GetOrigin());
        output->SetSpacing(input->GetSpacing());
        output->SetDirection(input->GetDirection());
        output->SetRegions(input->GetLargestPossibleRegion());
        output->Allocate();
        ProbabilisticPixelType p;
        p.Fill(0.0);
        output->FillBuffer(p);
        return output;

    }

    ProbabilisticVectorImagePointerType warpProbImage(ProbabilisticVectorImagePointerType input, DeformationFieldPointerType deformation){
        ProbabilisticVectorImagePointerType output=ProbabilisticVectorImageType::New();
        output->SetOrigin(deformation->GetOrigin());
        output->SetSpacing(deformation->GetSpacing());
        output->SetDirection(deformation->GetDirection());
        output->SetRegions(deformation->GetLargestPossibleRegion());
        output->Allocate();
        ProbImageIteratorType outIt(output,output->GetLargestPossibleRegion());
        typedef itk::VectorLinearInterpolateNearestNeighborExtrapolateImageFunction<
            ProbabilisticVectorImageType ,double> DefaultFieldInterpolatorType;
        typename DefaultFieldInterpolatorType::Pointer interpolator=DefaultFieldInterpolatorType::New();
        interpolator->SetInputImage(input);

        DeformationIteratorType deformationIt(deformation,deformation->GetLargestPossibleRegion());
        for (outIt.GoToBegin(),deformationIt.GoToBegin();!outIt.IsAtEnd();++outIt,++deformationIt){
            IndexType index=deformationIt.GetIndex();
            typename DefaultFieldInterpolatorType::ContinuousIndexType idx(index);
            DisplacementType displacement=deformationIt.Get();
            PointType p;
            output->TransformIndexToPhysicalPoint(index,p);
            p+=displacement;
            input->TransformPhysicalPointToContinuousIndex(p,idx);
            outIt.Set(interpolator->EvaluateAtContinuousIndex(idx));
        }
        return output;
    }

    double localMAD(ImageNeighborhoodIteratorPointerType tIt, ImageNeighborhoodIteratorPointerType aIt,ImageNeighborhoodIteratorPointerType mIt){
        double result=0;
        int count=0;
        for (unsigned int i=0;i<tIt->Size();++i){
            if (mIt->GetPixel(i)){
                result+=fabs(tIt->GetPixel(i)-aIt->GetPixel(i));
                count++;
            }
        }
        if (!count)
            return 1.0;
        return exp(-result/count/m_sigma);
    }
    double localMSD(ImageNeighborhoodIteratorPointerType tIt, ImageNeighborhoodIteratorPointerType aIt,ImageNeighborhoodIteratorPointerType mIt){
        double result=0;
        int count=0;
        for (unsigned int i=0;i<tIt->Size();++i){
            if (mIt->GetPixel(i)){
                double tmp=(tIt->GetPixel(i)-aIt->GetPixel(i));
                result+=tmp*tmp;
                count++;
            }
        }
        if (!count)
            return 1.0;
        return  exp(-result/count/(m_sigma*m_sigma));
    }
    double localNCC(ImageNeighborhoodIteratorPointerType tIt, ImageNeighborhoodIteratorPointerType aIt,ImageNeighborhoodIteratorPointerType mIt){
        double result=0;
        int count=0;
        double sff=0.0,smm=0.0,sfm=0.0,sf=0.0,sm=0.0;
        for (unsigned int i=0;i<tIt->Size();++i){
            if (mIt->GetPixel(i)){
                double f=tIt->GetPixel(i);
                double m= aIt->GetPixel(i);
                sff+=f*f;
                smm+=m*m;
                sfm+=f*m;
                sf+=f;
                sm+=m;
                count+=1;
            }
        }
        if (!count)
            return 0.5;
        else{
            double NCC=0;
            sff -= ( sf * sf / count );
            smm -= ( sm * sm / count );
            sfm -= ( sf * sm / count );
            if (smm*sff>0){
                NCC=1.0*sfm/sqrt(smm*sff);
            }
            result=(1.0+NCC)/2;
        }
        return result;
    }

    double globalMAD(ImagePointerType target, ImagePointerType moving, DeformationFieldPointerType deformation){
        std::pair<ImagePointerType,ImagePointerType> deformedMoving = TransfUtilsType::warpImageWithMask(moving,deformation);
        ImageIteratorType tIt(target,target->GetLargestPossibleRegion());
        ImageIteratorType mIt(deformedMoving.first,deformedMoving.first->GetLargestPossibleRegion());
        ImageIteratorType maskIt(deformedMoving.second,deformedMoving.second->GetLargestPossibleRegion());
        tIt.GoToBegin();mIt.GoToBegin();maskIt.GoToBegin();
        double result=0.0;int count=0;
        for (;!tIt.IsAtEnd();++tIt,++mIt,++maskIt){
            if (maskIt.Get()){
                result+=fabs(tIt.Get()-mIt.Get());
                count++;
            }
        }
        if (count)
            return exp(-result/count/m_sigma);
        else
            return 0.0;
    }

    double DICE(ImagePointerType seg1, ImagePointerType seg2){
        typedef typename itk::LabelOverlapMeasuresImageFilter<ImageType> OverlapMeasureFilterType;
        typename OverlapMeasureFilterType::Pointer filter = OverlapMeasureFilterType::New();
        seg1=FilterUtils<ImageType>::binaryThresholdingLow(seg1,1.0);
        seg2=FilterUtils<ImageType>::binaryThresholdingLow(seg2,1.0);
        filter->SetSourceImage(seg1);
        filter->SetTargetImage(seg2);
        filter->Update();
        return filter->GetDiceCoefficient(1);
    }
};//class