/*
* Copyright (c) 2005–2012 Goethe Center for Scientific Computing - Simulation and Modelling (G-CSC Frankfurt)
* Copyright (c) 2012-2015 Goethe Center for Scientific Computing - Computational Neuroscience (G-CSC Frankfurt)
*
* This file is part of NeuGen.
*
* NeuGen is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* as published by the Free Software Foundation.
*
* see: http://opensource.org/licenses/LGPL-3.0
* file://path/to/NeuGen/LICENSE
*
* NeuGen is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* This version of NeuGen includes copyright notice and attribution requirements.
* According to the LGPL this information must be displayed even if you modify
* the source code of NeuGen. The copyright statement/attribution may not be removed.
*
* Attribution Requirements:
*
* If you create derived work you must do the following regarding copyright
* notice and author attribution.
*
* Add an additional notice, stating that you modified NeuGen. In addition
* you must cite the publications listed below. A suitable notice might read
* "NeuGen source code modified by YourName 2012".
*
* Note, that these requirements are in full accordance with the LGPL v3
* (see 7. Additional Terms, b).
*
* Publications:
*
* S. Wolf, S. Grein, G. Queisser. NeuGen 2.0 -
* Employing NeuGen 2.0 to automatically generate realistic
* morphologies of hippocapal neurons and neural networks in 3D.
* Neuroinformatics, 2013, 11(2), pp. 137-148, doi: 10.1007/s12021-012-9170-1
*
*
* J. P. Eberhard, A. Wanner, G. Wittum. NeuGen -
* A tool for the generation of realistic morphology
* of cortical neurons and neural networks in 3D.
* Neurocomputing, 70(1-3), pp. 327-343, doi: 10.1016/j.neucom.2006.01.028
*
*/
package org.neugen.datastructures;
import org.neugen.datastructures.neuron.Neuron;
import java.util.ArrayList;
import java.util.List;
import javax.vecmath.Point3f;
import javax.vecmath.Point3i;
import org.apache.log4j.Logger;
import org.neugen.gui.DensityDialog;
/**
* Class VoxelVolume
*
* @author Jens P Eberhard
* @author Simone Eberhard
*/
public final class VoxelVolume {
/** use to log messages */
private final static Logger logger = Logger.getLogger(VoxelVolume.class.getName());
/** the net */
private Net net;
/** part of density : [dendritic, axonal, synaptic] */
private DensityDialog.DensityPart densityPart;
/** method of density : [length, volume, number] */
private DensityDialog.DensityMethod densityMethod;
/** x-, y- and z-length of one voxel */
private Point3i voxelSize;
/** number of voxels in the VoxelVolume / voxelArray */
private Point3i voxelNumber;
/** contains all Voxels of the VoxelVolume */
private List<Voxel> voxelArray;
public VoxelVolume(ArrayList<int[][]> matrixList, Point3i voxelSize, int intensity, int weight) {
int width = 0, height = 0;
if(matrixList.size() > 0) {
width = matrixList.get(0).length;
height = matrixList.get(0)[0].length;
}
int layerSize = matrixList.size();
this.densityPart = DensityDialog.DensityPart.IMAGE;
this.densityMethod = DensityDialog.DensityMethod.NUMBER;
// size of voxels
this.voxelSize = new Point3i(voxelSize.x, voxelSize.z, voxelSize.y);
//voxelSize = new Point3i(voxelLength, voxelLength, voxelLength); // size of voxels (x, y, z)
// number of voxels
voxelNumber = new Point3i(); // number of voxels (x, y, z) in VoxelVolume
/** The lower left corner of the region. */
Point3f lowLeftCorner = new Point3f(0.0f, 0.0f, 0.0f);
/** The upper right corner of the region. */
//Point3f e = new Point3f(par.getLength(), par.getWidth(), par.getHeight());
Point3f upRightCorner = new Point3f(width, layerSize, height);
Region region3D = new Region(lowLeftCorner, upRightCorner);
Region.setInstance(region3D);
voxelNumber = computeVoxelNumber();
int totalVoxelNumber = voxelNumber.x * voxelNumber.y * voxelNumber.z; // total number of Voxels in VoxelVolume
logger.info("totalVoxelNumber: " + totalVoxelNumber);
// fill voxelArray with empty Voxels
voxelArray = new ArrayList<Voxel>();
for (int i = 0; i < totalVoxelNumber; i++) {
Voxel voxel = new Voxel(densityPart, densityMethod);
voxelArray.add(i, voxel);
}
logger.info("Nucleus part and number method.");
// fill all voxels with number
int c =0;
for(int[][] matrix : matrixList) {
fillVoxelVolumeWithNumPixel(matrix, c, intensity, weight);
// c+=10;
c++;
}
// compute the percentage of value in each Voxel and overwrite it
computeNumberPercentageOfVoxelContent();
}
/** Constructor */
public VoxelVolume(Net net, int voxelLength, DensityDialog.DensityPart densityPart, DensityDialog.DensityMethod densityMethod) {
this.net = net; // the net
this.densityPart = densityPart;
this.densityMethod = densityMethod;
// size of voxels
voxelSize = new Point3i(voxelLength, voxelLength, voxelLength); // size of voxels (x, y, z)
// number of voxels
voxelNumber = new Point3i(); // number of voxels (x, y, z) in VoxelVolume
voxelNumber = computeVoxelNumber();
int totalVoxelNumber = voxelNumber.x * voxelNumber.y * voxelNumber.z; // total number of Voxels in VoxelVolume
//logger.info("totalVoxelNumber: " + totalVoxelNumber);
// fill voxelArray with empty Voxels
voxelArray = new ArrayList<Voxel>();
for (int i = 0; i < totalVoxelNumber; i++) {
Voxel voxel = new Voxel(densityPart, densityMethod);
voxelArray.add(i, voxel);
}
logger.info("voxelArray.size: " + voxelArray.size());
// fill the Voxels in the VoxelVolume / voxelArray with value
if ((densityPart.equals(DensityDialog.DensityPart.DENDRITIC)
|| densityPart.equals(DensityDialog.DensityPart.AXONAL))
&& densityMethod.equals(DensityDialog.DensityMethod.LENGTH)) {
logger.info("Axonal or dendritic part and lenght method.");
// fill all voxels with length
fillVoxelVolumeWithLen();
// compute the percentage of value in each Voxel and overwrite it
computeLengthPercentageOfVoxelContent();
} else if ((densityPart.equals(DensityDialog.DensityPart.DENDRITIC)
|| densityPart.equals(DensityDialog.DensityPart.AXONAL)) && densityMethod.equals(DensityDialog.DensityMethod.VOLUME)) {
logger.info("Axonal or dendritic part and volume method.");
// fill all voxels with volume
fillVoxelVolumeWithVol();
// compute the percentage of value in each Voxel and overwrite it
computeVolumePercentageOfVoxelContent();
} else if (densityPart.equals(DensityDialog.DensityPart.SYNAPTIC) && densityMethod.equals(DensityDialog.DensityMethod.NUMBER)) {
logger.info("Synaptic part and number method.");
// fill all voxels with number
fillVoxelVolumeWithNum();
// compute the percentage of value in each Voxel and overwrite it
computeNumberPercentageOfVoxelContent();
}
}
/** computes number of voxels [x, y, z] */
private Point3i computeVoxelNumber() {
Point3i voxelNum = new Point3i();
Point3f upRightCorner = Region.getInstance().getUpRightCorner();
logger.info("upRightCorner: " + upRightCorner.toString());
float xNumber = (upRightCorner.x) / voxelSize.x; // number of voxels in x direction
float yNumber = (upRightCorner.y) / voxelSize.y; // number of voxels in y direction
float zNumber = (upRightCorner.z) / voxelSize.z; // number of voxels in z direction
voxelNum.x = (int) xNumber;
voxelNum.y = (int) yNumber;
voxelNum.z = (int) zNumber;
return voxelNum;
}
/**
* returns the voxelArray
*
* @return the voxel arraylist
*/
public List<Voxel> getVoxelArray() {
return voxelArray;
}
/**
* returns part of density
*
* @return the density part
*/
public DensityDialog.DensityPart getDensityPart() {
return densityPart;
}
/**
* returns method of density
*
* @return the density method
*/
public DensityDialog.DensityMethod getDensityMethod() {
return densityMethod;
}
/** returns x-, y- and z-length of one Voxel */
public Point3i getVoxelSize() {
return voxelSize;
}
/** returns number of voxels in the VoxelVolume */
public Point3i getVoxelNumber() {
return voxelNumber;
}
/**
* computes the index of the voxel in which a given coordinate lays
*
* @return the index of the voxel
*/
public int getVoxelIndex(Point3f coordinates) {
int index;
int xRow, yColumn, zSlice;
Point3i coordinatesInVoxelVolume = new Point3i();
coordinatesInVoxelVolume.x = (int) Math.floor(coordinates.x / voxelSize.x);
coordinatesInVoxelVolume.y = (int) Math.floor(coordinates.y / voxelSize.y);
coordinatesInVoxelVolume.z = (int) Math.floor(coordinates.z / voxelSize.z);
// coordinates can extend outside column
if (coordinatesInVoxelVolume.x >= voxelNumber.x) {
return -1;
}
if (coordinatesInVoxelVolume.y >= voxelNumber.y) {
return -2;
}
if (coordinatesInVoxelVolume.z >= voxelNumber.z) {
return -3;
}
xRow = coordinatesInVoxelVolume.x;
yColumn = coordinatesInVoxelVolume.y * voxelNumber.x;
zSlice = coordinatesInVoxelVolume.z * voxelNumber.y * voxelNumber.x;
index = xRow + yColumn + zSlice;
if (index < -1) {
return -1;
}
return index;
}
/** fills the Voxels of the VoxelVolume with the dendritic or axonal length contained in this voxel */
public void fillVoxelVolumeWithLen() {
float lengthOfSegment;
int index;
if (densityPart.equals(DensityDialog.DensityPart.DENDRITIC)) {
for (Neuron neuron : net.getNeuronList()) {
for (Dendrite currentDen : neuron.getDendrites()) {
if (currentDen.getFirstSection() == null) {
return;
}
Section.Iterator secit = currentDen.getFirstSection().getIterator();
while (secit.hasNext()) {
Section sec = secit.next();
for (Segment segment : sec.getSegments()) {
lengthOfSegment = segment.getLength();
//test in which voxel center lays (getVoxelIndex)
//add length to this voxel
index = this.getVoxelIndex(segment.getCenter());
if (index != -1 && index != -2 && index != -3) {
try {
Voxel voxel = this.voxelArray.get(index);
voxel.addLengthContent(lengthOfSegment);
} catch (ArrayIndexOutOfBoundsException ex) {
if (logger.isDebugEnabled()) {
logger.error(ex);
}
}
}
}
}
}
}
} else if ((densityPart.equals(DensityDialog.DensityPart.AXONAL))) {
for (Neuron neuron : net.getNeuronList()) {
Axon axon = neuron.getAxon();
if (axon.getFirstSection() == null) {
return;
}
Section.Iterator secit = axon.getFirstSection().getIterator();
while (secit.hasNext()) {
Section sec = secit.next();
for (Segment segment : sec.getSegments()) {
lengthOfSegment = segment.getLength();
//test in which voxel center lays (getVoxelIndex)
//add length to this voxel
index = this.getVoxelIndex(segment.getCenter());
if (index != -1 && index != -2 && index != -3) {
try {
Voxel voxel = this.voxelArray.get(index);
voxel.addLengthContent(lengthOfSegment);
} catch (ArrayIndexOutOfBoundsException ex) {
if (logger.isDebugEnabled()) {
logger.error(ex);
}
}
}
}
}
}
} else if ((densityPart.equals(DensityDialog.DensityPart.SYNAPTIC))) {
logger.info("NOT YET IMPLEMENTED: SYNAPTIC");
} else {
logger.info("NOT YET IMPLEMENTED: " + densityPart);
}
}
/** fills the Voxels of the VoxelVolume with the dendritic volume contained in this voxel */
public void fillVoxelVolumeWithVol() {
int index;
if (densityPart.equals(DensityDialog.DensityPart.DENDRITIC)) {
for (Neuron neuron : net.getNeuronList()) {
for (Dendrite currentDen : neuron.getDendrites()) {
if (currentDen.getFirstSection() == null) {
return;
}
Section.Iterator secit = currentDen.getFirstSection().getIterator();
while (secit.hasNext()) {
Section sec = secit.next();
for (Segment segment : sec.getSegments()) {
float volumeOfSegment = segment.getVolume();
//test in which voxel center lays (getVoxelIndex)
//add volume to this voxel
index = this.getVoxelIndex(segment.getCenter());
if (index != -1 && index != -2 && index != -3) {
try {
Voxel voxel = voxelArray.get(index);
voxel.addVolumeContent(volumeOfSegment);
} catch (ArrayIndexOutOfBoundsException ex) {
if (logger.isDebugEnabled()) {
logger.error(ex);
}
}
}
}
}
}
}
} else if (densityPart.equals(DensityDialog.DensityPart.AXONAL)) {
for (Neuron neuron : net.getNeuronList()) {
Axon axon = neuron.getAxon();
if (axon.getFirstSection() == null) {
return;
}
Section.Iterator secit = axon.getFirstSection().getIterator();
while (secit.hasNext()) {
Section sec = secit.next();
for (Segment segment : sec.getSegments()) {
float volumeOfSegment = segment.getVolume();
//test in which voxel center lays (getVoxelIndex)
//add volume to this voxel
index = getVoxelIndex(segment.getCenter());
if (index != -1 && index != -2 && index != -3) {
try {
Voxel voxel = voxelArray.get(index);
voxel.addVolumeContent(volumeOfSegment);
} catch (ArrayIndexOutOfBoundsException ex) {
if (logger.isDebugEnabled()) {
logger.error(ex);
}
}
}
}
}
}
} else {
logger.info("NOT YET IMPLEMENTED");
}
}
/** fills the Voxels of the VoxelVolume with the synaptic numbers contained in this voxel */
public void fillVoxelVolumeWithNum() {
if (densityPart.equals(DensityDialog.DensityPart.SYNAPTIC)) {
logger.info("fill voxels with synapses");
for (Cons synapse : net.getSynapseList()) {
if (synapse.getNeuron1() == null) {
continue;
}
Segment axSeg = synapse.getNeuron1AxSegment();
Segment denSeg = synapse.getNeuron2DenSectionSegment();
Point3f axSegEnd = axSeg.getEnd();
Point3f denSegEnd = denSeg.getEnd();
Point3f center = new Point3f();
center.add(axSegEnd, denSegEnd);
center.scale(0.5f);
int index = getVoxelIndex(center);
if (index != -1 && index != -2 && index != -3) {
try {
Voxel voxel = voxelArray.get(index);
voxel.addNumberContent(1);
} catch (ArrayIndexOutOfBoundsException ex) {
if (logger.isDebugEnabled()) {
logger.error(ex);
}
}
}
}
}
}
/** fills the Voxels of the VoxelVolume with the pixel numbers contained in this voxel */
public void fillVoxelVolumeWithNumPixel(int[][] matrix, int layer, int grayVal, int weight) {
//logger.info("fill voxels with pixel");
int width = matrix.length;
int height = matrix[0].length;
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
int curVal = matrix[i][j];
if (curVal > grayVal) {
//System.out.println(matrix[i][j] + " ");
Point3f center = new Point3f(i, layer, j);
int index = getVoxelIndex(center);
if (index != -1 && index != -2 && index != -3) {
try {
Voxel voxel = voxelArray.get(index);
voxel.addNumberContent((float) Math.pow(curVal, weight));
//voxel.addNumberContent(1);
} catch (ArrayIndexOutOfBoundsException ex) {
if (logger.isDebugEnabled()) {
logger.error(ex);
}
}
}
}
}
}
}
/** computes the length percentage of the content of the voxel */
public void computeLengthPercentageOfVoxelContent() {
float totalContent = 0.0f;
float onePercent;
float voxelContent;
float voxelPercentContent;
for (Voxel voxel : voxelArray) {
totalContent += voxel.getLengthContent();
}
for (Voxel voxel : voxelArray) {
voxelContent = voxel.getLengthContent();
onePercent = totalContent / 100.0f;
voxelPercentContent = voxelContent / onePercent;
voxel.setLengthPercentContent(voxelPercentContent);
}
}
/** computes the volume percentage of the content of the voxel */
public void computeVolumePercentageOfVoxelContent() {
float totalContent = 0.0f;
float onePercent;
float voxelContent;
float voxelPercentContent;
for (Voxel voxel : voxelArray) {
totalContent += voxel.getVolumeContent();
}
for (Voxel voxel : voxelArray) {
voxelContent = voxel.getVolumeContent();
onePercent = totalContent / 100.0f;
voxelPercentContent = voxelContent / onePercent;
voxel.setVolumePercentContent(voxelPercentContent);
}
}
/** computes the number percentage of the content of the voxel */
public void computeNumberPercentageOfVoxelContent() {
float totalContent = 0.0f;
float onePercent;
float voxelContent;
float voxelPercentContent;
for (Voxel voxel : voxelArray) {
totalContent += voxel.getNumberContent();
}
for (Voxel voxel : voxelArray) {
voxelContent = voxel.getNumberContent();
onePercent = totalContent / 100.0f;
voxelPercentContent = voxelContent / onePercent;
voxel.setNumberPercentContent(voxelPercentContent);
}
}
}