Beispiel #1
0
int cnt(void)
{
    std::shared_ptr<group_connectometry_analysis> database(new group_connectometry_analysis);
    std::cout << "reading connectometry db" <<std::endl;
    if(!database->load_database(po.get("source").c_str()))
    {
        std::cout << "invalid database format" << std::endl;
        return 1;
    }
    std::shared_ptr<group_connectometry> vbc(new group_connectometry(0,database,po.get("source").c_str(),false));
    vbc->setAttribute(Qt::WA_DeleteOnClose);
    vbc->show();
    //vbc->hide();

    if(!po.has("demo"))
    {
        std::cout << "please assign demographic file" << std::endl;
        return 1;
    }
    std::string error_msg;
    if(!vbc->load_demographic_file(po.get("demo").c_str(),error_msg))
    {
        std::cout << error_msg << std::endl;
        return 1;
    }


    if(po.has("missing_value"))
    {
        vbc->ui->missing_data_checked->setChecked(true);
        vbc->ui->missing_value->setValue(po.get("missing_value",9999));
        std::cout << "missing value=" << vbc->ui->missing_value->value() << std::endl;
    }


    if(!po.has("voi") || !po.has("variable_list"))
    {
        std::cout << "please assign --voi and --variable_list" << std::endl;
        return 1;
    }
    {
        std::string var_text = po.get("variable_list");
        std::replace(var_text.begin(),var_text.end(),',',' ');
        std::istringstream var_in(var_text);
        std::vector<int> variable_list(
                    (std::istream_iterator<int>(var_in)),
                    (std::istream_iterator<int>()));

        for(int i = 0;i < vbc->ui->variable_list->count();++i)
            vbc->ui->variable_list->item(i)->setCheckState(Qt::Unchecked);
        std::cout << "variables=";

        int voi_index = po.get("voi",0);
        int voi_sel = -1;
        std::string voi_text;
        for(int i = 0;i < variable_list.size();++i)
        {
            int index = variable_list[i];
            if(index >= vbc->ui->variable_list->count())
            {
                std::cout << "Invalid number in the variable_list:" << index << std::endl;
                return 1;
            }
            if(index == voi_index)
            {
                voi_sel = vbc->ui->variable_list->count();
                voi_text = vbc->ui->variable_list->item(index)->text().toStdString();
            }
            vbc->ui->variable_list->item(index)->setCheckState(Qt::Checked);
            if(i)
                std::cout << ",";
            std::cout << vbc->ui->variable_list->item(index)->text().toStdString();
        }
        std::cout << std::endl;
        if(voi_sel == -1)
        {
            std::cout << "variable of interest is not included in the variable list" << std::endl;
            return 1;
        }
        vbc->on_variable_list_clicked(QModelIndex());
        vbc->ui->foi->update();
        vbc->ui->foi->setCurrentText(voi_text.c_str());
        std::cout << "study variable=" << vbc->ui->foi->currentText().toStdString() << std::endl;

    }

    vbc->ui->threshold->setValue(po.get("t_threshold",float(vbc->ui->threshold->value())));
    std::cout << "t_threshold=" << vbc->ui->threshold->value() << std::endl;

    vbc->ui->seed_count->setValue(po.get("seed_count",10000));
    std::cout << "seed_count=" << vbc->ui->seed_count->value() << std::endl;

    vbc->ui->permutation_count->setValue(po.get("permutation",int(2000)));
    std::cout << "permutation=" << vbc->ui->permutation_count->value() << std::endl;

    vbc->ui->multithread->setValue(po.get("thread_count",int(std::thread::hardware_concurrency())));
    std::cout << "thread=" << vbc->ui->multithread->value() << std::endl;

    vbc->ui->track_trimming->setValue(po.get("trim",1));
    std::cout << "trim=" << vbc->ui->track_trimming->value() << std::endl;


    if(po.get("normalized_qa",int(0)))
    {
        std::cout << "normalized qa" << std::endl;
        vbc->ui->normalize_qa->setChecked(true);
    }

    if(po.has("fdr_threshold"))
    {
        vbc->ui->rb_fdr->setChecked(true);
        vbc->ui->fdr_threshold->setValue(po.get("fdr_threshold",0.05f));
        std::cout << "fdr_threshold=" << vbc->ui->fdr_threshold->value() << std::endl;
    }
    else
    {
        vbc->ui->rb_length->setChecked(true);
        vbc->ui->length_threshold->setValue(po.get("length_threshold",int(40)));
        std::cout << "length_threshold=" << vbc->ui->length_threshold->value() << std::endl;
    }

    // check rois
    {
        const int total_count = 18;
        char roi_names[total_count][5] = {"roi","roi2","roi3","roi4","roi5","roa","roa2","roa3","roa4","roa5","end","end2","seed","ter","ter2","ter3","ter4","ter5"};
        unsigned char type[total_count] = {0,0,0,0,0,1,1,1,1,1,2,2,3,4,4,4,4,4};
        for(int index = 0;index < total_count;++index)
        if (po.has(roi_names[index]))
        {
            ROIRegion roi(vbc->vbc->handle);
            if(!load_region(vbc->vbc->handle,roi,po.get(roi_names[index])))
                return 1;
            vbc->add_new_roi(po.get(roi_names[index]).c_str(),
                             po.get(roi_names[index]).c_str(),
                             roi.get_region_voxels_raw(),type[index]);
            std::cout << roi_names[index] << "=" << po.get(roi_names[index]) << std::endl;
            vbc->ui->roi_user_defined->setChecked(true);
            vbc->ui->roi_whole_brain->setChecked(false);
        }
    }



    vbc->on_run_clicked();
    std::cout << vbc->vbc->report << std::endl;
    std::cout << "running connectometry" << std::endl;
    vbc->vbc->wait();
    std::cout << "output results" << std::endl;
    vbc->calculate_FDR();
    std::cout << "close GUI" << std::endl;
    vbc->close();
    vbc.reset();
    return 0;
}
Beispiel #2
0
tracking_window::tracking_window(QWidget *parent,ODFModel* new_handle,bool handle_release_) :
        QMainWindow(parent),handle(new_handle),handle_release(handle_release_),
        ui(new Ui::tracking_window),scene(*this,new_handle),slice(new_handle)

