campcommhdreceiver.cpp 7.08 KB
Newer Older
1
2
3
4
// ================================================================================================
// 
// This file is part of the CAMPVis Software Framework.
// 
5
// If not explicitly stated otherwise: Copyright (C) 2012-2013, all rights reserved,
6
7
//      Christian Schulte zu Berge <christian.szb@in.tum.de>
//      Chair for Computer Aided Medical Procedures
8
9
10
//      Technische Universität München
//      Boltzmannstr. 3, 85748 Garching b. München, Germany
// 
11
12
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
// 
13
14
15
16
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 
// except in compliance with the License. You may obtain a copy of the License at
// 
// http://www.apache.org/licenses/LICENSE-2.0
17
// 
18
19
20
21
// Unless required by applicable law or agreed to in writing, software distributed under the 
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
// either express or implied. See the License for the specific language governing permissions 
// and limitations under the License.
22
23
24
// 
// ================================================================================================

25
26
#define CAMPCOM_FAST_SERIALIZATION

27
28
29
30
#include "campcommhdreceiver.h"

#include "core/datastructures/imagedata.h"
#include "core/datastructures/genericimagerepresentationlocal.h"
31
#include "core/tools/stringutils.h"
32
33
34
35
36
37
38
39
40
41
42
43
44

namespace campvis {
    const std::string CampcomMhdReceiver::loggerCat_ = "CAMPVis.modules.io.CampcomMhdReceiver";

    CampcomMhdReceiver::CampcomMhdReceiver() 
        : AbstractProcessor()
        , p_address("ServerAddress", "Server Address", "127.0.0.1")
        , p_connect("Connect", "Connect to Server", AbstractProcessor::VALID)
        , p_targetImageID("targetImageName", "Target Image ID", "CampcomMhdReceiver.output", DataNameProperty::WRITE)
        , p_imageOffset("ImageOffset", "Image Offset in mm", tgt::vec3(0.f), tgt::vec3(-10000.f), tgt::vec3(10000.f), tgt::vec3(0.1f))
        , p_voxelSize("VoxelSize", "Voxel Size in mm", tgt::vec3(1.f), tgt::vec3(-100.f), tgt::vec3(100.f), tgt::vec3(0.1f))
        , _ccclient(0)
    {
45
46
        _incomingMhd = 0;

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
        addProperty(&p_address);
        addProperty(&p_targetImageID);
        addProperty(&p_connect);
        addProperty(&p_imageOffset);
        addProperty(&p_voxelSize);

    }

    CampcomMhdReceiver::~CampcomMhdReceiver() {

    }

    void CampcomMhdReceiver::init() {
        p_connect.s_clicked.connect(this, &CampcomMhdReceiver::onBtnConnectClicked);
    }

