/// <summary>
        /// Creates a histogram texture for 2D transfer functions.
        ///   X-axis = data sample (density) value
        ///   Y-axis = gradient magnitude
        ///   colour = white (if there is a data sample with the specified value and gradient magnitude) or black (if not)
        /// </summary>
        /// <param name="dataset"></param>
        /// <returns></returns>
        public static Texture2D Generate2DHistogramTexture(VolumeDataset dataset)
        {
            float minValue = dataset.GetMinDataValue();
            float maxValue = dataset.GetMaxDataValue();

            // Value range of the density values.
            float densityValRange   = maxValue - minValue + 1.0f;
            float densityRangeRecip = 1.0f / (maxValue - minValue); // reciprocal
            // Clamp density value samples.
            int numDensitySamples  = System.Math.Min((int)densityValRange, 512);
            int numGradientSamples = 256;

            Color[]   cols    = new Color[numDensitySamples * numGradientSamples];
            Texture2D texture = new Texture2D(numDensitySamples, numGradientSamples, TextureFormat.RGBAFloat, false);

            // Zero-initialise colours.
            for (int iCol = 0; iCol < cols.Length; iCol++)
            {
                cols[iCol] = new Color(0.0f, 0.0f, 0.0f, 0.0f);
            }

            float       maxRange = dataset.GetMaxDataValue() - dataset.GetMinDataValue();
            const float maxNormalisedMagnitude = 1.75f; // sqrt(1^2 + 1^2 + 1^2) = swrt(3) = a bit less than 1.75

            for (int x = 1; x < dataset.dimX - 1; x++)
            {
                for (int y = 1; y < dataset.dimY - 1; y++)
                {
                    for (int z = 1; z < dataset.dimZ - 1; z++)
                    {
                        int iData   = x + y * dataset.dimX + z * (dataset.dimX * dataset.dimY);
                        int density = Mathf.RoundToInt(dataset.data[iData]); // FIXME

                        float x1 = dataset.data[(x + 1) + y * dataset.dimX + z * (dataset.dimX * dataset.dimY)];
                        float x2 = dataset.data[(x - 1) + y * dataset.dimX + z * (dataset.dimX * dataset.dimY)];
                        float y1 = dataset.data[x + (y + 1) * dataset.dimX + z * (dataset.dimX * dataset.dimY)];
                        float y2 = dataset.data[x + (y - 1) * dataset.dimX + z * (dataset.dimX * dataset.dimY)];
                        float z1 = dataset.data[x + y * dataset.dimX + (z + 1) * (dataset.dimX * dataset.dimY)];
                        float z2 = dataset.data[x + y * dataset.dimX + (z - 1) * (dataset.dimX * dataset.dimY)];

                        // Calculate gradient
                        Vector3 grad = new Vector3((x2 - x1) / (float)maxRange, (y2 - y1) / (float)maxRange, (z2 - z1) / (float)maxRange);

                        // Calculate density and gradient value indices (in flattened 2D array)
                        float tDensity = (density - minValue) * densityRangeRecip;
                        int   iDensity = Mathf.RoundToInt((numDensitySamples - 1) * tDensity);
                        int   iGrad    = (int)(grad.magnitude * numGradientSamples / maxNormalisedMagnitude);

                        // Assign a white colour to all samples (in a histogram where x = density and y = gradient magnitude).
                        cols[iDensity + iGrad * numDensitySamples] = Color.white;
                    }
                }
            }

            texture.SetPixels(cols);
            texture.Apply();

            return(texture);
        }
        public static Texture2D GenerateHistogramTexture(VolumeDataset dataset)
        {
            int minValue = dataset.GetMinDataValue();
            int maxValue = dataset.GetMaxDataValue();

            int numSamples = maxValue - minValue + 1;

            int[]     values  = new int[numSamples];
            Color[]   cols    = new Color[numSamples];
            Texture2D texture = new Texture2D(numSamples, 1, TextureFormat.RGBAFloat, false);

            int maxFreq = 0;

            for (int iData = 0; iData < dataset.data.Length; iData++)
            {
                int dataValue = dataset.data[iData] - minValue;
                values[dataValue] += 1;
                maxFreq            = System.Math.Max(values[dataValue], maxFreq);
            }

            for (int iSample = 0; iSample < numSamples; iSample++)
            {
                cols[iSample] = new Color(Mathf.Log10((float)values[iSample]) / Mathf.Log10((float)maxFreq), 0.0f, 0.0f, 1.0f);
            }

            texture.SetPixels(cols);
            texture.Apply();

            return(texture);
        }
        /// <summary>
        /// Generates a histogram where:
        ///   X-axis = the data sample (density) value
        ///   Y-axis = the sample count (number of data samples with the specified density)
        /// </summary>
        /// <param name="dataset"></param>
        /// <returns></returns>
        public static Texture2D GenerateHistogramTexture(VolumeDataset dataset)
        {
            int minValue  = dataset.GetMinDataValue();
            int maxValue  = dataset.GetMaxDataValue();
            int numValues = maxValue - minValue + 1;

            float valRangeRecip = 1.0f / (maxValue - minValue);

            int numSamples = System.Math.Min(numValues, 1024);

            int[]     values  = new int[numSamples];
            Color[]   cols    = new Color[numSamples];
            Texture2D texture = new Texture2D(numSamples, 1, TextureFormat.RGBAFloat, false);

            int maxFreq = 0;

            for (int iData = 0; iData < dataset.data.Length; iData++)
            {
                int   dataValue  = dataset.data[iData];
                float tValue     = (dataValue - minValue) * valRangeRecip;
                int   valueIndex = Mathf.RoundToInt((numSamples - 1) * tValue);
                values[valueIndex] += 1;
                maxFreq             = System.Math.Max(values[valueIndex], maxFreq);
            }

            for (int iSample = 0; iSample < numSamples; iSample++)
            {
                cols[iSample] = new Color(Mathf.Log10((float)values[iSample]) / Mathf.Log10((float)maxFreq), 0.0f, 0.0f, 1.0f);
            }

            texture.SetPixels(cols);
            texture.Apply();

            return(texture);
        }
        /// <summary>
        /// Generates a histogram (but computaion is done on GPU) where:
        ///   X-axis = the data sample (density) value
        ///   Y-axis = the sample count (number of data samples with the specified density)
        /// </summary>
        /// <param name="dataset"></param>
        /// <returns></returns>
        public static Texture2D GenerateHistogramTextureOnGPU(VolumeDataset dataset)
        {
            double actualBound = dataset.GetMaxDataValue() - dataset.GetMinDataValue() + 1;
            int    numValues   = System.Convert.ToInt32(dataset.GetMaxDataValue() - dataset.GetMinDataValue() + 1); // removed +1
            int    sampleCount = System.Math.Min(numValues, 256);

            ComputeShader computeHistogram = Resources.Load("ComputeHistogram") as ComputeShader;
            int           handleInitialize = computeHistogram.FindKernel("HistogramInitialize");
            int           handleMain       = computeHistogram.FindKernel("HistogramMain");

            ComputeBuffer histogramBuffer = new ComputeBuffer(sampleCount, sizeof(uint) * 1);

            uint[]    histogramData = new uint[sampleCount];
            Color32[] histogramCols = new Color32[sampleCount];

            Texture3D dataTexture = dataset.GetDataTexture();

            if (handleInitialize < 0 || handleMain < 0)
            {
                Debug.LogError("Histogram compute shader initialization failed.");
            }

            computeHistogram.SetFloat("ValueRange", (float)(numValues - 1));
            computeHistogram.SetTexture(handleMain, "VolumeTexture", dataTexture);
            computeHistogram.SetBuffer(handleMain, "HistogramBuffer", histogramBuffer);
            computeHistogram.SetBuffer(handleInitialize, "HistogramBuffer", histogramBuffer);

            computeHistogram.Dispatch(handleInitialize, sampleCount / 8, 1, 1);
            computeHistogram.Dispatch(handleMain, (dataTexture.width + 7) / 8, (dataTexture.height + 7) / 8, (dataTexture.depth + 7) / 8);

            histogramBuffer.GetData(histogramData);

            int maxValue = (int)histogramData.Max();

            Texture2D texture = new Texture2D(sampleCount, 1, TextureFormat.RGBA32, false);

            for (int iSample = 0; iSample < sampleCount; iSample++)
            {
                histogramCols[iSample] = new Color(Mathf.Log10((float)histogramData[iSample]) / Mathf.Log10((float)maxValue), 0.0f, 0.0f, 1.0f);
            }

            texture.SetPixels32(histogramCols);
            texture.Apply();

            return(texture);
        }
        public static Texture2D Generate2DHistogramTexture(VolumeDataset dataset)
        {
            int numSamples         = dataset.GetMaxDataValue() + 1;
            int numGradientSamples = 256;

            Color[]   cols    = new Color[numSamples * numGradientSamples];
            Texture2D texture = new Texture2D(numSamples, numGradientSamples, TextureFormat.RGBAFloat, false);

            for (int iCol = 0; iCol < cols.Length; iCol++)
            {
                cols[iCol] = new Color(0.0f, 0.0f, 0.0f, 0.0f);
            }

            int         maxRange = dataset.GetMaxDataValue() - dataset.GetMinDataValue();
            const float maxNormalisedMagnitude = 1.75f; // sqrt(1^2 + 1^2 + 1^2) = swrt(3) = a bit less than 1.75

            for (int x = 1; x < dataset.dimX - 1; x++)
            {
                for (int y = 1; y < dataset.dimY - 1; y++)
                {
                    for (int z = 1; z < dataset.dimZ - 1; z++)
                    {
                        int iData   = x + y * dataset.dimX + z * (dataset.dimX * dataset.dimY);
                        int density = dataset.data[iData];

                        int x1 = dataset.data[(x + 1) + y * dataset.dimX + z * (dataset.dimX * dataset.dimY)];
                        int x2 = dataset.data[(x - 1) + y * dataset.dimX + z * (dataset.dimX * dataset.dimY)];
                        int y1 = dataset.data[x + (y + 1) * dataset.dimX + z * (dataset.dimX * dataset.dimY)];
                        int y2 = dataset.data[x + (y - 1) * dataset.dimX + z * (dataset.dimX * dataset.dimY)];
                        int z1 = dataset.data[x + y * dataset.dimX + (z + 1) * (dataset.dimX * dataset.dimY)];
                        int z2 = dataset.data[x + y * dataset.dimX + (z - 1) * (dataset.dimX * dataset.dimY)];

                        Vector3 grad = new Vector3((x2 - x1) / (float)maxRange, (y2 - y1) / (float)maxRange, (z2 - z1) / (float)maxRange);
                        cols[density + (int)(grad.magnitude * numGradientSamples / maxNormalisedMagnitude) * numSamples] = Color.white;
                    }
                }
            }

            texture.SetPixels(cols);
            texture.Apply();

            return(texture);
        }
        /// <summary>
        /// Generates a histogram where:
        ///   X-axis = the data sample (density) value
        ///   Y-axis = the sample count (number of data samples with the specified density)
        /// </summary>
        /// <param name="dataset"></param>
        /// <returns></returns>
        public static Texture2D GenerateHistogramTexture(VolumeDataset dataset)
        {
            float minValue   = dataset.GetMinDataValue();
            float maxValue   = dataset.GetMaxDataValue();
            float valueRange = maxValue - minValue;

            int numFrequencies = Mathf.Min((int)valueRange, 1024);

            int[] frequencies = new int[numFrequencies];

            int   maxFreq       = 0;
            float valRangeRecip = 1.0f / (maxValue - minValue);

            for (int iData = 0; iData < dataset.data.Length; iData++)
            {
                float dataValue = dataset.data[iData];
                float tValue    = (dataValue - minValue) * valRangeRecip;
                int   freqIndex = (int)(tValue * (numFrequencies - 1));
                frequencies[freqIndex] += 1;
                maxFreq = System.Math.Max(frequencies[freqIndex], maxFreq);
            }

            Color[]   cols    = new Color[numFrequencies];
            Texture2D texture = new Texture2D(numFrequencies, 1, TextureFormat.RGBAFloat, false);

            for (int iSample = 0; iSample < numFrequencies; iSample++)
            {
                cols[iSample] = new Color(Mathf.Log10((float)frequencies[iSample]) / Mathf.Log10((float)maxFreq), 0.0f, 0.0f, 1.0f);
            }

            texture.SetPixels(cols);
            //texture.filterMode = FilterMode.Point;
            texture.Apply();

            return(texture);
        }
