source: nanovis/trunk/ZincBlendeReconstructor.cpp @ 4936

Last change on this file since 4936 was 4894, checked in by ldelgass, 9 years ago

sync with release branch

  • Property svn:eol-style set to native
File size: 16.1 KB
RevLine 
[2798]1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
[3502]2/*
3 * Copyright (c) 2004-2013  HUBzero Foundation, LLC
[3611]4 *
5 * Authors:
6 *   Insoo Woo <iwoo@purdue.edu>
[3502]7 */
[4894]8#include <cstdio>
9#include <cstring>
10#include <cstdlib>
11#include <fstream>
[2844]12
[3492]13#include <vrmath/Vector3f.h>
14
[3611]15#include "ZincBlendeReconstructor.h"
[601]16#include "ZincBlendeVolume.h"
[3492]17#include "Trace.h"
[601]18
[3611]19using namespace nv;
[3492]20using namespace vrmath;
21
[3611]22ZincBlendeReconstructor *ZincBlendeReconstructor::_instance = NULL;
[806]23
[3611]24ZincBlendeReconstructor::ZincBlendeReconstructor()
[601]25{
26}
27
[3611]28ZincBlendeReconstructor::~ZincBlendeReconstructor()
[601]29{
30}
31
[3611]32ZincBlendeReconstructor *ZincBlendeReconstructor::getInstance()
[601]33{
[2822]34    if (_instance == NULL) {
[3611]35        return (_instance = new ZincBlendeReconstructor());
[601]36    }
37
38    return _instance;
39}
40
[3611]41ZincBlendeVolume *ZincBlendeReconstructor::loadFromFile(const char *fileName)
[601]42{
[800]43    std::ifstream stream;
44    stream.open(fileName, std::ios::binary);
[617]45
[2822]46    ZincBlendeVolume *volume = loadFromStream(stream);
[617]47
48    stream.close();
49
50    return volume;
51}
52
[3611]53ZincBlendeVolume *ZincBlendeReconstructor::loadFromStream(std::istream& stream)
[617]54{
[2822]55    ZincBlendeVolume *volume = NULL;
[3492]56    Vector3f origin, delta;
[617]57    int width = 0, height = 0, depth = 0;
[2822]58    void *data = NULL;
[800]59    int version = 1;
[617]60
61    char str[5][20];
62    do {
63        getLine(stream);
[4063]64        if (_buff[0] == '#') {
[800]65            continue;
[4063]66        } else if (strstr((const char*) _buff, "object") != 0) {
[3452]67            TRACE("VERSION 1");
[2822]68            version = 1;
69            break;
[4063]70        } else if (strstr(_buff, "record format") != 0) {
[3452]71            TRACE("VERSION 2");
[2822]72            version = 2;
73            break;
[800]74        }
[2822]75    } while (1);
[617]76
[953]77    if (version == 1) {
78        float dummy;
79
[4063]80        sscanf(_buff, "%s%s%s%s%s%d%d%d", str[0], str[1], str[2], str[3], str[4], &width, &height, &depth);
[800]81        getLine(stream);
[4063]82        sscanf(_buff, "%s%f%f%f", str[0], &(origin.x), &(origin.y), &(origin.z));
[800]83        getLine(stream);
[4063]84        sscanf(_buff, "%s%f%f%f", str[0], &(delta.x), &dummy, &dummy);
[800]85        getLine(stream);
[4063]86        sscanf(_buff, "%s%f%f%f", str[0], &dummy, &(delta.y), &dummy);
[800]87        getLine(stream);
[4063]88        sscanf(_buff, "%s%f%f%f", str[0], &dummy, &dummy, &(delta.z));
[800]89        do {
90            getLine(stream);
[4063]91        } while (strcmp(_buff, "<\\HDR>") != 0);
[617]92
[800]93        width = width / 4;
94        height = height / 4;
95        depth = depth / 4;
96        //data = new double[width * height * depth * 8 * 4];
97        data = malloc(width * height * depth * 8 * 4 * sizeof(double));
[2822]98        // 8 atom per cell, 4 double (x, y, z, and probability) per atom
[800]99        try {
[2822]100            stream.read((char *)data, width * height * depth * 8 * 4 * sizeof(double));
101        } catch (...) {
[3452]102            ERROR("Caught exception trying to read stream");
[800]103        }
[617]104
[800]105        volume = buildUp(origin, delta, width, height, depth, data);
[617]106
[800]107        free(data);
[2822]108    } else if (version == 2) {
109        const char *pt;
[800]110        int datacount;
111        double emptyvalue;
112        do {
113            getLine(stream);
[4063]114            if ((pt = strstr(_buff, "delta")) != 0) {
[800]115                sscanf(pt, "%s%f%f%f", str[0], &(delta.x), &(delta.y), &(delta.z));
[806]116#ifdef _LOADER_DEBUG_
[3452]117                TRACE("delta : %f %f %f", delta.x, delta.y, delta.z);
[806]118#endif
[4063]119            } else if ((pt = strstr(_buff, "datacount")) != 0) {
[800]120                sscanf(pt, "%s%d", str[0], &datacount);
[806]121#ifdef _LOADER_DEBUG_
[3452]122                TRACE("datacount = %d", datacount);
[806]123#endif
[4063]124            } else if ((pt = strstr(_buff, "datatype")) != 0) {
[800]125                sscanf(pt, "%s%s", str[0], str[1]);
[2822]126                if (strcmp(str[1], "double64")) {
[800]127                }
[4063]128            } else if ((pt = strstr(_buff, "count")) != 0) {
[800]129                sscanf(pt, "%s%d%d%d", str[0], &width, &height, &depth);
[806]130#ifdef _LOADER_DEBUG_
[3452]131                TRACE("width height depth %d %d %d", width, height, depth);
[806]132#endif
[4063]133            } else if ((pt = strstr(_buff, "emptymark")) != 0) {
[800]134                sscanf(pt, "%s%lf", str[0], &emptyvalue);
[806]135#ifdef _LOADER_DEBUG_
[3452]136                TRACE("emptyvalue %lf", emptyvalue);
[806]137#endif
[4063]138            } else if ((pt = strstr(_buff, "emprymark")) != 0) {
[800]139                sscanf(pt, "%s%lf", str[0], &emptyvalue);
[806]140#ifdef _LOADER_DEBUG_
[3452]141                TRACE("emptyvalue %lf", emptyvalue);
[806]142#endif
[800]143            }
[4063]144        } while (strcmp(_buff, "<\\HDR>") != 0 && strcmp(_buff, "</HDR>") != 0);
[800]145
146        data = malloc(width * height * depth * 8 * 4 * sizeof(double));
[804]147        memset(data, 0, width * height * depth * 8 * 4 * sizeof(double));
[2822]148        stream.read((char *) data, width * height * depth * 8 * 4 * sizeof(double));
[800]149
150        volume =  buildUp(origin, delta, width, height, depth, datacount, emptyvalue, data);
151        free(data);
[617]152    }
[800]153    return volume;
[601]154}
155
[617]156struct _NvAtomInfo {
157    double indexX, indexY, indexZ;
158    double atom;
[601]159
160    int getIndex(int width, int height) const
161    {
162        // NOTE
[2844]163        // Zinc blende data has different axes from OpenGL
[601]164        // + z -> +x (OpenGL)
165        // + x -> +y (OpenGL)
166        // + y -> +z (OpenGL), But in 3D texture coordinate is the opposite direction of z
[2844]167        // The reason why index is multiplied by 4 is that one unit cell has half of eight atoms,
168        // i.e. four atoms are mapped into RGBA component of one texel
[777]169        //return ((int) (indexZ - 1)+ (int) (indexX - 1) * width + (int) (indexY - 1) * width * height) * 4;
[2822]170        return ((int)(indexX - 1) + (int)(indexY - 1) * width + (int)(indexZ - 1) * width * height) * 4;
[601]171    }
172};
173
174template<class T>
[2822]175inline T _NvMax2(T a, T b)
176{ return ((a >= b)? a : b); }
[601]177
178template<class T>
[2822]179inline T _NvMin2(T a, T b)
180{ return ((a >= b)? a : b); }
[601]181
182template<class T>
[2822]183inline T _NvMax3(T a, T b, T c)
184{ return ((a >= b)? ((a >= c) ? a : c) : ((b >= c)? b : c)); }
[601]185
186template<class T>
[2822]187inline T _NvMin3(T a, T b, T c)
188{ return ((a <= b)? ((a <= c) ? a : c) : ((b <= c)? b : c)); }
[601]189
190template<class T>
[2822]191inline T _NvMax9(T* a, T curMax)
192{ return _NvMax3(_NvMax3(a[0], a[1], a[2]), _NvMax3(a[3], a[4], a[5]), _NvMax3(a[6], a[7], curMax)); }
[601]193
194template<class T>
[2822]195inline T _NvMin9(T* a, T curMax)
196{ return _NvMin3(_NvMax3(a[0], a[1], a[2]), _NvMin3(a[3], a[4], a[5]), _NvMin3(a[6], a[7], curMax)); }
[601]197
[617]198template<class T>
[2822]199inline T _NvMax4(T* a)
200{ return _NvMax2(_NvMax2(a[0], a[1]), _NvMax2(a[2], a[3])); }
[617]201
202template<class T>
[2822]203inline T _NvMin4(T* a)
204{ return _NvMin2(_NvMin2(a[0], a[1]), _NvMin2(a[2], a[3])); }
[617]205
[2822]206ZincBlendeVolume *
[3611]207ZincBlendeReconstructor::buildUp(const Vector3f& origin, const Vector3f& delta,
[2844]208                                   int width, int height, int depth, void *data)
[601]209{
[2822]210    ZincBlendeVolume *zincBlendeVolume = NULL;
[601]211
[617]212    float *fourAnionVolume, *fourCationVolume;
[601]213    int cellCount = width * height * depth;
[617]214    fourAnionVolume = new float[cellCount * sizeof(float) * 4];
215    fourCationVolume = new float[cellCount * sizeof(float) * 4];
[601]216
[2822]217    _NvAtomInfo *srcPtr = (_NvAtomInfo *)data;
[601]218
[777]219    float vmin, vmax, nzero_min;
[2822]220    float *component4A, *component4B;
[601]221    int index;
222
[953]223    nzero_min = 0.0f;           /* Suppress compiler warning. */
[617]224    vmin = vmax = srcPtr->atom;
225
[2822]226    for (int i = 0; i < cellCount; ++i) {
[601]227        index = srcPtr->getIndex(width, height);
[804]228
[806]229#ifdef _LOADER_DEBUG_
[3452]230        TRACE("index %d", index);
[806]231#endif
[804]232
[617]233        component4A = fourAnionVolume + index;
234        component4B = fourCationVolume + index;
[601]235
[2822]236        component4A[0] = (float)srcPtr->atom; srcPtr++;
237        component4A[1] = (float)srcPtr->atom; srcPtr++;
238        component4A[2] = (float)srcPtr->atom; srcPtr++;
239        component4A[3] = (float)srcPtr->atom; srcPtr++;
[617]240     
[2822]241        component4B[0] = (float)srcPtr->atom; srcPtr++;
242        component4B[1] = (float)srcPtr->atom; srcPtr++;
243        component4B[2] = (float)srcPtr->atom; srcPtr++;
244        component4B[3] = (float)srcPtr->atom; srcPtr++;
[601]245
[617]246        vmax = _NvMax3(_NvMax4(component4A), _NvMax4(component4B), vmax);
247        vmin = _NvMin3(_NvMin4(component4A), _NvMin4(component4B), vmin);
[777]248
[2822]249        if (vmin != 0.0 && vmin < nzero_min) {
250            nzero_min = vmin;
[777]251        }
[617]252    }
[601]253
[617]254    double dv = vmax - vmin;
[2822]255    if (vmax != 0.0f) {
256        for (int i = 0; i < cellCount; ++i) {
[617]257            fourAnionVolume[i] = (fourAnionVolume[i] - vmin)/ dv;
258            fourCationVolume[i] = (fourCationVolume[i] - vmin) / dv;
259        }
260    }
[601]261
[3492]262    Vector3f cellSize;
[617]263    cellSize.x = 0.25 / width;
264    cellSize.y = 0.25 / height;
265    cellSize.z = 0.25 / depth;
[601]266
[3630]267    zincBlendeVolume = new ZincBlendeVolume(width, height, depth, 4,
[617]268                                            fourAnionVolume, fourCationVolume,
[777]269                                            vmin, vmax, nzero_min, cellSize);
[601]270
[3630]271    zincBlendeVolume->xAxis.setRange(origin.x, origin.x + delta.x * (width-1));
272    zincBlendeVolume->yAxis.setRange(origin.y, origin.y + delta.y * (height-1));
273    zincBlendeVolume->zAxis.setRange(origin.z, origin.z + delta.z * (depth-1));
274
[601]275    return zincBlendeVolume;
276}
277
[2822]278ZincBlendeVolume *
[3611]279ZincBlendeReconstructor::buildUp(const Vector3f& origin, const Vector3f& delta,
[2822]280                                   int width, int height, int depth,
281                                   int datacount, double emptyvalue, void* data)
[800]282{
[2822]283    ZincBlendeVolume *zincBlendeVolume = NULL;
[800]284    float *fourAnionVolume, *fourCationVolume;
285    int size = width * height * depth * 4;
286    fourAnionVolume = new float[size];
287    fourCationVolume = new float[size];
288
289    memset(fourAnionVolume, 0, size * sizeof(float));
290    memset(fourCationVolume, 0, size * sizeof(float));
291
[2822]292    _NvAtomInfo *srcPtr = (_NvAtomInfo *) data;
[800]293
[2822]294    float *component4A, *component4B;
[800]295    float vmin, vmax, nzero_min;
296    int index;
297    nzero_min = 1e23f;
298    vmin = vmax = srcPtr->atom;
[2822]299    for (int i = 0; i < datacount; ++i) {
[800]300        index = srcPtr->getIndex(width, height);
[806]301
302#ifdef _LOADER_DEBUG_
[3452]303        TRACE("[%d] index %d (width:%lf height:%lf depth:%lf)", i, index, srcPtr->indexX, srcPtr->indexY, srcPtr->indexZ);
[806]304#endif
[804]305
306        if (index < 0) {
[806]307#ifdef _LOADER_DEBUG_
[3452]308            TRACE("There is an invalid data");
[806]309#endif
[804]310            srcPtr +=8;
311            continue;
312        }
313
[800]314        component4A = fourAnionVolume + index;
315        component4B = fourCationVolume + index;
316
317        component4A[0] = (srcPtr->atom != emptyvalue)? (float) srcPtr->atom : 0.0f; srcPtr++;
318        component4A[1] = (srcPtr->atom != emptyvalue)? (float) srcPtr->atom : 0.0f; srcPtr++;
319        component4A[2] = (srcPtr->atom != emptyvalue)? (float) srcPtr->atom : 0.0f; srcPtr++;
320        component4A[3] = (srcPtr->atom != emptyvalue)? (float) srcPtr->atom : 0.0f; srcPtr++;
321     
322        component4B[0] = (srcPtr->atom != emptyvalue)? (float) srcPtr->atom : 0.0f; srcPtr++;
323        component4B[1] = (srcPtr->atom != emptyvalue)? (float) srcPtr->atom : 0.0f; srcPtr++;
324        component4B[2] = (srcPtr->atom != emptyvalue)? (float) srcPtr->atom : 0.0f; srcPtr++;
325        component4B[3] = (srcPtr->atom != emptyvalue)? (float) srcPtr->atom : 0.0f; srcPtr++;
326
327        vmax = _NvMax3(_NvMax4(component4A), _NvMax4(component4B), vmax);
328        vmin = _NvMin3(_NvMin4(component4A), _NvMin4(component4B), vmin);
329
[2822]330        if (vmin != 0.0 && vmin < nzero_min) {
[800]331            nzero_min = vmin;   
332        }
333    }
334
335    double dv = vmax - vmin;
[2822]336    if (vmax != 0.0f) {
337        for (int i = 0; i < datacount; ++i) {
[800]338            fourAnionVolume[i] = (fourAnionVolume[i] - vmin)/ dv;
339            fourCationVolume[i] = (fourCationVolume[i] - vmin) / dv;
340        }
341    }
342
[3492]343    Vector3f cellSize;
[800]344    cellSize.x = 0.25 / width;
345    cellSize.y = 0.25 / height;
346    cellSize.z = 0.25 / depth;
347
[3630]348    zincBlendeVolume = new ZincBlendeVolume(width, height, depth, 4,
[800]349                                            fourAnionVolume, fourCationVolume,
350                                            vmin, vmax, nzero_min, cellSize);
351
[3630]352    zincBlendeVolume->xAxis.setRange(origin.x, origin.x + delta.x * (width-1));
353    zincBlendeVolume->yAxis.setRange(origin.y, origin.y + delta.y * (height-1));
354    zincBlendeVolume->zAxis.setRange(origin.z, origin.z + delta.z * (depth-1));
355
[800]356    return zincBlendeVolume;
357}
358
[3611]359void ZincBlendeReconstructor::getLine(std::istream& sin)
[617]360{
361    char ch;
362    int index = 0;
363    do {
364        sin.get(ch);
365        if (ch == '\n') break;
[4063]366        _buff[index++] = ch;
[2822]367        if (ch == '>') {
[4063]368            if (_buff[1] == '\\')
[617]369                break;
370        }
371    } while (!sin.eof());
372
[4063]373    _buff[index] = '\0';
[804]374
[806]375#ifdef _LOADER_DEBUG_
[4063]376    TRACE("%s", _buff);
[806]377#endif
[617]378}
379
[2822]380ZincBlendeVolume *
[4063]381ZincBlendeReconstructor::loadFromMemory(const void *dataBlock)
[804]382{
[2822]383    ZincBlendeVolume *volume = NULL;
[3492]384    Vector3f origin, delta;
[804]385    int width = 0, height = 0, depth = 0;
[2822]386    void *data = NULL;
[804]387    int version = 1;
388
[4063]389    const unsigned char *stream = (const unsigned char *)dataBlock;
[804]390    char str[5][20];
391    do {
392        getLine(stream);
[4063]393        if (_buff[0] == '#') {
[804]394            continue;
[4063]395        } else if (strstr((const char *)_buff, "object") != 0) {
[3452]396            TRACE("VERSION 1");
[2822]397            version = 1;
398            break;
[4063]399        } else if (strstr(_buff, "record format") != 0) {
[3452]400            TRACE("VERSION 2");
[2822]401            version = 2;
402            break;
[804]403        }
[2822]404    } while (1);
[804]405
[2822]406    if (version == 1) {
[953]407        float dummy;
408
[4063]409        sscanf(_buff, "%s%s%s%s%s%d%d%d", str[0], str[1], str[2], str[3], str[4],&width, &height, &depth);
[804]410        getLine(stream);
[4063]411        sscanf(_buff, "%s%f%f%f", str[0], &(origin.x), &(origin.y), &(origin.z));
[804]412        getLine(stream);
[4063]413        sscanf(_buff, "%s%f%f%f", str[0], &(delta.x), &dummy, &dummy);
[804]414        getLine(stream);
[4063]415        sscanf(_buff, "%s%f%f%f", str[0], &dummy, &(delta.y), &dummy);
[804]416        getLine(stream);
[4063]417        sscanf(_buff, "%s%f%f%f", str[0], &dummy, &dummy, &(delta.z));
[804]418        do {
419            getLine(stream);
[4063]420        } while (strcmp(_buff, "<\\HDR>") != 0);
[804]421
422        width = width / 4;
423        height = height / 4;
424        depth = depth / 4;
425        data = malloc(width * height * depth * 8 * 4 * sizeof(double));
[2822]426        // 8 atom per cell, 4 double (x, y, z, and probability) per atom
427        memcpy(data, stream, width * height * depth * 8 * 4 * sizeof(double));
[804]428
429        volume = buildUp(origin, delta, width, height, depth, data);
430
431        free(data);
[2822]432    } else if (version == 2) {
433        const char *pt;
[804]434        int datacount = -1;
435        double emptyvalue;
436        do {
437            getLine(stream);
[4063]438            if ((pt = strstr(_buff, "delta")) != 0) {   
[804]439                sscanf(pt, "%s%f%f%f", str[0], &(delta.x), &(delta.y), &(delta.z));
[806]440#ifdef _LOADER_DEBUG_
[3452]441                TRACE("delta : %f %f %f", delta.x, delta.y, delta.z);
[806]442#endif
[4063]443            } else if ((pt = strstr(_buff, "datacount")) != 0) {
[804]444                sscanf(pt, "%s%d", str[0], &datacount);
[3452]445                TRACE("datacount = %d", datacount);
[4063]446            } else if ((pt = strstr(_buff, "datatype")) != 0) {
[804]447                sscanf(pt, "%s%s", str[0], str[1]);
[2822]448                if (strcmp(str[1], "double64")) {
[804]449                }
[4063]450            } else if ((pt = strstr(_buff, "count")) != 0) {
[804]451                sscanf(pt, "%s%d%d%d", str[0], &width, &height, &depth);
[806]452#ifdef _LOADER_DEBUG_
[3452]453                TRACE("width height depth %d %d %d", width, height, depth);
[806]454#endif
[4063]455            } else if ((pt = strstr(_buff, "emptymark")) != 0) {
[804]456                sscanf(pt, "%s%lf", str[0], &emptyvalue);
[806]457#ifdef _LOADER_DEBUG_
[3452]458                TRACE("emptyvalue %lf", emptyvalue);
[806]459#endif
[4063]460            } else if ((pt = strstr(_buff, "emprymark")) != 0) {
[804]461                sscanf(pt, "%s%lf", str[0], &emptyvalue);
[806]462#ifdef _LOADER_DEBUG_
[3452]463                TRACE("emptyvalue %lf", emptyvalue);
[806]464#endif
[804]465            }
[4063]466        } while (strcmp(_buff, "<\\HDR>") != 0 && strcmp(_buff, "</HDR>") != 0);
[804]467
468        if (datacount == -1) datacount = width * height * depth;
469
470        data = malloc(datacount * 8 * 4 * sizeof(double));
471        memset(data, 0, datacount * 8 * 4 * sizeof(double));
472        memcpy(data, stream, datacount * 8 * 4 * sizeof(double));
473
474        volume =  buildUp(origin, delta, width, height, depth, datacount, emptyvalue, data);
475
476        free(data);
477    }
478    return volume;
479}
480
[4063]481void ZincBlendeReconstructor::getLine(const unsigned char*& stream)
[804]482{
483    char ch;
484    int index = 0;
485    do {
486        ch = stream[0];
487        ++stream;
488        if (ch == '\n') break;
[4063]489        _buff[index++] = ch;
[2822]490        if (ch == '>') {
[4063]491            if (_buff[1] == '\\')
[804]492                break;
493        }
494    } while (1);
495
[4063]496    _buff[index] = '\0';
[804]497
[806]498#ifdef _LOADER_DEBUG_
[4063]499    TRACE("%s", _buff);
[806]500#endif
[804]501}
Note: See TracBrowser for help on using the repository browser.