{

    ODFModel* odf_model = (ODFModel*)handle;
    FibData& fib_data = odf_model->fib_data;

    odf_size = fib_data.fib.odf_table.size();
    odf_face_size = fib_data.fib.odf_faces.size();
    has_odfs = fib_data.fib.has_odfs() ? 1:0;
    // check whether first index is "fa0"
    is_dti = (fib_data.view_item[0].name[0] == 'f');

    ui->setupUi(this);
    {
        setGeometry(10,10,800,600);

        ui->regionDockWidget->setMinimumWidth(0);
        ui->dockWidget->setMinimumWidth(0);
        ui->dockWidget_3->setMinimumWidth(0);
        ui->renderingLayout->addWidget(renderWidget = new RenderingTableWidget(*this,ui->renderingWidgetHolder,has_odfs));
        ui->centralLayout->insertWidget(1,glWidget = new GLWidget(renderWidget->getData("anti_aliasing").toInt(),
                                                                  *this,renderWidget,ui->centralwidget));
        ui->verticalLayout_3->addWidget(regionWidget = new RegionTableWidget(*this,ui->regionDockWidget));
        ui->tractverticalLayout->addWidget(tractWidget = new TractTableWidget(*this,ui->TractWidgetHolder));
        ui->graphicsView->setScene(&scene);
        ui->graphicsView->setCursor(Qt::CrossCursor);
        scene.statusbar = ui->statusbar;
        color_bar.reset(new color_bar_dialog(this));
    }

    // setup fa threshold
    {
        for(int index = 0;index < fib_data.fib.index_name.size();++index)
            ui->tracking_index->addItem((fib_data.fib.index_name[index]+" threshold").c_str());
        ui->tracking_index->setCurrentIndex(0);
        ui->step_size->setValue(fib_data.vs[0]/2.0);
    }

    // setup sliders
    {
        slice_no_update = true;
        ui->SagSlider->setRange(0,slice.geometry[0]-1);
        ui->CorSlider->setRange(0,slice.geometry[1]-1);
        ui->AxiSlider->setRange(0,slice.geometry[2]-1);
        ui->SagSlider->setValue(slice.slice_pos[0]);
        ui->CorSlider->setValue(slice.slice_pos[1]);
        ui->AxiSlider->setValue(slice.slice_pos[2]);

        ui->glSagBox->setRange(0,slice.geometry[0]-1);
        ui->glCorBox->setRange(0,slice.geometry[1]-1);
        ui->glAxiBox->setRange(0,slice.geometry[2]-1);
        ui->glSagBox->setValue(slice.slice_pos[0]);
        ui->glCorBox->setValue(slice.slice_pos[1]);
        ui->glAxiBox->setValue(slice.slice_pos[2]);
        slice_no_update = false;
        on_SliceModality_currentIndexChanged(0);

        for (unsigned int index = 0;index < fib_data.view_item.size(); ++index)
        {
            ui->sliceViewBox->addItem(fib_data.view_item[index].name.c_str());
            if(fib_data.view_item[index].is_overlay)
                ui->overlay->addItem(fib_data.view_item[index].name.c_str());
        }
        ui->sliceViewBox->setCurrentIndex(0);
        ui->overlay->setCurrentIndex(0);
        if(ui->overlay->count() == 1)
           ui->overlay->hide();
    }

    is_qsdr = !handle->fib_data.trans_to_mni.empty();

    // setup atlas
    if(!fa_template_imp.I.empty() && fib_data.vs[0] > 0.5 && !is_qsdr)
    {
        mi3_arg.scaling[0] = slice.voxel_size[0] / std::fabs(fa_template_imp.tran[0]);
        mi3_arg.scaling[1] = slice.voxel_size[1] / std::fabs(fa_template_imp.tran[5]);
        mi3_arg.scaling[2] = slice.voxel_size[2] / std::fabs(fa_template_imp.tran[10]);
        image::reg::align_center(slice.source_images,fa_template_imp.I,mi3_arg);
        mi3.reset(new manual_alignment(this,slice.source_images,fa_template_imp.I,mi3_arg));
        is_qsdr = false;
    }
    else
        ui->actionManual_Registration->setEnabled(false);
    ui->actionConnectometry->setEnabled(handle->fib_data.fib.has_odfs() && is_qsdr);
    for(int index = 0;index < atlas_list.size();++index)
        ui->atlasListBox->addItem(atlas_list[index].name.c_str());


    {
        if(is_dti)
            ui->actionQuantitative_anisotropy_QA->setText("Save FA...");
        for (int index = fib_data.other_mapping_index; index < fib_data.view_item.size(); ++index)
            {
                std::string& name = fib_data.view_item[index].name;
                QAction* Item = new QAction(this);
                Item->setText(QString("Save %1...").arg(name.c_str()));
                Item->setData(QString(name.c_str()));
                Item->setVisible(true);
                connect(Item, SIGNAL(triggered()),tractWidget, SLOT(save_tracts_data_as()));
                ui->menuSave->addAction(Item);
            }
    }

    // opengl
    {
        connect(renderWidget->treemodel,SIGNAL(dataChanged(QModelIndex,QModelIndex)),
                glWidget,SLOT(updateGL()));
        connect(ui->tbDefaultParam,SIGNAL(clicked()),renderWidget,SLOT(setDefault()));
        connect(ui->tbDefaultParam,SIGNAL(clicked()),glWidget,SLOT(updateGL()));

        connect(ui->glSagSlider,SIGNAL(valueChanged(int)),this,SLOT(glSliderValueChanged()));
        connect(ui->glCorSlider,SIGNAL(valueChanged(int)),this,SLOT(glSliderValueChanged()));
        connect(ui->glAxiSlider,SIGNAL(valueChanged(int)),this,SLOT(glSliderValueChanged()));

        connect(ui->glSagCheck,SIGNAL(stateChanged(int)),glWidget,SLOT(updateGL()));
        connect(ui->glCorCheck,SIGNAL(stateChanged(int)),glWidget,SLOT(updateGL()));
        connect(ui->glAxiCheck,SIGNAL(stateChanged(int)),glWidget,SLOT(updateGL()));

        connect(ui->glSagView,SIGNAL(clicked()),this,SLOT(on_SagView_clicked()));
        connect(ui->glCorView,SIGNAL(clicked()),this,SLOT(on_CorView_clicked()));
        connect(ui->glAxiView,SIGNAL(clicked()),this,SLOT(on_AxiView_clicked()));

        connect(ui->addSlices,SIGNAL(clicked()),this,SLOT(on_actionInsert_T1_T2_triggered()));
        connect(ui->actionAdd_surface,SIGNAL(triggered()),glWidget,SLOT(addSurface()));
        connect(ui->SliceModality,SIGNAL(currentIndexChanged(int)),glWidget,SLOT(updateGL()));
        connect(ui->actionSave_Screen,SIGNAL(triggered()),glWidget,SLOT(catchScreen()));
        connect(ui->actionSave_3D_screen_in_high_resolution,SIGNAL(triggered()),glWidget,SLOT(catchScreen2()));
        connect(ui->actionLoad_Camera,SIGNAL(triggered()),glWidget,SLOT(loadCamera()));
        connect(ui->actionSave_Camera,SIGNAL(triggered()),glWidget,SLOT(saveCamera()));
        connect(ui->actionLoad_mapping,SIGNAL(triggered()),glWidget,SLOT(loadMapping()));
        connect(ui->actionSave_mapping,SIGNAL(triggered()),glWidget,SLOT(saveMapping()));
        connect(ui->actionSave_Rotation_Images,SIGNAL(triggered()),glWidget,SLOT(saveRotationSeries()));
        connect(ui->actionSave_Left_Right_3D_Image,SIGNAL(triggered()),glWidget,SLOT(saveLeftRight3DImage()));
    }
    // scene view
    {
        connect(ui->SagSlider,SIGNAL(valueChanged(int)),this,SLOT(SliderValueChanged()));
        connect(ui->CorSlider,SIGNAL(valueChanged(int)),this,SLOT(SliderValueChanged()));
        connect(ui->AxiSlider,SIGNAL(valueChanged(int)),this,SLOT(SliderValueChanged()));


        connect(&scene,SIGNAL(need_update()),&scene,SLOT(show_slice()));
        connect(&scene,SIGNAL(need_update()),glWidget,SLOT(updateGL()));
        connect(ui->fa_threshold,SIGNAL(valueChanged(double)),&scene,SLOT(show_slice()));
        connect(ui->contrast,SIGNAL(valueChanged(int)),&scene,SLOT(show_slice()));
        connect(ui->offset,SIGNAL(valueChanged(int)),&scene,SLOT(show_slice()));
        connect(ui->show_fiber,SIGNAL(clicked()),&scene,SLOT(show_slice()));
        connect(ui->show_pos,SIGNAL(clicked()),&scene,SLOT(show_slice()));
        connect(ui->show_lr,SIGNAL(clicked()),&scene,SLOT(show_slice()));

        connect(ui->zoom,SIGNAL(valueChanged(double)),&scene,SLOT(show_slice()));
        connect(ui->zoom,SIGNAL(valueChanged(double)),&scene,SLOT(center()));


        connect(ui->actionAxial_View,SIGNAL(triggered()),this,SLOT(on_AxiView_clicked()));
        connect(ui->actionCoronal_View,SIGNAL(triggered()),this,SLOT(on_CorView_clicked()));
        connect(ui->actionSagittal_view,SIGNAL(triggered()),this,SLOT(on_SagView_clicked()));


        connect(ui->actionSave_ROI_Screen,SIGNAL(triggered()),&scene,SLOT(catch_screen()));

        connect(ui->actionSave_Anisotrpy_Map_as,SIGNAL(triggered()),&scene,SLOT(save_slice_as()));


        connect(ui->overlay,SIGNAL(currentIndexChanged(int)),this,SLOT(on_sliceViewBox_currentIndexChanged(int)));

    }

    // regions
    {

        connect(regionWidget,SIGNAL(need_update()),&scene,SLOT(show_slice()));
        connect(regionWidget,SIGNAL(need_update()),glWidget,SLOT(updateGL()));



        connect(ui->whole_brain,SIGNAL(clicked()),regionWidget,SLOT(whole_brain()));

        connect(ui->view_style,SIGNAL(currentIndexChanged(int)),&scene,SLOT(show_slice()));

        //atlas
        connect(ui->addRegionFromAtlas,SIGNAL(clicked()),regionWidget,SLOT(add_atlas()));


        connect(ui->actionNewRegion,SIGNAL(triggered()),regionWidget,SLOT(new_region()));
        connect(ui->actionOpenRegion,SIGNAL(triggered()),regionWidget,SLOT(load_region()));
        connect(ui->actionSaveRegionAs,SIGNAL(triggered()),regionWidget,SLOT(save_region()));
        connect(ui->actionSave_Voxel_Data_As,SIGNAL(triggered()),regionWidget,SLOT(save_region_info()));
        connect(ui->actionDeleteRegion,SIGNAL(triggered()),regionWidget,SLOT(delete_region()));
        connect(ui->actionDeleteRegionAll,SIGNAL(triggered()),regionWidget,SLOT(delete_all_region()));


        // actions
        connect(ui->actionShift_X,SIGNAL(triggered()),regionWidget,SLOT(action_shiftx()));
        connect(ui->actionShift_X_2,SIGNAL(triggered()),regionWidget,SLOT(action_shiftnx()));
        connect(ui->actionShift_Y,SIGNAL(triggered()),regionWidget,SLOT(action_shifty()));
        connect(ui->actionShift_Y_2,SIGNAL(triggered()),regionWidget,SLOT(action_shiftny()));
        connect(ui->actionShift_Z,SIGNAL(triggered()),regionWidget,SLOT(action_shiftz()));
        connect(ui->actionShift_Z_2,SIGNAL(triggered()),regionWidget,SLOT(action_shiftnz()));

        connect(ui->actionFlip_X,SIGNAL(triggered()),regionWidget,SLOT(action_flipx()));
        connect(ui->actionFlip_Y,SIGNAL(triggered()),regionWidget,SLOT(action_flipy()));
        connect(ui->actionFlip_Z,SIGNAL(triggered()),regionWidget,SLOT(action_flipz()));

        connect(ui->actionThreshold,SIGNAL(triggered()),regionWidget,SLOT(action_threshold()));



        connect(ui->actionSmoothing,SIGNAL(triggered()),regionWidget,SLOT(action_smoothing()));
        connect(ui->actionErosion,SIGNAL(triggered()),regionWidget,SLOT(action_erosion()));
        connect(ui->actionDilation,SIGNAL(triggered()),regionWidget,SLOT(action_dilation()));
        connect(ui->actionNegate,SIGNAL(triggered()),regionWidget,SLOT(action_negate()));
        connect(ui->actionDefragment,SIGNAL(triggered()),regionWidget,SLOT(action_defragment()));

        connect(ui->actionCheck_all_regions,SIGNAL(triggered()),regionWidget,SLOT(check_all()));
        connect(ui->actionUnckech_all_regions,SIGNAL(triggered()),regionWidget,SLOT(uncheck_all()));

        connect(ui->actionWhole_brain_seeding,SIGNAL(triggered()),regionWidget,SLOT(whole_brain()));
        connect(ui->actionRegion_statistics,SIGNAL(triggered()),regionWidget,SLOT(show_statistics()));


    }
    // tracts
    {
        connect(ui->perform_tracking,SIGNAL(clicked()),tractWidget,SLOT(start_tracking()));
        connect(ui->stopTracking,SIGNAL(clicked()),tractWidget,SLOT(stop_tracking()));

        connect(tractWidget,SIGNAL(need_update()),glWidget,SLOT(makeTracts()));
        connect(tractWidget,SIGNAL(need_update()),glWidget,SLOT(updateGL()));

        connect(glWidget,SIGNAL(edited()),tractWidget,SLOT(edit_tracts()));
        connect(glWidget,SIGNAL(region_edited()),glWidget,SLOT(updateGL()));
        connect(glWidget,SIGNAL(region_edited()),&scene,SLOT(show_slice()));

        connect(ui->actionOpenTract,SIGNAL(triggered()),tractWidget,SLOT(load_tracts()));
        connect(ui->actionMerge_All,SIGNAL(triggered()),tractWidget,SLOT(merge_all()));
        connect(ui->actionCopyTrack,SIGNAL(triggered()),tractWidget,SLOT(copy_track()));
        connect(ui->actionDeleteTract,SIGNAL(triggered()),tractWidget,SLOT(delete_tract()));
        connect(ui->actionDeleteTractAll,SIGNAL(triggered()),tractWidget,SLOT(delete_all_tract()));

        connect(ui->actionOpen_Colors,SIGNAL(triggered()),tractWidget,SLOT(load_tracts_color()));
        connect(ui->actionSave_Tracts_Colors_As,SIGNAL(triggered()),tractWidget,SLOT(save_tracts_color_as()));

        connect(ui->actionUndo,SIGNAL(triggered()),tractWidget,SLOT(undo_tracts()));
        connect(ui->actionRedo,SIGNAL(triggered()),tractWidget,SLOT(redo_tracts()));
        connect(ui->actionTrim,SIGNAL(triggered()),tractWidget,SLOT(trim_tracts()));

        connect(ui->actionSet_Color,SIGNAL(triggered()),tractWidget,SLOT(set_color()));

        connect(ui->actionK_means,SIGNAL(triggered()),tractWidget,SLOT(clustering_kmeans()));
        connect(ui->actionEM,SIGNAL(triggered()),tractWidget,SLOT(clustering_EM()));
        connect(ui->actionHierarchical,SIGNAL(triggered()),tractWidget,SLOT(clustering_hie()));
        connect(ui->actionOpen_Cluster_Labels,SIGNAL(triggered()),tractWidget,SLOT(open_cluster_label()));

        //setup menu
        connect(ui->actionSaveTractAs,SIGNAL(triggered()),tractWidget,SLOT(save_tracts_as()));
        connect(ui->actionSave_All_Tracts_As,SIGNAL(triggered()),tractWidget,SLOT(save_all_tracts_as()));
        connect(ui->actionQuantitative_anisotropy_QA,SIGNAL(triggered()),tractWidget,SLOT(save_fa_as()));
        connect(ui->actionSave_End_Points_As,SIGNAL(triggered()),tractWidget,SLOT(save_end_point_as()));
        connect(ui->actionStatistics,SIGNAL(triggered()),tractWidget,SLOT(show_tracts_statistics()));

        connect(ui->track_up,SIGNAL(clicked()),tractWidget,SLOT(move_up()));
        connect(ui->track_down,SIGNAL(clicked()),tractWidget,SLOT(move_down()));

    }




    // recall the setting
    {

        QSettings settings;
        if(!default_geo.size())
            default_geo = saveGeometry();
        if(!default_state.size())
            default_state = saveState();
        restoreGeometry(settings.value("geometry").toByteArray());
        restoreState(settings.value("state").toByteArray());
        ui->turning_angle->setValue(settings.value("turning_angle",60).toDouble());
        ui->smoothing->setValue(settings.value("smoothing",0.0).toDouble());
        ui->min_length->setValue(settings.value("min_length",0.0).toDouble());
        ui->max_length->setValue(settings.value("max_length",500).toDouble());
        ui->tracking_method->setCurrentIndex(settings.value("tracking_method",0).toInt());
        ui->seed_plan->setCurrentIndex(settings.value("seed_plan",0).toInt());
        ui->initial_direction->setCurrentIndex(settings.value("initial_direction",0).toInt());
        ui->interpolation->setCurrentIndex(settings.value("interpolation",0).toInt());
        ui->tracking_plan->setCurrentIndex(settings.value("tracking_plan",0).toInt());
        ui->track_count->setValue(settings.value("track_count",2000).toInt());
        ui->thread_count->setCurrentIndex(settings.value("thread_count",0).toInt());

        ui->glSagCheck->setChecked(settings.value("SagSlice",1).toBool());
        ui->glCorCheck->setChecked(settings.value("CorSlice",1).toBool());
        ui->glAxiCheck->setChecked(settings.value("AxiSlice",1).toBool());
        ui->RenderingQualityBox->setCurrentIndex(settings.value("RenderingQuality",1).toInt());

        ui->view_style->setCurrentIndex((settings.value("view_style",0).toInt()));
        ui->RAS->setChecked(settings.value("RAS",0).toBool());
    }

    {
        scene.center();
        slice_no_update = false;
        copy_target = 0;
    }

    on_glAxiView_clicked();
    if(scene.neurology_convention)
        on_glAxiView_clicked();
    qApp->installEventFilter(this);
}
Beispiel #3
0
/* Function that loads all instrument data and which is called from IDirectMusicCollection_GetInstrument as in native */
HRESULT IDirectMusicInstrumentImpl_CustomLoad(IDirectMusicInstrument *iface, IStream *stream)
{
    IDirectMusicInstrumentImpl *This = impl_from_IDirectMusicInstrument(iface);
    HRESULT hr;
    DMUS_PRIVATE_CHUNK chunk;
    ULONG i = 0;
    ULONG length = This->length;

    TRACE("(%p, %p): offset = 0x%s, length = %u)\n", This, stream, wine_dbgstr_longlong(This->liInstrumentPosition.QuadPart), This->length);

    if (This->loaded)
        return S_OK;

    hr = IStream_Seek(stream, This->liInstrumentPosition, STREAM_SEEK_SET, NULL);
    if (FAILED(hr))
    {
        WARN("IStream_Seek failed: %08x\n", hr);
        return DMUS_E_UNSUPPORTED_STREAM;
    }

    This->regions = HeapAlloc(GetProcessHeap(), 0, sizeof(*This->regions) * This->header.cRegions);
    if (!This->regions)
        return E_OUTOFMEMORY;

    while (length)
    {
        hr = read_from_stream(stream, &chunk, sizeof(chunk));
        if (FAILED(hr))
            goto error;

        length = subtract_bytes(length, sizeof(chunk) + chunk.dwSize);

        switch (chunk.fccID)
        {
            case FOURCC_INSH:
            case FOURCC_DLID:
                TRACE("Chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);

                /* Instrument header and id are already set so just skip */
                hr = advance_stream(stream, chunk.dwSize);
                if (FAILED(hr))
                    goto error;

                break;

            case FOURCC_LIST: {
                DWORD size = chunk.dwSize;

                TRACE("LIST chunk: %u bytes\n", chunk.dwSize);

                hr = read_from_stream(stream, &chunk.fccID, sizeof(chunk.fccID));
                if (FAILED(hr))
                    goto error;

                size = subtract_bytes(size, sizeof(chunk.fccID));

                switch (chunk.fccID)
                {
                    case FOURCC_LRGN:
                        TRACE("LRGN chunk (regions list): %u bytes\n", size);

                        while (size)
                        {
                            hr = read_from_stream(stream, &chunk, sizeof(chunk));
                            if (FAILED(hr))
                                goto error;

                            if (chunk.fccID != FOURCC_LIST)
                            {
                                TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
                                goto error;
                            }

                            hr = read_from_stream(stream, &chunk.fccID, sizeof(chunk.fccID));
                            if (FAILED(hr))
                                goto error;

                            if (chunk.fccID == FOURCC_RGN)
                            {
                                TRACE("RGN chunk (region): %u bytes\n", chunk.dwSize);
                                hr = load_region(This, stream, &This->regions[i++], chunk.dwSize - sizeof(chunk.fccID));
                            }
                            else
                            {
                                TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
                                hr = advance_stream(stream, chunk.dwSize - sizeof(chunk.fccID));
                            }
                            if (FAILED(hr))
                                goto error;

                            size = subtract_bytes(size, chunk.dwSize + sizeof(chunk));
                        }
                        break;

                    case FOURCC_LART:
                        TRACE("LART chunk (articulations list): %u bytes\n", size);

                        while (size)
                        {
                            hr = read_from_stream(stream, &chunk, sizeof(chunk));
                            if (FAILED(hr))
                                goto error;

                            if (chunk.fccID == FOURCC_ART1)
                            {
                                TRACE("ART1 chunk (level 1 articulation): %u bytes\n", chunk.dwSize);
                                hr = load_articulation(This, stream, chunk.dwSize);
                            }
                            else
                            {
                                TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
                                hr = advance_stream(stream, chunk.dwSize);
                            }
                            if (FAILED(hr))
                                goto error;

                            size = subtract_bytes(size, chunk.dwSize + sizeof(chunk));
                        }
                        break;

                    default:
                        TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);

                        hr = advance_stream(stream, chunk.dwSize - sizeof(chunk.fccID));
                        if (FAILED(hr))
                            goto error;

                        size = subtract_bytes(size, chunk.dwSize - sizeof(chunk.fccID));
                        break;
                }
                break;
            }

            default:
                TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);

                hr = advance_stream(stream, chunk.dwSize);
                if (FAILED(hr))
                    goto error;

                break;
        }
    }

    This->loaded = TRUE;

    return S_OK;

error:
    HeapFree(GetProcessHeap(), 0, This->regions);
    This->regions = NULL;

    return DMUS_E_UNSUPPORTED_STREAM;
}