Beispiel #7
0
        public override VolumeDataset Import()
        {
            // Check that the file exists
            if (!File.Exists(filePath))
            {
                Debug.LogError("The file does not exist: " + filePath);
                return(null);
            }

            FileStream   fs     = new FileStream(filePath, FileMode.Open);
            BinaryReader reader = new BinaryReader(fs);

            // Check that the dimension does not exceed the file size
            long expectedFileSize = (long)(dimX * dimY * dimZ) * GetSampleFormatSize(contentFormat) + skipBytes;

            if (fs.Length < expectedFileSize)
            {
                Debug.LogError($"The dimension({dimX}, {dimY}, {dimZ}) exceeds the file size. Expected file size is {expectedFileSize} bytes, while the actual file size is {fs.Length} bytes");
                reader.Close();
                fs.Close();
                return(null);
            }

            VolumeDataset dataset = new VolumeDataset();

            dataset.datasetName = Path.GetFileName(filePath);
            dataset.dimX        = dimX;
            dataset.dimY        = dimY;
            dataset.dimZ        = dimZ;

            // Skip header (if any)
            if (skipBytes > 0)
            {
                reader.ReadBytes(skipBytes);
            }

            int uDimension = dimX * dimY * dimZ;

            dataset.data = new int[uDimension];

            // Read the data/sample values
            for (int i = 0; i < uDimension; i++)
            {
                dataset.data[i] = ReadDataValue(reader);
            }
            Debug.Log("Loaded dataset in range: " + dataset.GetMinDataValue() + "  -  " + dataset.GetMaxDataValue());

            reader.Close();
            fs.Close();
            return(dataset);
        }