    void CampcomMhdReceiver::deinit() {
        p_connect.s_clicked.disconnect(this);
65
66
67
68
        if (_ccclient) {
            _ccclient->disconnect();
            delete _ccclient;
        }
69
70
71
        _ccclient = 0;
    }

72
    void CampcomMhdReceiver::updateResult(DataContainer& data) {
73
74
        validate(INVALID_RESULT);

75
76
        // Get the last received MHD file:
        // Use atomic fetch and store because at the same time CAMPCom may receive another file!
77
78
79
80
        campcom::MHDImageData* mid = _incomingMhd.fetch_and_store(0);
        if (mid == 0)
            return;

81
        // Transform campcom::MHDImageData to campvis::ImageData
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
        int numChannels = 1;
        size_t dimensionality = mid->NDims;
        tgt::svec3 size(1);
        for (int i = 0; i < mid->DimSize.size(); ++i)
            size.elem[i] = mid->DimSize[i];

        WeaklyTypedPointer wtp;
        wtp._pointer = &(mid->imageData.front().front());
        wtp._numChannels = numChannels;

        std::string et = StringUtils::uppercase(mid->elementType);
        if (et == "MET_UCHAR")
            wtp._baseType = WeaklyTypedPointer::UINT8;
        else if (et == "MET_CHAR")
            wtp._baseType = WeaklyTypedPointer::INT8;
        else if (et == "MET_USHORT")
            wtp._baseType = WeaklyTypedPointer::UINT16;
        else if (et == "MET_SHORT")
            wtp._baseType = WeaklyTypedPointer::INT16;
        else if (et == "MET_UINT")
            wtp._baseType = WeaklyTypedPointer::UINT32;
        else if (et == "MET_INT")
            wtp._baseType = WeaklyTypedPointer::INT32;
        else if (et == "MET_FLOAT")
            wtp._baseType = WeaklyTypedPointer::FLOAT;
        else {
            LERROR("Error while parsing MHD header: Unsupported element type: " << et);
            return;
        }

        tgt::vec3 imageOffset(0.f);
        tgt::vec3 voxelSize(1.f);

115
        // all parsing done - lets create the image:
116
117
118
119
        ImageData* image = new ImageData(dimensionality, size, numChannels);
        ImageRepresentationLocal::create(image, wtp);
        image->setMappingInformation(ImageMappingInformation(size, imageOffset + p_imageOffset.getValue(), voxelSize * p_voxelSize.getValue()));
        data.addData(p_targetImageID.getValue(), image);
120
121
122
    }

    void CampcomMhdReceiver::onBtnConnectClicked() {
123
        // CAMPComClient does not support dis-/reconnect. So we have to delete it and recreate it.
124
125
126
127
128
129
        if (_ccclient) {
            _ccclient->disconnect();
            delete _ccclient;
            _ccclient = 0;
        }

130
        // create CAMPComClient and subscribe.
131
        _ccclient = new campcom::CAMPComClient("Campvis", campcom::Device_TestDevice, p_address.getValue());
132
        _ccclient->connect();
133

134
        if (_ccclient->isConnected()) {
135
136
137
            // use ugly boost magic to connect to member function (unfortunately CAMPCom only supports free functions...)
            campcom::DataCallback dc = boost::bind(&CampcomMhdReceiver::ccReceiveImage, this, _1);
            campcom::SuccessCallback sc = std::bind1st(std::mem_fun(&CampcomMhdReceiver::ccSuccessCallback), this);
138
139
140
141
            _ccclient->subscribe(campcom::Type_Image, dc, sc);
        }
        else {
            LWARNING("Could not connect to CAMPCom server.");
142
            delete _ccclient;
143
144
145
146
147
            _ccclient = 0;
        }
    }

    void CampcomMhdReceiver::ccReceiveImage(std::vector<campcom::Byte>& msg) {
148
        // Deserialize payload
149
150
151
        campcom::MHDImageData return_payload;
        campcom::Header header;
        campcom::TypeHandler<campcom::MHDImageData>::deserializePayload(&msg[0], msg.size(), return_payload);
152

153
154
        if (campcom::MHDImageData::isValid(return_payload)) {
            LINFO("New valid MHDImageData received! Pushing it to the DataContainer...");
155
156
157
158
159

            // putting the image into the DataContainer has to be done asynchroneously, because we
            // don't know the DataContainer here... :/
            // So copy the image one more time, but it into _incomingMhd and invalidate the processor.
            // Use atomic fetch and store because at the same time we may convert the last received image!
160
            campcom::MHDImageData* copy = new campcom::MHDImageData(return_payload);
161
162

            // delete old image not yet converted (if present)
163
164
165
166
167
168
169
170
            campcom::MHDImageData* toDelete = _incomingMhd.fetch_and_store(copy);
            delete toDelete;

            invalidate(INVALID_RESULT);
        }
        else {
            LWARNING("New MHDImageData received but it isn't valid!");
        }
171
172
173

    }

174
    void CampcomMhdReceiver::ccSuccessCallback(bool b) {
175
176
177
178
        LINFO("CAMPCom subscribe callback: " << b);
    }

}