Beispiel #8
0
        public VolumeDataset Import() //fills VolumeDataset object
        {
            var extension = Path.GetExtension(filePath);

            if (!File.Exists(filePath))
            {
                Debug.LogError("The file does not exist: " + filePath);
                return(null);
            }

            fileContentLines = File.ReadLines(filePath).Where(x => x.Trim(' ') != "").ToArray();
            fileContentIndex = 0;

            ReadSystemTitle();
            ReadLatticeConstant();
            ReadLatticeVectors();
            GetVolume();
            ReadAtomNames();
            ReadAtomSum();
            ReadCoordinateSystemType();
            ReadCoordinates();
            if (isDirect)
            {
                cartesiancoordinatebasisCells = ToCartesian();
            }

            ReadDimensions();
            dimTotal = dimArray[0] * dimArray[1] * dimArray[2];
            nx       = dimArray[0];
            ny       = dimArray[1];
            nz       = dimArray[2]; // dimensions

            CalculateDataLines();
            ReadGrid();

            VolumeDataset dataFiller = new VolumeDataset(); //volume object then gets sent to VolumeObjectFactory

            dataFiller.datasetName = fileName;
            dataFiller.filePath    = filePath;
            dataFiller.dimX        = nx;
            dataFiller.dimY        = ny;
            dataFiller.dimZ        = nz;
            dataFiller.volumeScale = (float)(1 / volumeScale);
            dataFiller.data        = new float[dimTotal];
            volumeScaledData       = new float[dimTotal];

            for (int ix = 0; ix < nx; ix++)
            {
                for (int iy = 0; iy < ny; iy++)
                {
                    for (int iz = 0; iz < nz; iz++)
                    {
                        int itr = (iz * nx * ny) + (iy * nx) + ix;
                        volumeScaledData[itr] = (float)dataGrid[itr] * (float)dataFiller.volumeScale * (float)0.036749309; //density * volumescale * e_units
                    }
                }
            }
            for (int i = 0; i < dimTotal; i++)
            {
                dataFiller.data[i] = dataGrid[i];
            }

            Debug.Log("Loaded dataset in range: " + dataFiller.GetMinDataValue() + "  -  " + dataFiller.GetMaxDataValue());

            return(dataFiller);
        }
        public override VolumeDataset Import()
        {
            VolumeDataset dataset = new VolumeDataset();

            dataset.dimX = dimX;
            dataset.dimY = dimY;
            dataset.dimZ = dimZ;

            FileStream   fs     = new FileStream(filePath, FileMode.Open);
            BinaryReader reader = new BinaryReader(fs);

            if (skipBytes > 0)
            {
                reader.ReadBytes(skipBytes);
            }

            int uDimension = dimX * dimY * dimZ;

            dataset.data = new int[uDimension];

            int val = 0;

            for (int i = 0; i < uDimension; i++)
            {
                switch (contentFormat)
                {
                case DataContentFormat.Int8:
                    val = (int)reader.ReadSByte();
                    break;

                case DataContentFormat.Int16:
                    val = (int)reader.ReadInt16();
                    break;

                case DataContentFormat.Int32:
                    val = (int)reader.ReadInt32();
                    break;

                case DataContentFormat.Uint8:
                    val = (int)reader.ReadByte();
                    break;

                case DataContentFormat.Uint16:
                    val = (int)reader.ReadUInt16();
                    break;

                case DataContentFormat.Uint32:
                    val = (int)reader.ReadUInt32();
                    break;
                }
                dataset.data[i] = val;
            }
            Debug.Log("Loaded dataset in range: " + dataset.GetMinDataValue() + "  -  " + dataset.GetMaxDataValue());

            return(dataset);
        }