Commit d531d201 authored by Andrey Filippov's avatar Andrey Filippov

merged with nc393 branch

parents 01246a62 b759e500
...@@ -2514,8 +2514,8 @@ if (PROCESS_PARAMETERS.saveSettings) saveProperties(FILE_PARAMETERS.resultsDirec ...@@ -2514,8 +2514,8 @@ if (PROCESS_PARAMETERS.saveSettings) saveProperties(FILE_PARAMETERS.resultsDirec
tileY = nTile /tilesX; tileY = nTile /tilesX;
tileX = nTile % tilesX; tileX = nTile % tilesX;
if (tileX==0) { if (tileX==0) {
if (updateStatus) IJ.showStatus("Reducing sampling aliases, row "+(tileY+1)+" of "+tilesY); if (updateStatus) IJ.showStatus("(3)Reducing sampling aliases, row "+(tileY+1)+" of "+tilesY);
if (MASTER_DEBUG_LEVEL>2) System.out.println("Reducing sampling aliases, row "+(tileY+1)+" of "+tilesY+" : "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)); if (MASTER_DEBUG_LEVEL>2) System.out.println("(3)Reducing sampling aliases, row "+(tileY+1)+" of "+tilesY+" : "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
} }
if ((tileY==yTileDebug) && (tileX==xTileDebug)) DEBUG_LEVEL=4; if ((tileY==yTileDebug) && (tileX==xTileDebug)) DEBUG_LEVEL=4;
......
...@@ -45,6 +45,7 @@ import java.net.MalformedURLException; ...@@ -45,6 +45,7 @@ import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
...@@ -76,6 +77,7 @@ public class CalibrationHardwareInterface { ...@@ -76,6 +77,7 @@ public class CalibrationHardwareInterface {
// JP46_Reader_camera JP4_INSTANCE= new JP46_Reader_camera(false); // JP46_Reader_camera JP4_INSTANCE= new JP46_Reader_camera(false);
public LaserPointers laserPointers=null; public LaserPointers laserPointers=null;
private int masterSubCamera=0; // "master" camera index of IP in the list private int masterSubCamera=0; // "master" camera index of IP in the list
private int masterPort= 0; // "master" camera port (0..3) to apply trigger to
private JP46_Reader_camera [] jp4_Instances=null; private JP46_Reader_camera [] jp4_Instances=null;
private String [] resetURLs=null; private String [] resetURLs=null;
private String [] imageURLs=null; private String [] imageURLs=null;
...@@ -87,7 +89,8 @@ public class CalibrationHardwareInterface { ...@@ -87,7 +89,8 @@ public class CalibrationHardwareInterface {
// TODO: when saving/restoring save cameraSubnet, iBaseIP, cameraIPs, so any IPs are OK through config, generate - sequential // TODO: when saving/restoring save cameraSubnet, iBaseIP, cameraIPs, so any IPs are OK through config, generate - sequential
private String cameraSubnet="192.168.0."; private String cameraSubnet="192.168.0.";
private int iBaseIP=236; private int iBaseIP=236;
private String [] cameraIPs = null; private String [] cameraIPs = null; // since nc393 port is a part of cameraIPs[]
private int [] channelIPPort = null; // index in camareIPs (each IP/port combination) for each individual sensor
private int imgsrvPort=8081; private int imgsrvPort=8081;
private String resetURLcmd="towp/save/pointers"; // advance buffer, next time will wait for the next frame acquired private String resetURLcmd="towp/save/pointers"; // advance buffer, next time will wait for the next frame acquired
// will return XML, just "trig" - 1x1 GIF // will return XML, just "trig" - 1x1 GIF
...@@ -99,6 +102,7 @@ public class CalibrationHardwareInterface { ...@@ -99,6 +102,7 @@ public class CalibrationHardwareInterface {
private double lastTemperature=Double.NaN; private double lastTemperature=Double.NaN;
private int colorMode=5; // JP4 private int colorMode=5; // JP4
private boolean noWait= true; // when false, IRQ_SMART=3 and the frame is available only 1 frame later, when true IRQ_SMART=6, frame is available after compression end private boolean noWait= true; // when false, IRQ_SMART=3 and the frame is available only 1 frame later, when true IRQ_SMART=6, frame is available after compression end
private boolean nc393 = false;
private int debugSensorNumber=-1; // increase debug level for this particular sensor private int debugSensorNumber=-1; // increase debug level for this particular sensor
private int JPEGquality=99; // JPEG quality private int JPEGquality=99; // JPEG quality
private boolean cameraAutoExposure = false; private boolean cameraAutoExposure = false;
...@@ -115,7 +119,7 @@ public class CalibrationHardwareInterface { ...@@ -115,7 +119,7 @@ public class CalibrationHardwareInterface {
private double cameraRScale =1.25; private double cameraRScale =1.25;
private double cameraBScale =1.5; private double cameraBScale =1.5;
private double cameraGScale =1.0; private double cameraGScale =1.0;
private double [] cameraExposureCorr=null; // per-camera exposure correction private double [] cameraExposureCorr=null; // per-camera exposure correction1
private double [] cameraGainCorr = null; // per-camera gain correction; private double [] cameraGainCorr = null; // per-camera gain correction;
private double [] cameraRScaleCorr = null; // per-camera R/G scale correction; private double [] cameraRScaleCorr = null; // per-camera R/G scale correction;
private double [] cameraBScaleCorr = null; // per-camera B/G scale correction; private double [] cameraBScaleCorr = null; // per-camera B/G scale correction;
...@@ -124,9 +128,10 @@ public class CalibrationHardwareInterface { ...@@ -124,9 +128,10 @@ public class CalibrationHardwareInterface {
// these are initialized after being null, when the cameras are probed // these are initialized after being null, when the cameras are probed
private int [] cameraFrameNumber=null; private int [] cameraFrameNumber=null;
private boolean [] triggeredMode= null; // true - triggered, false - free running private boolean [] triggeredMode= null; // true - triggered, false - free running
private boolean [][] sensorPresent= null; // probe which sensors (of 3) are detected per system board private boolean [][] sensorPresent= null; // probe which sensors (of 3) are detected per system board (NC393 - per board/port)
// TODO - try if skipping setting TRIG_PERIOD=0, IRQ_SMART=6 (when they are already set) will fix hanging // TODO - try if skipping setting TRIG_PERIOD=0, IRQ_SMART=6 (when they are already set) will fix hanging
private int [] triggerPeriod= null; private int [] triggerPeriod= null;
private int [] cameraMasterPort= null;
private int [] irqSmart= null; private int [] irqSmart= null;
private int [] motorsPosition= null; // motors steps when the images were acquired (for null) private int [] motorsPosition= null; // motors steps when the images were acquired (for null)
private long startTime=System.nanoTime(); private long startTime=System.nanoTime();
...@@ -150,22 +155,29 @@ public class CalibrationHardwareInterface { ...@@ -150,22 +155,29 @@ public class CalibrationHardwareInterface {
this.thisTime=this.startTime; this.thisTime=this.startTime;
} }
private int [][] channelMap_23_393={ // ip index, channel number, port
{0,0,3},{0,0,2},{0,0,0},{0,0,1},{1,0,3},{1,0,2},{1,0,0},{1,0,1},
{0,1,3},{0,1,2},{0,1,0},{0,1,1},{1,1,3},{1,1,2},{1,1,0},{1,1,1},
{0,2,3},{0,2,2},{0,2,0},{0,2,1},{1,2,3},{1,2,2},{1,2,0},{1,2,1},
{2,0,2},{2,0,3}};
private int [][] channelMap21={ // ip index, channel number private int [][] channelMap21={ // ip index, channel number
{0,1},{0,0},{0,2}, {0,1,0},{0,0,0},{0,2,0},
{1,1},{1,0},{1,2}, {1,1,0},{1,0,0},{1,2,0},
{2,1},{2,0},{2,2}, {2,1,0},{2,0,0},{2,2,0},
{3,1},{3,0},{3,2}, {3,1,0},{3,0,0},{3,2,0},
{4,1},{4,0},{4,2}, {4,1,0},{4,0,0},{4,2,0},
{5,1},{5,0},{5,2}, {5,1,0},{5,0,0},{5,2,0},
{6,1},{6,0},{6,2}}; {6,1,0},{6,0,0},{6,2,0}};
private int [][] channelMap1={ // ip index, channel number private int [][] channelMap1={ // ip index, channel number
// {0,-1}}; // negative channel - single camera // {0,-1}}; // negative channel - single camera
{0,0}}; // Try with 0 {0,0,0}}; // Try with 0
private int [][] channelMap2={ // ip index, channel number private int [][] channelMap2={ // ip index, channel number
{0,0},{0,1}}; {0,0,0},{0,1,0}};
private int [][] channelMap3={ // ip index, channel number private int [][] channelMap3={ // ip index, channel number
// {0,-1}}; // negative channel - single camera // {0,-1}}; // negative channel - single camera
{0,0},{1,0},{2,0}}; {0,0,0},{1,0,0},{2,0,0}};
private int [][] channelMap=null; private int [][] channelMap=null;
public int maxNumberOfThreads=100; public int maxNumberOfThreads=100;
/** /**
...@@ -194,32 +206,50 @@ public class CalibrationHardwareInterface { ...@@ -194,32 +206,50 @@ public class CalibrationHardwareInterface {
public int getSubChannel (int channelNumber){ public int getSubChannel (int channelNumber){
return ((channelNumber>=0)&& (channelNumber<this.channelMap.length))?this.channelMap[channelNumber][1]:-1; return ((channelNumber>=0)&& (channelNumber<this.channelMap.length))?this.channelMap[channelNumber][1]:-1;
} }
public int getSensorPort (int channelNumber){
return ((channelNumber>=0)&& (channelNumber<this.channelMap.length))?this.channelMap[channelNumber][2]:-1;
}
// not used anywhere
public int getChannel (int subCam, int subChn){ public int getChannel (int subCam, int subChn){
return getChannel (subCam, subChn, 0); // for compatibility with 353
}
public int getChannel (int subCam, int subChn, int port){
for (int channelNumber=0;channelNumber<this.channelMap.length;channelNumber++) for (int channelNumber=0;channelNumber<this.channelMap.length;channelNumber++)
if ((this.channelMap[channelNumber][0]==subCam) && (this.channelMap[channelNumber][1]==subChn)) return channelNumber; if ((this.channelMap[channelNumber][0]==subCam) &&
(this.channelMap[channelNumber][1]==subChn) &&
(this.channelMap[channelNumber][2]==port)) return channelNumber;
return -1; return -1;
} }
private void initJP4(){ private void initJP4(){
this.jp4_Instances=new JP46_Reader_camera[this.cameraIPs.length]; this.jp4_Instances=new JP46_Reader_camera[this.cameraIPs.length];
this.resetURLs=new String [this.cameraIPs.length]; this.resetURLs=new String [this.cameraIPs.length];
this.imageURLs=new String [this.cameraIPs.length]; this.imageURLs=new String [this.cameraIPs.length];
this.metaURLs= new String [this.cameraIPs.length]; this.metaURLs= new String [this.cameraIPs.length];
this.triggerURL="http://"+this.cameraIPs[this.masterSubCamera]+":"+this.imgsrvPort+"/"+triggerURLcmd; // this.triggerURL is already defined
// this.triggerURL="http://"+this.cameraIPs[this.masterSubCamera]+":"+(this.imgsrvPort+this.masterPort)+"/"+triggerURLcmd;
this.images= new ImagePlus[this.channelMap.length]; this.images= new ImagePlus[this.channelMap.length];
this.imagesIP= new ImagePlus[this.cameraIPs.length]; this.imagesIP= new ImagePlus[this.cameraIPs.length];
for (int i=0; i<this.cameraIPs.length;i++){ for (int i=0; i<this.cameraIPs.length;i++){
this.jp4_Instances[i]=new JP46_Reader_camera(false);// invisible this.jp4_Instances[i]=new JP46_Reader_camera(false);// invisible
this.jp4_Instances[i].camera_url="http://"+this.cameraIPs[i]+":"+this.imgsrvPort+"/"; // this.jp4_Instances[i].camera_url="http://"+this.cameraIPs[i]+":"+this.imgsrvPort+"/";
this.jp4_Instances[i].camera_url="http://"+this.cameraIPs[i]+"/";
this.jp4_Instances[i].camera_img= this.imageURLcmd; // not currently used this.jp4_Instances[i].camera_img= this.imageURLcmd; // not currently used
this.jp4_Instances[i].camera_img_new=this.imageURLcmd; //"torp/wait/" will survive, only "towp/wait/" is removed for Exif re-read this.jp4_Instances[i].camera_img_new=this.imageURLcmd; //"torp/wait/" will survive, only "towp/wait/" is removed for Exif re-read
this.jp4_Instances[i].ABSOLUTELY_SILENT=true; this.jp4_Instances[i].ABSOLUTELY_SILENT=true;
this.resetURLs[i]="http://"+this.cameraIPs[i]+":"+this.imgsrvPort+"/"+resetURLcmd; // this.resetURLs[i]="http://"+this.cameraIPs[i]+":"+this.imgsrvPort+"/"+resetURLcmd;
this.imageURLs[i]="http://"+this.cameraIPs[i]+":"+this.imgsrvPort+"/"+this.imageURLcmd; // this.imageURLs[i]="http://"+this.cameraIPs[i]+":"+this.imgsrvPort+"/"+this.imageURLcmd;
this.metaURLs[i]= "http://"+this.cameraIPs[i]+":"+this.imgsrvPort+"/"+metaURLcmd; // this.metaURLs[i]= "http://"+this.cameraIPs[i]+":"+this.imgsrvPort+"/"+metaURLcmd;
this.resetURLs[i]="http://"+this.cameraIPs[i]+"/"+resetURLcmd;
this.imageURLs[i]="http://"+this.cameraIPs[i]+"/"+this.imageURLcmd;
this.metaURLs[i]= "http://"+this.cameraIPs[i]+"/"+metaURLcmd;
this.imagesIP[i]= null; this.imagesIP[i]= null;
} }
for (int i=0; i<this.images.length;i++) this.images[i]= null; for (int i=0; i<this.images.length;i++) this.images[i]= null;
} }
...@@ -245,6 +275,32 @@ public class CalibrationHardwareInterface { ...@@ -245,6 +275,32 @@ public class CalibrationHardwareInterface {
/** /**
* Initialize cameraIPs from subNet and baseIP (sequentially) * Initialize cameraIPs from subNet and baseIP (sequentially)
*/ */
private void initIPs(){
ArrayList<Integer> ip_ports_list= new ArrayList<Integer>();
for (int i=0;i<this.channelMap.length;i++) {
Integer ip_port=(this.channelMap[i][0]<<2) + this.channelMap[i][2];
if (!ip_ports_list.contains(ip_port)) ip_ports_list.add(ip_port);
}
Collections.sort(ip_ports_list);
this.cameraIPs = new String [ip_ports_list.size()];
this.channelIPPort = new int [this.channelMap.length];
for (int i = 0; i<this.cameraIPs.length; i++){
int ip_index= ip_ports_list.get(i)>>2;
int sensor_port = ip_ports_list.get(i) & 3;
this.cameraIPs[i] = this.cameraSubnet+(this.iBaseIP + ip_index) + ":"+ (this.imgsrvPort+sensor_port);
for (int j = 0; j<this.channelMap.length; j++){
if ((this.channelMap[j][0] == ip_index) && (this.channelMap[j][2] == sensor_port)) {
this.channelIPPort[j] = i;
}
}
}
this.triggerURL="http://"+this.cameraSubnet+(this.iBaseIP+this.masterSubCamera)+":"+
(this.imgsrvPort+ (this.masterPort & 3))+"/"+triggerURLcmd;
if (this.debugLevel>1) System.out.println("DEBUG393: initIPs(): this.triggerURL ="+this.triggerURL);
}
/*
//pre nc393
private void initIPs(){ private void initIPs(){
if (this.debugLevel>2) System.out.println("initIPs(): this.iBaseIP=" + this.iBaseIP ); if (this.debugLevel>2) System.out.println("initIPs(): this.iBaseIP=" + this.iBaseIP );
int size=0; int size=0;
...@@ -252,41 +308,72 @@ public class CalibrationHardwareInterface { ...@@ -252,41 +308,72 @@ public class CalibrationHardwareInterface {
size++; size++;
this.cameraIPs=new String [size]; this.cameraIPs=new String [size];
for (int i=0;i<size;i++) this.cameraIPs[i]=this.cameraSubnet+(this.iBaseIP+i); for (int i=0;i<size;i++) this.cameraIPs[i]=this.cameraSubnet+(this.iBaseIP+i);
this.masterSubCamera=0; // this.masterSubCamera=0;
} }
*/
/** /**
* Initialize default subcamera map * Initialize default subcamera map
* @param size number of subcameras * @param size number of subcameras
*/ */
private void initDefaultMap(int size){ private void initDefaultMap(int size){
this.channelMap=new int [size][]; this.channelMap=new int [size][];
this.flipImages=new boolean[size]; this.flipImages=new boolean[size];
if (size==1) { // single camera - old lens focusing int []port_seq={1,0,2,3};
this.channelMap[0]=channelMap1[0].clone(); this.masterSubCamera=0;
this.flipImages[0]=true; this.masterPort=0;
} else if (size==2){ // New lens focusing machine if (this.nc393){
this.channelMap[0]=channelMap2[0].clone(); this.imgsrvPort=2323;
this.flipImages[0]=true; // main sensor under test this.resetURLcmd="towp/save/pointers"; // advance buffer, next time will wait for the next frame acquired
this.channelMap[1]=channelMap2[1].clone(); this.imageURLcmd="torp/wait/timestamp_name/bimg"; // will wait if needed. If repeated (as when reading Exif)- won't wait
this.flipImages[1]=false; // extra sensor for location this.metaURLcmd="torp/wait/meta"; // will get XML, including timestamp
if (size == 26) {
} else if (size==3){ for (int i=0;i<size;i++){
for (int i=0;i<size;i++){ this.channelMap[i]=channelMap_23_393[i].clone();
this.flipImages[i]=false; this.flipImages[i]=false;
int i0=((i>=this.channelMap3.length)?(this.channelMap3.length-1):i); }
this.channelMap[i]=this.channelMap21[i0].clone(); this.masterSubCamera = 2;
} this.masterPort=2;
} else for (int i=0;i<size;i++){ } else for (int i=0;i<size;i++){
this.flipImages[i]=false; this.flipImages[i]=false;
int i0=((i>=this.channelMap21.length)?(this.channelMap21.length-1):i); this.channelMap[i]=new int[3];
this.channelMap[i]=this.channelMap21[i0].clone(); this.channelMap[i][0]= i >> 2;
} this.channelMap[i][1]= 0;
if (size <4) {
this.channelMap[i][2]= i;
} else {
this.channelMap[i][2]= port_seq[i & 3];
}
}
} else {
if (size==1) { // single camera - old lens focusing
this.channelMap[0]=channelMap1[0].clone();
this.flipImages[0]=true;
} else if (size==2){ // New lens focusing machine
this.channelMap[0]=channelMap2[0].clone();
this.flipImages[0]=true; // main sensor under test
this.channelMap[1]=channelMap2[1].clone();
this.flipImages[1]=false; // extra sensor for location
} else if (size==3){
for (int i=0;i<size;i++){
this.flipImages[i]=false;
int i0=((i>=this.channelMap3.length)?(this.channelMap3.length-1):i);
// this.channelMap[i]=this.channelMap21[i0].clone();
this.channelMap[i]=this.channelMap3[i0].clone();
}
} else for (int i=0;i<size;i++){
this.flipImages[i]=false;
int i0=((i>=this.channelMap21.length)?(this.channelMap21.length-1):i);
this.channelMap[i]=this.channelMap21[i0].clone();
}
}
} }
public void setProperties(String prefix,Properties properties){
public void setProperties(String prefix,Properties properties){
properties.setProperty(prefix+"cameraSubnet",this.cameraSubnet); properties.setProperty(prefix+"cameraSubnet",this.cameraSubnet);
properties.setProperty(prefix+"iBaseIP",this.iBaseIP+""); properties.setProperty(prefix+"iBaseIP",this.iBaseIP+"");
properties.setProperty(prefix+"masterSubCamera",this.masterSubCamera+""); properties.setProperty(prefix+"masterSubCamera",this.masterSubCamera+"");
properties.setProperty(prefix+"masterPort",this.masterPort+"");
properties.setProperty(prefix+"cameraBootTimeSeconds",this.cameraBootTimeSeconds+""); properties.setProperty(prefix+"cameraBootTimeSeconds",this.cameraBootTimeSeconds+"");
properties.setProperty(prefix+"connectionTimeoutMilliseconds",this.connectionTimeoutMilliseconds+""); properties.setProperty(prefix+"connectionTimeoutMilliseconds",this.connectionTimeoutMilliseconds+"");
properties.setProperty(prefix+"imgsrvPort",this.imgsrvPort+""); properties.setProperty(prefix+"imgsrvPort",this.imgsrvPort+"");
...@@ -298,12 +385,14 @@ public class CalibrationHardwareInterface { ...@@ -298,12 +385,14 @@ public class CalibrationHardwareInterface {
for (int i=0;i<this.channelMap.length;i++) { for (int i=0;i<this.channelMap.length;i++) {
properties.setProperty(prefix+"channelMap_"+i+"_IPindex", this.channelMap[i][0]+""); properties.setProperty(prefix+"channelMap_"+i+"_IPindex", this.channelMap[i][0]+"");
properties.setProperty(prefix+"channelMap_"+i+"_subchannel",this.channelMap[i][1]+""); properties.setProperty(prefix+"channelMap_"+i+"_subchannel",this.channelMap[i][1]+"");
properties.setProperty(prefix+"channelMap_"+i+"_port", this.channelMap[i][2]+"");
properties.setProperty(prefix+"flipImages_"+i ,this.flipImages[i]?"1":"0"); properties.setProperty(prefix+"flipImages_"+i ,this.flipImages[i]?"1":"0");
} }
properties.setProperty(prefix+"cameraIPs.length",this.cameraIPs.length+""); properties.setProperty(prefix+"cameraIPs.length",this.cameraIPs.length+"");
properties.setProperty(prefix+"colorMode",this.colorMode+""); properties.setProperty(prefix+"colorMode",this.colorMode+"");
properties.setProperty(prefix+"noWait",this.noWait+""); properties.setProperty(prefix+"noWait",this.noWait+"");
properties.setProperty(prefix+"nc393",this.nc393+"");
properties.setProperty(prefix+"debugSensorNumber",this.debugSensorNumber+""); properties.setProperty(prefix+"debugSensorNumber",this.debugSensorNumber+"");
properties.setProperty(prefix+"JPEGquality",this.JPEGquality+""); properties.setProperty(prefix+"JPEGquality",this.JPEGquality+"");
properties.setProperty(prefix+"cameraAutoExposure",this.cameraAutoExposure+""); properties.setProperty(prefix+"cameraAutoExposure",this.cameraAutoExposure+"");
...@@ -332,28 +421,8 @@ public class CalibrationHardwareInterface { ...@@ -332,28 +421,8 @@ public class CalibrationHardwareInterface {
} }
} }
public void getProperties(String prefix,Properties properties){ public void getProperties(String prefix,Properties properties){
if (properties.getProperty(prefix+"cameraSubnet")!=null)
this.cameraSubnet=properties.getProperty(prefix+"cameraSubnet");
if (properties.getProperty(prefix+"iBaseIP")!=null)
this.iBaseIP=Integer.parseInt(properties.getProperty(prefix+"iBaseIP"));
if (properties.getProperty(prefix+"masterSubCamera")!=null)
this.masterSubCamera=Integer.parseInt(properties.getProperty(prefix+"masterSubCamera"));
if (properties.getProperty(prefix+"cameraBootTimeSeconds")!=null)
this.cameraBootTimeSeconds=Integer.parseInt(properties.getProperty(prefix+"cameraBootTimeSeconds"));
if (properties.getProperty(prefix+"connectionTimeoutMilliseconds")!=null)
this.connectionTimeoutMilliseconds=Integer.parseInt(properties.getProperty(prefix+"connectionTimeoutMilliseconds"));
if (properties.getProperty(prefix+"imgsrvPort")!=null)
this.imgsrvPort=Integer.parseInt(properties.getProperty(prefix+"imgsrvPort"));
if (properties.getProperty(prefix+"resetURLcmd")!=null)
this.resetURLcmd=properties.getProperty(prefix+"resetURLcmd");
if (properties.getProperty(prefix+"triggerURLcmd")!=null)
this.triggerURLcmd=properties.getProperty(prefix+"triggerURLcmd");
if (properties.getProperty(prefix+"imageURLcmd")!=null)
this.imageURLcmd=properties.getProperty(prefix+"imageURLcmd");
if (properties.getProperty(prefix+"metaURLcmd")!=null)
this.metaURLcmd=properties.getProperty(prefix+"metaURLcmd");
if (properties.getProperty(prefix+"channelMap.length")!=null) { if (properties.getProperty(prefix+"channelMap.length")!=null) {
// next initializes default values, so it should be before reading them from saved properties
initDefaultMap (Integer.parseInt(properties.getProperty(prefix+"channelMap.length"))); initDefaultMap (Integer.parseInt(properties.getProperty(prefix+"channelMap.length")));
this.flipImages=new boolean[this.channelMap.length]; this.flipImages=new boolean[this.channelMap.length];
for (int i=0;i<this.channelMap.length;i++) { for (int i=0;i<this.channelMap.length;i++) {
...@@ -361,12 +430,13 @@ public class CalibrationHardwareInterface { ...@@ -361,12 +430,13 @@ public class CalibrationHardwareInterface {
this.channelMap[i][0]=Integer.parseInt(properties.getProperty(prefix+"channelMap_"+i+"_IPindex")); this.channelMap[i][0]=Integer.parseInt(properties.getProperty(prefix+"channelMap_"+i+"_IPindex"));
if (properties.getProperty(prefix+"channelMap_"+i+"_subchannel")!=null) if (properties.getProperty(prefix+"channelMap_"+i+"_subchannel")!=null)
this.channelMap[i][1]=Integer.parseInt(properties.getProperty(prefix+"channelMap_"+i+"_subchannel")); this.channelMap[i][1]=Integer.parseInt(properties.getProperty(prefix+"channelMap_"+i+"_subchannel"));
if (properties.getProperty(prefix+"channelMap_"+i+"_port")!=null)
this.channelMap[i][2]=Integer.parseInt(properties.getProperty(prefix+"channelMap_"+i+"_port"));
if (properties.getProperty(prefix+"flipImages_"+i)!=null) if (properties.getProperty(prefix+"flipImages_"+i)!=null)
this.flipImages[i]=(Integer.parseInt(properties.getProperty(prefix+"flipImages_"+i))>0); this.flipImages[i]=(Integer.parseInt(properties.getProperty(prefix+"flipImages_"+i))>0);
} }
} }
int numCams=0; int numCams=0;
if (properties.getProperty(prefix+"cameraIPs.length")!=null) { if (properties.getProperty(prefix+"cameraIPs.length")!=null) {
numCams=Integer.parseInt(properties.getProperty(prefix+"cameraIPs.length")); numCams=Integer.parseInt(properties.getProperty(prefix+"cameraIPs.length"));
...@@ -378,6 +448,35 @@ public class CalibrationHardwareInterface { ...@@ -378,6 +448,35 @@ public class CalibrationHardwareInterface {
} }
} }
initCamParsDefaultArrays(numCams); initCamParsDefaultArrays(numCams);
if (properties.getProperty(prefix+"cameraSubnet")!=null)
this.cameraSubnet=properties.getProperty(prefix+"cameraSubnet");
if (properties.getProperty(prefix+"iBaseIP")!=null)
this.iBaseIP=Integer.parseInt(properties.getProperty(prefix+"iBaseIP"));
if (properties.getProperty(prefix+"masterSubCamera")!=null)
this.masterSubCamera=Integer.parseInt(properties.getProperty(prefix+"masterSubCamera"));
if (properties.getProperty(prefix+"masterPort")!=null)
this.masterPort=Integer.parseInt(properties.getProperty(prefix+"masterPort"));
if (properties.getProperty(prefix+"cameraBootTimeSeconds")!=null)
this.cameraBootTimeSeconds=Integer.parseInt(properties.getProperty(prefix+"cameraBootTimeSeconds"));
if (properties.getProperty(prefix+"connectionTimeoutMilliseconds")!=null)
this.connectionTimeoutMilliseconds=Integer.parseInt(properties.getProperty(prefix+"connectionTimeoutMilliseconds"));
if (properties.getProperty(prefix+"imgsrvPort")!=null)
this.imgsrvPort=Integer.parseInt(properties.getProperty(prefix+"imgsrvPort"));
if (properties.getProperty(prefix+"resetURLcmd")!=null)
this.resetURLcmd=properties.getProperty(prefix+"resetURLcmd");
if (properties.getProperty(prefix+"triggerURLcmd")!=null)
this.triggerURLcmd=properties.getProperty(prefix+"triggerURLcmd");
if (properties.getProperty(prefix+"imageURLcmd")!=null)
this.imageURLcmd=properties.getProperty(prefix+"imageURLcmd");
if (properties.getProperty(prefix+"metaURLcmd")!=null)
this.metaURLcmd=properties.getProperty(prefix+"metaURLcmd");
// both defaults were here
if (properties.getProperty(prefix+"colorMode")!=null) if (properties.getProperty(prefix+"colorMode")!=null)
this.colorMode=Integer.parseInt(properties.getProperty(prefix+"colorMode")); this.colorMode=Integer.parseInt(properties.getProperty(prefix+"colorMode"));
...@@ -387,6 +486,8 @@ public class CalibrationHardwareInterface { ...@@ -387,6 +486,8 @@ public class CalibrationHardwareInterface {
this.JPEGquality=Integer.parseInt(properties.getProperty(prefix+"JPEGquality")); this.JPEGquality=Integer.parseInt(properties.getProperty(prefix+"JPEGquality"));
if (properties.getProperty(prefix+"noWait")!=null) if (properties.getProperty(prefix+"noWait")!=null)
this.noWait=Boolean.parseBoolean(properties.getProperty(prefix+"noWait")); this.noWait=Boolean.parseBoolean(properties.getProperty(prefix+"noWait"));
if (properties.getProperty(prefix+"nc393")!=null)
this.nc393=Boolean.parseBoolean(properties.getProperty(prefix+"nc393"));
if (properties.getProperty(prefix+"cameraAutoExposure")!=null) if (properties.getProperty(prefix+"cameraAutoExposure")!=null)
this.cameraAutoExposure=Boolean.parseBoolean(properties.getProperty(prefix+"cameraAutoExposure")); this.cameraAutoExposure=Boolean.parseBoolean(properties.getProperty(prefix+"cameraAutoExposure"));
if (properties.getProperty(prefix+"cameraAutoWhiteBalance")!=null) if (properties.getProperty(prefix+"cameraAutoWhiteBalance")!=null)
...@@ -438,6 +539,7 @@ public class CalibrationHardwareInterface { ...@@ -438,6 +539,7 @@ public class CalibrationHardwareInterface {
} }
} }
initIPs(); // was missing here?
initJP4(); initJP4();
} }
...@@ -458,23 +560,25 @@ public class CalibrationHardwareInterface { ...@@ -458,23 +560,25 @@ public class CalibrationHardwareInterface {
//http://192.168.0.221/parsedit.php?title=bright-day&immediate&EXPOS=10000*0&AUTOEXP_ON=0*0&WB_EN=0*0&COLOR=1*0&GAINR=0x270a4*0&GAING=0x20000*0&GAINB=0x2999a*0&GAINGB=0x20000*0 //http://192.168.0.221/parsedit.php?title=bright-day&immediate&EXPOS=10000*0&AUTOEXP_ON=0*0&WB_EN=0*0&COLOR=1*0&GAINR=0x270a4*0&GAING=0x20000*0&GAINB=0x2999a*0&GAINGB=0x20000*0
//http://192.168.0.221/parsedit.php?immediate&TRIG&TRIG_PERIOD //http://192.168.0.221/parsedit.php?immediate&TRIG&TRIG_PERIOD
GenericDialog gd = new GenericDialog(title); GenericDialog gd = new GenericDialog(title);
gd.addCheckbox ("NC393 (unchecked - nc353)", this.nc393);
gd.addStringField ("Subnet of the cameras (3 first of the four IPv4 address ending with '.')",this.cameraSubnet,12); gd.addStringField ("Subnet of the cameras (3 first of the four IPv4 address ending with '.')",this.cameraSubnet,12);
gd.addNumericField("Last byte of the first sub-camera IP address)",this.iBaseIP,0); gd.addNumericField("Last byte of the first sub-camera IP address)",this.iBaseIP,0);
gd.addNumericField("Camera boot time",this.cameraBootTimeSeconds,0,3,"sec"); gd.addNumericField("Camera boot time",this.cameraBootTimeSeconds,0,3,"sec");
gd.addNumericField("Network connection timeout",this.connectionTimeoutMilliseconds,0,3,"ms"); gd.addNumericField("Network connection timeout",this.connectionTimeoutMilliseconds,0,3,"ms");
gd.addNumericField("Index (in IP table) of the master camera (used for triggering)",this.masterSubCamera,0); gd.addNumericField("Index (in IP table) of the master camera (used for triggering)",this.masterSubCamera,0);
gd.addNumericField("Master (used for triggering), normally lowest connected port (0..3)",this.masterPort,0);
gd.addNumericField("Image server port number)",this.imgsrvPort,0); gd.addNumericField("Image server port number)",this.imgsrvPort,0);
gd.addStringField ("Image server command to reset image buffer",this.resetURLcmd,15); gd.addStringField ("Image server command to reset image buffer",this.resetURLcmd,25);
gd.addStringField ("Image server command to trigger acquisition",this.triggerURLcmd,15); gd.addStringField ("Image server command to trigger acquisition",this.triggerURLcmd,25);
gd.addStringField ("Image server command to acquire image (waits for the new one after reset)",this.imageURLcmd,15); gd.addStringField ("Image server command to acquire image (waits for the new one after reset)",this.imageURLcmd,25);
gd.addStringField ("Image server command to receive XML metadata (with timestamp)",this.metaURLcmd,15); gd.addStringField ("Image server command to receive XML metadata (with timestamp)",this.metaURLcmd,25);
gd.addMessage("Configure each sub-camera - which IP index and channel does it use."); gd.addMessage("Configure each sub-camera - which IP index and channel does it use.");
if (askRegenerate) gd.addMessage("You may change number of subcameras and press REGENERATE below"); if (askRegenerate) gd.addMessage("You may change number of subcameras and press REGENERATE below");
for (int i=0; i< this.channelMap.length;i++){ for (int i=0; i< this.channelMap.length;i++){
gd.addMessage("---------------------------------------------------------"); gd.addMessage("---------------------------------------------------------");
gd.addNumericField("Subcamera "+(i+1)+" IP index (starting from 0)", this.channelMap[i][0],0); gd.addNumericField("Subcamera "+(i+1)+" IP index (starting from 0)", this.channelMap[i][0],0);
gd.addNumericField("Subcamera "+(i+1)+" port (0..3)", this.channelMap[i][2],0);
gd.addNumericField("Subcamera "+(i+1)+" channel (0,1 or 2)", this.channelMap[i][1],0); gd.addNumericField("Subcamera "+(i+1)+" channel (0,1 or 2)", this.channelMap[i][1],0);
gd.addCheckbox("Subcamera "+(i+1)+" - used mirror", this.flipImages[i]); gd.addCheckbox("Subcamera "+(i+1)+" - used mirror", this.flipImages[i]);
} }
...@@ -487,6 +591,7 @@ public class CalibrationHardwareInterface { ...@@ -487,6 +591,7 @@ public class CalibrationHardwareInterface {
WindowTools.addScrollBars(gd); WindowTools.addScrollBars(gd);
gd.showDialog(); gd.showDialog();
if (gd.wasCanceled()) return false; if (gd.wasCanceled()) return false;
this.nc393= gd.getNextBoolean();
this.cameraSubnet= gd.getNextString(); this.cameraSubnet= gd.getNextString();
if (!this.cameraSubnet.endsWith(".")) this.cameraSubnet += "."; if (!this.cameraSubnet.endsWith(".")) this.cameraSubnet += ".";
int bip= (int) gd.getNextNumber(); int bip= (int) gd.getNextNumber();
...@@ -497,6 +602,8 @@ public class CalibrationHardwareInterface { ...@@ -497,6 +602,8 @@ public class CalibrationHardwareInterface {
this.cameraBootTimeSeconds=(int) gd.getNextNumber(); this.cameraBootTimeSeconds=(int) gd.getNextNumber();
this.connectionTimeoutMilliseconds=(int) gd.getNextNumber(); this.connectionTimeoutMilliseconds=(int) gd.getNextNumber();
this.masterSubCamera= (int) gd.getNextNumber(); // should be after initIPs()! this.masterSubCamera= (int) gd.getNextNumber(); // should be after initIPs()!
this.masterPort= (int) gd.getNextNumber(); // should be after initIPs()!
this.imgsrvPort= (int) gd.getNextNumber(); this.imgsrvPort= (int) gd.getNextNumber();
this.resetURLcmd= gd.getNextString(); this.resetURLcmd= gd.getNextString();
this.triggerURLcmd= gd.getNextString(); this.triggerURLcmd= gd.getNextString();
...@@ -504,6 +611,7 @@ public class CalibrationHardwareInterface { ...@@ -504,6 +611,7 @@ public class CalibrationHardwareInterface {
this.metaURLcmd= gd.getNextString(); this.metaURLcmd= gd.getNextString();
for (int i=0; i< this.channelMap.length;i++){ for (int i=0; i< this.channelMap.length;i++){
this.channelMap[i][0]=(int) gd.getNextNumber(); this.channelMap[i][0]=(int) gd.getNextNumber();
this.channelMap[i][2]=(int) gd.getNextNumber();
this.channelMap[i][1]=(int) gd.getNextNumber(); this.channelMap[i][1]=(int) gd.getNextNumber();
this.flipImages[i]= gd.getNextBoolean(); this.flipImages[i]= gd.getNextBoolean();
} }
...@@ -557,8 +665,11 @@ public class CalibrationHardwareInterface { ...@@ -557,8 +665,11 @@ public class CalibrationHardwareInterface {
public String getSerialNumber(int chn, int EEPROM_chn){ public String getSerialNumber(int chn, int EEPROM_chn){
String url="http://"+this.cameraIPs[chn]+"/i2c.php?cmd=fromEEPROM0&EEPROM_chn="+EEPROM_chn; int colon_index = this.cameraIPs[chn].indexOf(":");
int sensor_port = Integer.parseInt(this.cameraIPs[chn].substring(colon_index+1)) - this.imgsrvPort;
String ip=this.cameraIPs[chn].substring(0, colon_index);
// String url="http://"+this.cameraIPs[chn]+"/i2c.php?cmd=fromEEPROM0&EEPROM_chn="+EEPROM_chn;
String url="http://"+ip+"/i2c.php?cmd=fromEEPROM" + sensor_port+ "&EEPROM_chn="+EEPROM_chn;
Document dom=null; Document dom=null;
String serial=null; String serial=null;
try { try {
...@@ -610,45 +721,50 @@ public class CalibrationHardwareInterface { ...@@ -610,45 +721,50 @@ public class CalibrationHardwareInterface {
printTiming("=== setupCameraAcquisition()"); printTiming("=== setupCameraAcquisition()");
} }
if (!this.sensorPresent[chn][0] && !this.sensorPresent[chn][1] && !this.sensorPresent[chn][2]) EEPROM_chn=0; // no 10359 - null pointer while "lens center" if first if (!this.sensorPresent[chn][0] && !this.sensorPresent[chn][1] && !this.sensorPresent[chn][2]) EEPROM_chn=0; // no 10359 - null pointer while "lens center" if first
String url="http://"+this.cameraIPs[chn]+"/i2c.php?cmd=fromEEPROM0&EEPROM_chn="+EEPROM_chn;
this.lastTemperature=Double.NaN; int colon_index = this.cameraIPs[chn].indexOf(":");
Document dom=null; int sensor_port = Integer.parseInt(this.cameraIPs[chn].substring(colon_index+1)) - this.imgsrvPort;
try { String ip=this.cameraIPs[chn].substring(0, colon_index);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); // String url="http://"+this.cameraIPs[chn]+"/i2c.php?cmd=fromEEPROM0&EEPROM_chn="+EEPROM_chn;
DocumentBuilder db = dbf.newDocumentBuilder(); String url="http://"+ip+"/i2c.php?cmd=fromEEPROM"+ sensor_port +"&EEPROM_chn="+EEPROM_chn;
dom = db.parse(url); this.lastTemperature=Double.NaN;
if (!dom.getDocumentElement().getNodeName().equals("board")) { Document dom=null;
String msg="Root element: expected 'board', got \"" + dom.getDocumentElement().getNodeName()+"\""; try {
IJ.showMessage("Error",msg); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
throw new IllegalArgumentException (msg); DocumentBuilder db = dbf.newDocumentBuilder();
} dom = db.parse(url);
if (!dom.getDocumentElement().getNodeName().equals("board")) {
String sTemperature=((Node) (((Node) dom.getDocumentElement().getElementsByTagName("sensorTemperature").item(0)).getChildNodes().item(0))).getNodeValue(); String msg="Root element: expected 'board', got \"" + dom.getDocumentElement().getNodeName()+"\"";
// remove opening and closing " IJ.showMessage("Error",msg);
if (sTemperature==null){ throw new IllegalArgumentException (msg);
String msg="Could not read sensor temperature"; }
// IJ.showMessage("Error",msg);
System.out.println("Warning: "+msg); String sTemperature=((Node) (((Node) dom.getDocumentElement().getElementsByTagName("sensorTemperature").item(0)).getChildNodes().item(0))).getNodeValue();
return Double.parseDouble(sTemperature); // remove opening and closing "
} if (sTemperature==null){
this.lastTemperature= Double.parseDouble(sTemperature); String msg="Could not read sensor temperature";
} catch(MalformedURLException e){ // IJ.showMessage("Error",msg);
String msg="Please check the URL:" + e.toString(); System.out.println("Warning: "+msg);
IJ.showMessage("Error",msg); return Double.parseDouble(sTemperature);
throw new IllegalArgumentException (msg); }
} catch(IOException e1){ this.lastTemperature= Double.parseDouble(sTemperature);
String msg = e1.getMessage(); } catch(MalformedURLException e){
if (msg==null || msg.equals("")) msg = ""+e1; String msg="Please check the URL:" + e.toString();
IJ.showMessage("Error",msg); IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg); throw new IllegalArgumentException (msg);
}catch(ParserConfigurationException pce) { } catch(IOException e1){
pce.printStackTrace(); String msg = e1.getMessage();
throw new IllegalArgumentException ("PCE error"); if (msg==null || msg.equals("")) msg = ""+e1;
}catch(SAXException se) { IJ.showMessage("Error",msg);
se.printStackTrace(); throw new IllegalArgumentException (msg);
throw new IllegalArgumentException ("SAX error"); }catch(ParserConfigurationException pce) {
} pce.printStackTrace();
return this.lastTemperature; throw new IllegalArgumentException ("PCE error");
}catch(SAXException se) {
se.printStackTrace();
throw new IllegalArgumentException ("SAX error");
}
return this.lastTemperature;
} }
...@@ -683,12 +799,15 @@ public class CalibrationHardwareInterface { ...@@ -683,12 +799,15 @@ public class CalibrationHardwareInterface {
if (probeCameraState(chn)) { if (probeCameraState(chn)) {
numOnline++; numOnline++;
printTiming("===== probing channel "+chn); printTiming("===== probing channel "+chn);
boolean single_no_mux= (!this.sensorPresent[chn][0] && !this.sensorPresent[chn][1] && !this.sensorPresent[chn][2]);
if (this.debugLevel>1) System.out.println("Frame number: "+this.cameraFrameNumber[chn]+ if (this.debugLevel>1) System.out.println("Frame number: "+this.cameraFrameNumber[chn]+
", Trigger mode:"+(this.triggeredMode[chn]?"ex":"in")+"ternal, "+ ", Trigger mode:"+(this.triggeredMode[chn]?"ex":"in")+"ternal, "+
" sensors attached:"+(this.sensorPresent[chn][0]?"1 ":"")+(this.sensorPresent[chn][1]?"2 ":"")+(this.sensorPresent[chn][2]?"3 ":"")+ " sensors attached:"+(this.sensorPresent[chn][0]?"1 ":"")+(this.sensorPresent[chn][1]?"2 ":"")+(this.sensorPresent[chn][2]?"3 ":"")+
((!this.sensorPresent[chn][0] && !this.sensorPresent[chn][1] && !this.sensorPresent[chn][2])?"single-sensor, no multiplexer":"") (single_no_mux?"single-sensor, no multiplexer":"") +
(" Master port "+this.cameraMasterPort[chn])
); );
for (int i=0;i<this.sensorPresent[chn].length;i++) if (this.sensorPresent[chn][i]) numSensors++; for (int i=0;i<this.sensorPresent[chn].length;i++) if (this.sensorPresent[chn][i]) numSensors++;
if (single_no_mux) numSensors++;
} else { } else {
if (this.debugLevel>1) System.out.println("Camera did not respond"); if (this.debugLevel>1) System.out.println("Camera did not respond");
} }
...@@ -700,11 +819,12 @@ public class CalibrationHardwareInterface { ...@@ -700,11 +819,12 @@ public class CalibrationHardwareInterface {
public void initCameraArrays(int numChn){ public void initCameraArrays(int numChn){
if (this.debugLevel>1) System.out.println("initCameraArrays("+numChn+")"); if (this.debugLevel>1) System.out.println("initCameraArrays("+numChn+")");
this.cameraFrameNumber=new int[numChn]; this.cameraFrameNumber=new int[numChn];
this.triggeredMode=new boolean[numChn]; this.triggeredMode= new boolean[numChn];
this.sensorPresent=new boolean[numChn][]; this.sensorPresent= new boolean[numChn][];
// TODO - try if skipping setting TRIG_PERIOD=0, IRQ_SMART=6 (when they are already set) will fix hanging // TODO - try if skipping setting TRIG_PERIOD=0, IRQ_SMART=6 (when they are already set) will fix hanging
this.triggerPeriod=new int[numChn]; this.triggerPeriod= new int[numChn];
this.irqSmart= new int[numChn]; this.irqSmart= new int[numChn];
this.cameraMasterPort= new int[numChn]; // not sure if will use it - master port for each camera:port
} }
public boolean probeCameraState( public boolean probeCameraState(
int chn){ int chn){
...@@ -718,15 +838,30 @@ public class CalibrationHardwareInterface { ...@@ -718,15 +838,30 @@ public class CalibrationHardwareInterface {
int timeout // ms int timeout // ms
){ ){
//http://192.168.0.221/parsedit.php?immediate&TRIG&TRIG_PERIOD&FRAME //http://192.168.0.221/parsedit.php?immediate&TRIG&TRIG_PERIOD&FRAME
String url="http://"+this.cameraIPs[chn]+"/parsedit.php?immediate&TRIG&TRIG_PERIOD&IRQ_SMART&SENS_AVAIL&FRAME"; String url;
int colon_index = this.cameraIPs[chn].indexOf(":");
int sensor_port = Integer.parseInt(this.cameraIPs[chn].substring(colon_index+1)) - this.imgsrvPort;
String ip=this.cameraIPs[chn].substring(0, colon_index);
if (this.nc393){
// url="http://"+this.cameraIPs[chn]+"/parsedit.php?immediate&TRIG&TRIG_PERIOD&SENS_AVAIL&FRAME";
url="http://"+ip+"/parsedit.php?sensor_port="+sensor_port+"&immediate&TRIG&TRIG_PERIOD&SENS_AVAIL&FRAME&TRIG_MASTER";
} else {
// url="http://"+this.cameraIPs[chn]+"/parsedit.php?immediate&TRIG&TRIG_PERIOD&IRQ_SMART&SENS_AVAIL&FRAME";
url="http://"+ip+"/parsedit.php?immediate&TRIG&TRIG_PERIOD&IRQ_SMART&SENS_AVAIL&FRAME";
}
if (this.debugLevel>1) System.out.println("url="+url); if (this.debugLevel>1) System.out.println("url="+url);
Document dom=null; Document dom=null;
if ((this.cameraFrameNumber==null) || ((this.cameraFrameNumber.length<(chn+1)))) initCameraArrays(chn+1); if ((this.cameraFrameNumber==null) || ((this.cameraFrameNumber.length<(chn+1)))) initCameraArrays(chn+1);
// did not find yet - why cameraFrameNumber is not null, but sensorPresent is? Added next lines until find // did not find yet - why cameraFrameNumber is not null, but sensorPresent is? Added next lines until find
if ((this.triggeredMode==null) || ((this.triggeredMode.length<(chn+1)))) initCameraArrays(chn+1); if ((this.triggeredMode==null) || ((this.triggeredMode.length<(chn+1)))) initCameraArrays(chn+1);
if ((this.sensorPresent==null) || ((this.sensorPresent.length<(chn+1)))) initCameraArrays(chn+1); if ((this.sensorPresent==null) || ((this.sensorPresent.length<(chn+1)))) initCameraArrays(chn+1);
if ((this.triggerPeriod==null) || ((this.triggerPeriod.length<(chn+1)))) initCameraArrays(chn+1); if ((this.triggerPeriod==null) || ((this.triggerPeriod.length<(chn+1)))) initCameraArrays(chn+1);
if ((this.irqSmart==null) || ((this.irqSmart.length<(chn+1)))) initCameraArrays(chn+1); if (!this.nc393) {
if ((this.irqSmart==null) || ((this.irqSmart.length<(chn+1)))) initCameraArrays(chn+1);
} else {
if ((this.cameraMasterPort==null) || ((this.cameraMasterPort.length<(chn+1)))) initCameraArrays(chn+1);
}
try { try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder(); DocumentBuilder db = dbf.newDocumentBuilder();
...@@ -758,7 +893,12 @@ public class CalibrationHardwareInterface { ...@@ -758,7 +893,12 @@ public class CalibrationHardwareInterface {
this.sensorPresent[chn]=new boolean[3]; this.sensorPresent[chn]=new boolean[3];
for (int i=0;i<this.sensorPresent[chn].length;i++) this.sensorPresent[chn][i]=(sensAvail & (1<<i))!=0; for (int i=0;i<this.sensorPresent[chn].length;i++) this.sensorPresent[chn][i]=(sensAvail & (1<<i))!=0;
this.triggerPeriod[chn]= Integer.parseInt(((Node) (((Node) dom.getDocumentElement().getElementsByTagName("TRIG_PERIOD").item(0)).getChildNodes().item(0))).getNodeValue()); this.triggerPeriod[chn]= Integer.parseInt(((Node) (((Node) dom.getDocumentElement().getElementsByTagName("TRIG_PERIOD").item(0)).getChildNodes().item(0))).getNodeValue());
this.irqSmart[chn]= Integer.parseInt(((Node) (((Node) dom.getDocumentElement().getElementsByTagName("IRQ_SMART").item(0)).getChildNodes().item(0))).getNodeValue()); if (!this.nc393) {
this.irqSmart[chn]= Integer.parseInt(((Node) (((Node) dom.getDocumentElement().getElementsByTagName("IRQ_SMART").item(0)).getChildNodes().item(0))).getNodeValue());
this.cameraMasterPort[chn]= sensor_port;
} else {
this.cameraMasterPort[chn]= Integer.parseInt(((Node) (((Node) dom.getDocumentElement().getElementsByTagName("TRIG_MASTER").item(0)).getChildNodes().item(0))).getNodeValue());
}
this.cameraFrameNumber[chn]= Integer.parseInt(((Node) (((Node) dom.getDocumentElement().getElementsByTagName("FRAME").item(0)).getChildNodes().item(0))).getNodeValue()); this.cameraFrameNumber[chn]= Integer.parseInt(((Node) (((Node) dom.getDocumentElement().getElementsByTagName("FRAME").item(0)).getChildNodes().item(0))).getNodeValue());
} catch(MalformedURLException e){ } catch(MalformedURLException e){
String msg="Please check the URL:" + e.toString(); String msg="Please check the URL:" + e.toString();
...@@ -812,6 +952,7 @@ public class CalibrationHardwareInterface { ...@@ -812,6 +952,7 @@ public class CalibrationHardwareInterface {
startAndJoin(threads); startAndJoin(threads);
if (Double.isNaN(exposureScale)){ // full init if (Double.isNaN(exposureScale)){ // full init
int nRepeat=this.setupTriggerMode?4:1; int nRepeat=this.setupTriggerMode?4:1;
if (this.nc393) nRepeat++; // is it needed?
for (int i=0;i<nRepeat;i++){ for (int i=0;i<nRepeat;i++){
if (this.debugLevel>0) System.out.println((i+1)+" of "+nRepeat+": Triggering cameras to give parameters a chance to propagate"); if (this.debugLevel>0) System.out.println((i+1)+" of "+nRepeat+": Triggering cameras to give parameters a chance to propagate");
trigger(); trigger();
...@@ -845,6 +986,16 @@ public class CalibrationHardwareInterface { ...@@ -845,6 +986,16 @@ public class CalibrationHardwareInterface {
} }
// TODO: issue several TRIG pulses after setting parameters? // TODO: issue several TRIG pulses after setting parameters?
public boolean setupCameraAcquisition(int chn, double exposureScale){ public boolean setupCameraAcquisition(int chn, double exposureScale){
int colon_index = this.cameraIPs[chn].indexOf(":");
int sensor_port = Integer.parseInt(this.cameraIPs[chn].substring(colon_index+1)) - this.imgsrvPort;
String ip=this.cameraIPs[chn].substring(0, colon_index);
boolean isMasterSubcamera = ip.equals(this.cameraSubnet+(this.iBaseIP+this.masterSubCamera));
boolean isMasterPort = (this.cameraMasterPort[chn] == sensor_port); // for 353 should always be master port
if (isMasterSubcamera && (this.cameraMasterPort[chn] != this.masterPort)){
System.out.println("Master port mismatch for camera "+ip+" (master) - parameters master port = "+
this.masterPort+", camera responded with "+this.cameraMasterPort[chn] );
}
if (this.debugLevel>1) System.out.println("DEBUG393: chn="+chn+" sensor_port="+sensor_port+" ip= "+ip+" isMasterSubcamera="+isMasterSubcamera+ " isMasterPort="+isMasterPort);
boolean exposureOnly=!Double.isNaN(exposureScale); boolean exposureOnly=!Double.isNaN(exposureScale);
int minExposure=10; // usec int minExposure=10; // usec
int maxExposure=1000000; //usec int maxExposure=1000000; //usec
...@@ -860,6 +1011,7 @@ public class CalibrationHardwareInterface { ...@@ -860,6 +1011,7 @@ public class CalibrationHardwareInterface {
int gScale= (int) (Math.round(0x10000*this.cameraGScale*this.cameraGScaleCorr[chn])); int gScale= (int) (Math.round(0x10000*this.cameraGScale*this.cameraGScaleCorr[chn]));
int autoExp= this.cameraAutoExposure?1:0; int autoExp= this.cameraAutoExposure?1:0;
int autoWB= this.cameraAutoWhiteBalance?1:0; int autoWB= this.cameraAutoWhiteBalance?1:0;
String extraURL=""; String extraURL="";
if (this.cameraExtraURLCommon.length()>0){ if (this.cameraExtraURLCommon.length()>0){
extraURL+=(this.cameraExtraURLCommon.substring(0,1).equals("&"))?"":"&"+this.cameraExtraURLCommon; extraURL+=(this.cameraExtraURLCommon.substring(0,1).equals("&"))?"":"&"+this.cameraExtraURLCommon;
...@@ -874,19 +1026,62 @@ public class CalibrationHardwareInterface { ...@@ -874,19 +1026,62 @@ public class CalibrationHardwareInterface {
if (bScale<minScale) bScale= minScale ; else if (bScale> maxScale) bScale= maxScale; if (bScale<minScale) bScale= minScale ; else if (bScale> maxScale) bScale= maxScale;
if (gScale<minScale) gScale= minScale ; else if (gScale> maxScale) gScale= maxScale; if (gScale<minScale) gScale= minScale ; else if (gScale> maxScale) gScale= maxScale;
String triggerMode=this.setupTriggerMode?( String triggerMode="";
"&TRIG_CONDITION="+(this.noCabling?(0):(this.externalTriggerCabling?"0x200000":"0x20000"))+"*0"+
"&TRIG_OUT="+(this.noCabling?(0):(this.externalTriggerCabling?"0x800000":"0x80000"))+"*0"+
"&TRIG=4*3"):""; if (this.nc393) {
if (this.triggerPeriod[chn]>1)triggerMode+="&TRIG_PERIOD=1*0"; // just imgsrv /trig does not set it, only FPGA register if (isMasterPort) {
/*
* P_TRIG_OUT (outputs):
* off: 0x00000
* external: 0x02000
* internal: 0x20000
* both: 0x22000
* P_TRIG_IN (inputs):
* off: 0x00000
* external: 0x80000
* internal: 0x08000
* both: 0x88000
*/
if (this.setupTriggerMode){
triggerMode+="&TRIG_CONDITION="+(this.noCabling?(0):(this.externalTriggerCabling?"0x80000":"0x08000"))+"*0"+
"&TRIG_OUT="+(this.noCabling?(0):(this.externalTriggerCabling?"0x02000":"0x20000"))+"*0"+
"&TRIG=4*3";
}
if ((this.triggerPeriod[chn]>1) || this.setupTriggerMode) {
triggerMode+="&TRIG_PERIOD=0*1"; // just stop it if it wasn't already, imgsrv /trig does not set it, only FPGA register
}
}
}else {
if (this.setupTriggerMode){
triggerMode+="&TRIG_CONDITION="+(this.noCabling?(0):(this.externalTriggerCabling?"0x200000":"0x20000"))+"*0"+
"&TRIG_OUT="+(this.noCabling?(0):(this.externalTriggerCabling?"0x800000":"0x80000"))+"*0"+
"&TRIG=4*3";
}
if ((this.triggerPeriod[chn]>1) || this.setupTriggerMode){
triggerMode+="&TRIG_PERIOD=1*0"; // just imgsrv /trig does not set it, only FPGA register
}
}
String url="http://"+ip+"/parsedit.php?immediate";
if (this.nc393) {
url += "&sensor_port="+sensor_port;
}
String url="http://"+this.cameraIPs[chn]+"/parsedit.php?immediate";
url+="&EXPOS="+exposure+"*0"; // always url+="&EXPOS="+exposure+"*0"; // always
if (!exposureOnly){ if (!exposureOnly){
if (this.irqSmart[chn]!=(this.noWait?6:3)){ if (!this.nc393) {
url+="&IRQ_SMART="+(this.noWait?6:3)+"*0"; if (this.irqSmart[chn]!=(this.noWait?6:3)){
url+="&IRQ_SMART="+(this.noWait?6:3)+"*0";
}
} }
url+="&COLOR="+this.colorMode+"*0"+ url+="&COLOR="+this.colorMode+"*"+(this.nc393?"1":"0")+
"&QUALITY="+this.JPEGquality+"*0"+ "&QUALITY="+this.JPEGquality+"*0"+
"&EXPOS="+exposure+"*0"+ "&EXPOS="+exposure+"*0"+
"&AUTOEXP_EXP_MAX="+autoExposureMax+"*0"+ "&AUTOEXP_EXP_MAX="+autoExposureMax+"*0"+
...@@ -941,9 +1136,9 @@ public class CalibrationHardwareInterface { ...@@ -941,9 +1136,9 @@ public class CalibrationHardwareInterface {
private boolean editSubCamerasIPs() { private boolean editSubCamerasIPs() {
GenericDialog gd = new GenericDialog("Edit IPs/hosts of the sub cameras"); GenericDialog gd = new GenericDialog("Edit IPs/hosts and ports of the sub cameras");
for (int i=0;i<this.cameraIPs.length;i++){ for (int i=0;i<this.cameraIPs.length;i++){
gd.addStringField(i+": IP address/host of the subcamera",this.cameraIPs[i],20); gd.addStringField(i+": IP address/host:sensor port of the subcamera",this.cameraIPs[i],25);
} }
WindowTools.addScrollBars(gd); WindowTools.addScrollBars(gd);
gd.showDialog(); gd.showDialog();
...@@ -959,6 +1154,7 @@ public class CalibrationHardwareInterface { ...@@ -959,6 +1154,7 @@ public class CalibrationHardwareInterface {
public boolean editCameraSettings(String title){ public boolean editCameraSettings(String title){
GenericDialog gd = new GenericDialog("title"); GenericDialog gd = new GenericDialog("title");
gd.addCheckbox ("NC393 (unchecked - nc353)", this.nc393);
gd.addNumericField("Camera exposure",this.cameraExposure,2,8,"ms"); gd.addNumericField("Camera exposure",this.cameraExposure,2,8,"ms");
gd.addNumericField("Scale camera exposure for target laser detection (4 lasers)",100*this.scaleExposureForLasers,1,5,"%"); gd.addNumericField("Scale camera exposure for target laser detection (4 lasers)",100*this.scaleExposureForLasers,1,5,"%");
gd.addNumericField("Scale camera exposure for optical head laser detection (2 lasers)",100*this.scaleExposureForHeadLasers,1,5,"%"); gd.addNumericField("Scale camera exposure for optical head laser detection (2 lasers)",100*this.scaleExposureForHeadLasers,1,5,"%");
...@@ -1000,6 +1196,7 @@ public class CalibrationHardwareInterface { ...@@ -1000,6 +1196,7 @@ public class CalibrationHardwareInterface {
WindowTools.addScrollBars(gd); WindowTools.addScrollBars(gd);
gd.showDialog(); gd.showDialog();
if (gd.wasCanceled()) return false; if (gd.wasCanceled()) return false;
this.nc393= gd.getNextBoolean();
this.cameraExposure= gd.getNextNumber(); this.cameraExposure= gd.getNextNumber();
this.scaleExposureForLasers= 0.01*gd.getNextNumber(); this.scaleExposureForLasers= 0.01*gd.getNextNumber();
this.scaleExposureForHeadLasers=0.01*gd.getNextNumber(); this.scaleExposureForHeadLasers=0.01*gd.getNextNumber();
...@@ -1061,7 +1258,8 @@ public class CalibrationHardwareInterface { ...@@ -1061,7 +1258,8 @@ public class CalibrationHardwareInterface {
boolean [] IPs= new boolean[this.cameraIPs.length]; boolean [] IPs= new boolean[this.cameraIPs.length];
for (int i=0;i<IPs.length;i++) IPs[i]=false; for (int i=0;i<IPs.length;i++) IPs[i]=false;
for (int i=0;i<selectCameras.length;i++) if (i<this.channelMap.length) { for (int i=0;i<selectCameras.length;i++) if (i<this.channelMap.length) {
IPs[this.channelMap[i][0]]=true; // IPs[this.channelMap[i][0]]=true;
IPs[this.channelIPPort[i]] = true; // since NC393
} }
return IPs; return IPs;
} }
...@@ -1242,7 +1440,7 @@ public class CalibrationHardwareInterface { ...@@ -1242,7 +1440,7 @@ public class CalibrationHardwareInterface {
public void run() { public void run() {
for (int ipIndex=ipIndexAtomic.getAndIncrement(); ipIndex<ipLength;ipIndex=ipIndexAtomic.getAndIncrement()){ for (int ipIndex=ipIndexAtomic.getAndIncrement(); ipIndex<ipLength;ipIndex=ipIndexAtomic.getAndIncrement()){
// for (int i=0;i<this.imagesIP.length;i++){ // for (int i=0;i<this.imagesIP.length;i++){
if (debugLevel>2) System.out.println("getImages()3: ipIndex="+ipIndex+" acquireIPs.length=" +acquireIPs.length+ if (debugLevel>1/*2*/) System.out.println("getImages()3: ipIndex="+ipIndex+" acquireIPs.length=" +acquireIPs.length+
((ipIndex<acquireIPs.length)? (" acquireIPs[ipIndex]="+acquireIPs[ipIndex]):"")); ((ipIndex<acquireIPs.length)? (" acquireIPs[ipIndex]="+acquireIPs[ipIndex]):""));
if ((ipIndex<acquireIPs.length) && acquireIPs[ipIndex]) { if ((ipIndex<acquireIPs.length) && acquireIPs[ipIndex]) {
if (debugLevel>2) System.out.println("getImages:" + imageURLs[ipIndex] ); if (debugLevel>2) System.out.println("getImages:" + imageURLs[ipIndex] );
...@@ -1280,8 +1478,10 @@ public class CalibrationHardwareInterface { ...@@ -1280,8 +1478,10 @@ public class CalibrationHardwareInterface {
//TODO: Multithread the next cycle (per-sensor) //TODO: Multithread the next cycle (per-sensor)
final ImagePlus [] images=this.images; final ImagePlus [] images=this.images;
final int [][] channelMap = this.channelMap; final int [][] channelMap = this.channelMap;
final int [] channelIPPort = this.channelIPPort;
final AtomicInteger imageIndexAtomic = new AtomicInteger(0); final AtomicInteger imageIndexAtomic = new AtomicInteger(0);
final int [] motorsPosition=this.motorsPosition; final int [] motorsPosition=this.motorsPosition;
for (int ithread = 0; ithread < threads.length; ithread++) { for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() { threads[ithread] = new Thread() {
public void run() { public void run() {
...@@ -1290,7 +1490,8 @@ public class CalibrationHardwareInterface { ...@@ -1290,7 +1490,8 @@ public class CalibrationHardwareInterface {
for (int imageIndex=imageIndexAtomic.getAndIncrement(); imageIndex<images.length;imageIndex=imageIndexAtomic.getAndIncrement()) for (int imageIndex=imageIndexAtomic.getAndIncrement(); imageIndex<images.length;imageIndex=imageIndexAtomic.getAndIncrement())
if ((imageIndex<acquire.length) && acquire[imageIndex]){ if ((imageIndex<acquire.length) && acquire[imageIndex]){
// for (int i=0;i<this.images.length;i++) if ((i<acquire.length) && acquire[i]) { // for (int i=0;i<this.images.length;i++) if ((i<acquire.length) && acquire[i]) {
int iIP=channelMap[imageIndex][0]; // int iIP=channelMap[imageIndex][0];
int iIP=channelIPPort[imageIndex]; // index in composite images (per ip/port)
if (sensorPresent[iIP]==null) { // system board for this channel did not respond null pointer - check cameras were detected if (sensorPresent[iIP]==null) { // system board for this channel did not respond null pointer - check cameras were detected
images[imageIndex]=null; images[imageIndex]=null;
continue; continue;
...@@ -1298,6 +1499,7 @@ public class CalibrationHardwareInterface { ...@@ -1298,6 +1499,7 @@ public class CalibrationHardwareInterface {
boolean singleSensor=true; boolean singleSensor=true;
for (int s=0;s<sensorPresent[iIP].length;s++) singleSensor&= !sensorPresent[iIP][s]; for (int s=0;s<sensorPresent[iIP].length;s++) singleSensor&= !sensorPresent[iIP][s];
if (singleSensor){ // no 10359 multiplexor if (singleSensor){ // no 10359 multiplexor
if (debugLevel>1) System.out.println("DEBUG393: demuxing single sensor imageIndex="+imageIndex+" iIP="+iIP);
images[imageIndex]=jp4_Instance.demuxClone(imagesIP[iIP]); images[imageIndex]=jp4_Instance.demuxClone(imagesIP[iIP]);
} else { } else {
int subCam=channelMap[imageIndex][1]; int subCam=channelMap[imageIndex][1];
...@@ -1307,6 +1509,7 @@ public class CalibrationHardwareInterface { ...@@ -1307,6 +1509,7 @@ public class CalibrationHardwareInterface {
} }
// skip missing channels, then demux // skip missing channels, then demux
for (int s=0;s<channelMap[imageIndex][1];s++) if (!sensorPresent[iIP][s]) subCam--; for (int s=0;s<channelMap[imageIndex][1];s++) if (!sensorPresent[iIP][s]) subCam--;
if (debugLevel>1) System.out.println("DEBUG393: demuxing imageIndex="+imageIndex+" iIP="+iIP+" subCam="+subCam);
images[imageIndex]=jp4_Instance.demuxImage(imagesIP[iIP],subCam); images[imageIndex]=jp4_Instance.demuxImage(imagesIP[iIP],subCam);
} }
// this.images[i]=this.jp4_Instances[j].demuxImageOrClone(this.imagesIP[j],this.channelMap[i][1]); // this.images[i]=this.jp4_Instances[j].demuxImageOrClone(this.imagesIP[j],this.channelMap[i][1]);
...@@ -1331,6 +1534,7 @@ public class CalibrationHardwareInterface { ...@@ -1331,6 +1534,7 @@ public class CalibrationHardwareInterface {
} }
images[imageIndex].setProperty("channel", String.format("%02d", imageIndex)); images[imageIndex].setProperty("channel", String.format("%02d", imageIndex));
images[imageIndex].setProperty("subcamera",""+getSubCamera(imageIndex)); images[imageIndex].setProperty("subcamera",""+getSubCamera(imageIndex));
images[imageIndex].setProperty("sensor_port",""+getSensorPort(imageIndex));
images[imageIndex].setProperty("subchannel", ""+getSubChannel(imageIndex)); images[imageIndex].setProperty("subchannel", ""+getSubChannel(imageIndex));
// private int [] motorsPosition= null; // motors steps when the images were acquired (for null) // private int [] motorsPosition= null; // motors steps when the images were acquired (for null)
if (motorsPosition!=null) for (int m=0;m<motorsPosition.length;m++ ) { if (motorsPosition!=null) for (int m=0;m<motorsPosition.length;m++ ) {
...@@ -1425,6 +1629,9 @@ public class CalibrationHardwareInterface { ...@@ -1425,6 +1629,9 @@ public class CalibrationHardwareInterface {
public void run() { public void run() {
for (int ipIndex=ipIndexAtomic.getAndIncrement(); ipIndex<lasersIPs.length;ipIndex=ipIndexAtomic.getAndIncrement()){ for (int ipIndex=ipIndexAtomic.getAndIncrement(); ipIndex<lasersIPs.length;ipIndex=ipIndexAtomic.getAndIncrement()){
long st=System.nanoTime(); long st=System.nanoTime();
if (debugLevel>1) {
System.out.println("image url["+ipIndex+"]="+imageURLs[ipIndex]);
}
laserImagesIP[fnSeqNum-1][ipIndex]=jp4_Instances[ipIndex].openURL( laserImagesIP[fnSeqNum-1][ipIndex]=jp4_Instances[ipIndex].openURL(
imageURLs[ipIndex], imageURLs[ipIndex],
"", "",
...@@ -1476,6 +1683,7 @@ public class CalibrationHardwareInterface { ...@@ -1476,6 +1683,7 @@ public class CalibrationHardwareInterface {
final boolean otherGreen=laserPointers.laserPointer.otherGreen; final boolean otherGreen=laserPointers.laserPointer.otherGreen;
final int [][] channelMap=this.channelMap; final int [][] channelMap=this.channelMap;
final int [] channelIPPort = this.channelIPPort;
final ImagePlus [] images=this.images; final ImagePlus [] images=this.images;
final boolean [] flipImages=this.flipImages; final boolean [] flipImages=this.flipImages;
final LaserPointers laserPointers=this.laserPointers; final LaserPointers laserPointers=this.laserPointers;
...@@ -1494,7 +1702,8 @@ public class CalibrationHardwareInterface { ...@@ -1494,7 +1702,8 @@ public class CalibrationHardwareInterface {
for (int sensorNum=sensorNumAtomic.getAndIncrement(); sensorNum<lasers.length;sensorNum=sensorNumAtomic.getAndIncrement()) // null pointer for (int sensorNum=sensorNumAtomic.getAndIncrement(); sensorNum<lasers.length;sensorNum=sensorNumAtomic.getAndIncrement()) // null pointer
if (lasers[sensorNum] && (images[sensorNum]!=null)){ if (lasers[sensorNum] && (images[sensorNum]!=null)){
// for (int sensorNum=0;sensorNum<lasers.length;sensorNum++) if (lasers[sensorNum] && (this.images[sensorNum]!=null)){ // lasers - here sensors to use lasers for // for (int sensorNum=0;sensorNum<lasers.length;sensorNum++) if (lasers[sensorNum] && (this.images[sensorNum]!=null)){ // lasers - here sensors to use lasers for
int iIP=channelMap[sensorNum][0]; // int iIP=channelMap[sensorNum][0];
int iIP=channelIPPort[sensorNum]; // index in composite images (per ip/port)
double saturationRed=255.0; double saturationRed=255.0;
if (images[sensorNum].getProperty("saturation_0")!=null) saturationRed=Double.parseDouble((String)images[sensorNum].getProperty("saturation_0")); if (images[sensorNum].getProperty("saturation_0")!=null) saturationRed=Double.parseDouble((String)images[sensorNum].getProperty("saturation_0"));
if (scaleExposureForLasers>0) saturationRed*=scaleExposureForLasers; // scaled to reduced exposure time if (scaleExposureForLasers>0) saturationRed*=scaleExposureForLasers; // scaled to reduced exposure time
...@@ -1736,7 +1945,8 @@ public class CalibrationHardwareInterface { ...@@ -1736,7 +1945,8 @@ public class CalibrationHardwareInterface {
if (this.debugLevel>1) { if (this.debugLevel>1) {
if (this.debugLevel>2) System.out.println("++++++++++++++++++ Image Properies ++++++++++++++++++++++++++++"); if (this.debugLevel>2) System.out.println("++++++++++++++++++ Image Properies ++++++++++++++++++++++++++++");
for (int i=0;i<this.images.length;i++) if (this.images[i]!=null) { for (int i=0;i<this.images.length;i++) if (this.images[i]!=null) {
int j=this.channelMap[i][0]; // int j=this.channelMap[i][0];
int j=channelIPPort[i]; // sincer NC393 adder port
if (this.debugLevel>2) { if (this.debugLevel>2) {
System.out.println("Image #"+i); System.out.println("Image #"+i);
this.jp4_Instances[j].listImageProperties(this.images[i]); this.jp4_Instances[j].listImageProperties(this.images[i]);
...@@ -2914,7 +3124,7 @@ public class CalibrationHardwareInterface { ...@@ -2914,7 +3124,7 @@ public class CalibrationHardwareInterface {
} catch (IOException e) { } catch (IOException e) {
String msg="Failed to write XML motor state file: "+path; String msg="Failed to write XML motor state file: "+path;
IJ.showMessage("Error",msg); IJ.showMessage("Error",msg);
throw new IOException (msg); extracted(msg);
} }
try { try {
os.close(); os.close();
...@@ -2940,7 +3150,7 @@ public class CalibrationHardwareInterface { ...@@ -2940,7 +3150,7 @@ public class CalibrationHardwareInterface {
} catch (IOException e) { } catch (IOException e) {
String msg="Failed to read XML configuration file: "+path; String msg="Failed to read XML configuration file: "+path;
IJ.showMessage("Error",msg); IJ.showMessage("Error",msg);
throw new IOException (msg); extracted(msg);
} }
try { try {
is.close(); is.close();
...@@ -2958,11 +3168,14 @@ public class CalibrationHardwareInterface { ...@@ -2958,11 +3168,14 @@ public class CalibrationHardwareInterface {
} else { } else {
String msg="motor"+(i+1)+" is undefined in "+path+". If the file is corrupted you may delete it."; String msg="motor"+(i+1)+" is undefined in "+path+". If the file is corrupted you may delete it.";
IJ.showMessage("Error",msg); IJ.showMessage("Error",msg);
throw new IOException (msg); extracted(msg);
} }
} }
return savedPosition; return savedPosition;
} }
private void extracted(String msg) throws IOException {
throw new IOException (msg);
}
public void checkEnabled(){ public void checkEnabled(){
if (isEnabled()) return; if (isEnabled()) return;
GenericDialog gd = new GenericDialog("Enable motors"); GenericDialog gd = new GenericDialog("Enable motors");
......
...@@ -30,6 +30,8 @@ import ij.ImageStack; ...@@ -30,6 +30,8 @@ import ij.ImageStack;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import javax.swing.SwingUtilities;
public class DebayerScissors { public class DebayerScissors {
// showDoubleFloatArrays SDFA_INSTANCE= new showDoubleFloatArrays(); // showDoubleFloatArrays SDFA_INSTANCE= new showDoubleFloatArrays();
...@@ -96,104 +98,142 @@ public class DebayerScissors { ...@@ -96,104 +98,142 @@ public class DebayerScissors {
final Thread[] threads = newThreadArray(threadsMax); final Thread[] threads = newThreadArray(threadsMax);
final AtomicInteger ai = new AtomicInteger(0); final AtomicInteger ai = new AtomicInteger(0);
final int numberOfKernels=tilesY*tilesX; final int numberOfKernels=tilesY*tilesX;
int indx,dx,dy,tx,ty,li;
final int [] nonOverlapSeq = new int[numberOfKernels];
int [] nextFirstFindex=new int[4];
indx = 0;
li=0;
for (dy=0;dy<2;dy++) for (dx=0;dx<2;dx++) {
for (ty=dy; ty < tilesY; ty+=2) for (tx=dx; tx < tilesX; tx+=2){
nonOverlapSeq[indx++] = ty*tilesX + tx;
}
nextFirstFindex[li++] = indx;
}
final AtomicInteger aStopIndex = new AtomicInteger(0);
final long startTime = System.nanoTime(); final long startTime = System.nanoTime();
for (int ithread = 0; ithread < threads.length; ithread++) { final AtomicInteger tilesFinishedAtomic = new AtomicInteger(1); // first finished will be 1
threads[ithread] = new Thread() { if (updateStatus) IJ.showStatus("Reducing sampling aliases, "+tilesY+" rows, threadsMax="+threadsMax);
public void run() { if (updateStatus) System.out.println("Reducing sampling aliases, "+tilesY+" rows, threadsMax="+threadsMax);
double [][] tile= new double[nChn][debayerParameters.size * debayerParameters.size ]; for (li = 0; li < nextFirstFindex.length; li++){
double [][] both_masks; aStopIndex.set(nextFirstFindex[li]);
float [][] pixels= new float[nChn][]; if (li>0){
int chn,tileY,tileX,i; ai.set(nextFirstFindex[li-1]);
for (chn=0;chn<nChn;chn++) pixels[chn]= (float[]) imageStack.getPixels(chn+1); }
DoubleFHT fht_instance = new DoubleFHT(); // provide DoubleFHT instance to save on initializations (or null) for (int ithread = 0; ithread < threads.length; ithread++) {
showDoubleFloatArrays SDFA_instance=null; // just for debugging? threads[ithread] = new Thread() {
public void run() {
double [][] tile= new double[nChn][debayerParameters.size * debayerParameters.size ];
double [][] both_masks;
float [][] pixels= new float[nChn][];
int chn,tileY,tileX,i;
for (chn=0;chn<nChn;chn++) pixels[chn]= (float[]) imageStack.getPixels(chn+1);
DoubleFHT fht_instance = new DoubleFHT(); // provide DoubleFHT instance to save on initializations (or null)
showDoubleFloatArrays SDFA_instance=null; // just for debugging?
deBayerScissors debayer_instance=new deBayerScissors( debayerParameters.size, // size of the square array, centar is at size/2, size/2, only top half+line will be used deBayerScissors debayer_instance=new deBayerScissors( debayerParameters.size, // size of the square array, centar is at size/2, size/2, only top half+line will be used
debayerParameters.polarStep, // maximal step in pixels on the maxRadius for 1 angular step (i.e. 0.5) debayerParameters.polarStep, // maximal step in pixels on the maxRadius for 1 angular step (i.e. 0.5)
debayerParameters.debayerRelativeWidthGreen, // result green mask mpy by scaled default (diamond) debayerParameters.debayerRelativeWidthGreen, // result green mask mpy by scaled default (diamond)
debayerParameters.debayerRelativeWidthRedblue, // result red/blue mask mpy by scaled default (square) debayerParameters.debayerRelativeWidthRedblue, // result red/blue mask mpy by scaled default (square)
debayerParameters.debayerRelativeWidthRedblueMain, // green mask when applied to red/blue, main (center) debayerParameters.debayerRelativeWidthRedblueMain, // green mask when applied to red/blue, main (center)
debayerParameters.debayerRelativeWidthRedblueClones);// green mask when applied to red/blue, clones debayerParameters.debayerRelativeWidthRedblueClones);// green mask when applied to red/blue, clones
// for (int nTile0 = ai.getAndIncrement(); nTile0 < numberOfKernels; nTile0 = ai.getAndIncrement()) {
for (int nTile = ai.getAndIncrement(); nTile < numberOfKernels; nTile = ai.getAndIncrement()) { for (int nTile0 = ai.getAndIncrement(); nTile0 < aStopIndex.get(); nTile0 = ai.getAndIncrement()) {
tileY = nTile /tilesX;
tileX = nTile % tilesX; int nTile = nonOverlapSeq[nTile0];
if (tileX==0) { tileY = nTile /tilesX;
if (updateStatus) IJ.showStatus("Reducing sampling aliases, row "+(tileY+1)+" of "+tilesY); tileX = nTile % tilesX;
if (globalDebugLevel>2) System.out.println("Reducing sampling aliases, row "+(tileY+1)+" of "+tilesY+" : "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)); if (tileX < 2) {
} int trow=(tileY+((2*(tileY & 1) + (tileX & 1))*tilesY))/4;
if (updateStatus) IJ.showStatus("Reducing sampling aliases, row "+(trow+1)+" of "+tilesY);
// if ((tileY==yTileDebug) && (tileX==xTileDebug)) this.debugLevel=4; // System.out.println("(1)Reducing sampling aliases, row "+(tileY+1)+" of "+tilesY+" ("+nTile+"/"+nTile0+") col="+(tileX+1));
// else this.debugLevel=wasDebugLevel; if (globalDebugLevel>2) System.out.println("Reducing sampling aliases, row "+(trow+1)+" of "+tilesY+" : "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
for (chn=0;chn<nChn;chn++){ }
extractSquareTile( pixels[chn], // source pixel array,
tile[chn], // will be filled, should have correct size before call
slidingWindow, // window (same size as the kernel)
imgWidth, // width of pixels array
tileX*step, // left corner X
tileY*step); // top corner Y
}
/* Scale green channel x0.5 as there are twice more pixels there as in red or blue. Or move it somewhere else and multiply to original range ? */ for (chn=0;chn<nChn;chn++){
for (i=0;i<tile[greenChn].length;i++) tile[greenChn][i]*=0.5; extractSquareTile( pixels[chn], // source pixel array,
if ((tileY==yTileDebug) && (tileX==xTileDebug)) { tile[chn], // will be filled, should have correct size before call
if (SDFA_instance==null) SDFA_instance= new showDoubleFloatArrays(); slidingWindow, // window (same size as the kernel)
SDFA_instance.showArrays (tile.clone(),debayerParameters.size,debayerParameters.size, "x"+(tileX*step)+"_y"+(tileY*step)); imgWidth, // width of pixels array
} tileX*step, // left corner X
for (chn=0;chn<nChn;chn++){ tileY*step); // top corner Y
fht_instance.swapQuadrants(tile[chn]); }
fht_instance.transform(tile[chn]);
}
if ((tileY==yTileDebug) && (tileX==xTileDebug) && (SDFA_instance!=null)) SDFA_instance.showArrays (tile.clone(),debayerParameters.size,debayerParameters.size, "tile-fht");
both_masks= debayer_instance.aliasScissors(tile[greenChn], // fht array for green, will be masked in-place
debayerParameters.debayerThreshold, // no high frequencies - use default uniform filter
debayerParameters.debayerGamma, // power function applied to the amplitudes before generating spectral masks
debayerParameters.debayerBonus, // scale far pixels as (1.0+bonus*r/rmax)
debayerParameters.mainToAlias,// relative main/alias amplitudes to enable lixels (i.e. 0.5 means that if alias is >0.5*main, the pixel will be masked out)
debayerParameters.debayerMaskBlur, // for both masks sigma for gaussian blur of the binary masks (<0 -do not use "scissors")
debayerParameters.debayerUseScissors, // use "scissors", if false - just apply "diamond" ands "square" with DEBAYER_PARAMETERS.debayerRelativeWidthGreen and DEBAYER_PARAMETERS.debayerRelativeWidthRedblue
((tileY==yTileDebug) && (tileX==xTileDebug))?4:1);
// 1); // internal debug level ((this.debugLevel>2) && (yTile==yTile0) && (xTile==xTile0))?3:1;
if ((tileY==yTileDebug) && (tileX==xTileDebug) && (SDFA_instance!=null)) {
SDFA_instance.showArrays (tile.clone(),debayerParameters.size,debayerParameters.size, "A00");
SDFA_instance.showArrays (both_masks.clone(),debayerParameters.size,debayerParameters.size, "masks");
}
if (debayerEnergy!=null) {
debayerEnergy[tileY*tilesX+tileX]=debayer_instance.getMidEnergy();
}
for (chn=0;chn<nChn;chn++) {
tile[chn]=fht_instance.multiply(tile[chn],both_masks[(chn==greenChn)?0:1],false);
fht_instance.inverseTransform(tile[chn]);
fht_instance.swapQuadrants(tile[chn]);
/* accumulate result */
/*This is synchronized method. It is possible to make threads to write to non-overlapping regions of the outPixles, but as the accumulation
* takes just small fraction of severtal FHTs, it should be OK - reasonable number of threads will spread and not "stay in line"
*/
accumulateSquareTile(outPixles[chn], // float pixels array to accumulate tile /* Scale green channel x0.5 as there are twice more pixels there as in red or blue. Or move it somewhere else and multiply to original range ? */
tile[chn], // data to accumulate to the pixels array for (i=0;i<tile[greenChn].length;i++) tile[greenChn][i]*=0.5;
imgWidth, // width of pixels array if ((tileY==yTileDebug) && (tileX==xTileDebug)) {
tileX*step, // left corner X if (SDFA_instance==null) SDFA_instance= new showDoubleFloatArrays();
tileY*step); // top corner Y SDFA_instance.showArrays (tile.clone(),debayerParameters.size,debayerParameters.size, "x"+(tileX*step)+"_y"+(tileY*step));
}
for (chn=0;chn<nChn;chn++){
fht_instance.swapQuadrants(tile[chn]);
fht_instance.transform(tile[chn]);
}
if ((tileY==yTileDebug) && (tileX==xTileDebug) && (SDFA_instance!=null)) SDFA_instance.showArrays (tile.clone(),debayerParameters.size,debayerParameters.size, "tile-fht");
both_masks= debayer_instance.aliasScissors(tile[greenChn], // fht array for green, will be masked in-place
debayerParameters.debayerThreshold, // no high frequencies - use default uniform filter
debayerParameters.debayerGamma, // power function applied to the amplitudes before generating spectral masks
debayerParameters.debayerBonus, // scale far pixels as (1.0+bonus*r/rmax)
debayerParameters.mainToAlias,// relative main/alias amplitudes to enable pixels (i.e. 0.5 means that if alias is >0.5*main, the pixel will be masked out)
debayerParameters.debayerMaskBlur, // for both masks sigma for Gaussian blur of the binary masks (<0 -do not use "scissors")
debayerParameters.debayerUseScissors, // use "scissors", if false - just apply "diamond" ands "square" with DEBAYER_PARAMETERS.debayerRelativeWidthGreen and DEBAYER_PARAMETERS.debayerRelativeWidthRedblue
((tileY==yTileDebug) && (tileX==xTileDebug))?4:1);
// 1); // internal debug level ((this.debugLevel>2) && (yTile==yTile0) && (xTile==xTile0))?3:1;
if ((tileY==yTileDebug) && (tileX==xTileDebug) && (SDFA_instance!=null)) {
SDFA_instance.showArrays (tile.clone(),debayerParameters.size,debayerParameters.size, "A00");
SDFA_instance.showArrays (both_masks.clone(),debayerParameters.size,debayerParameters.size, "masks");
}
if (debayerEnergy!=null) {
debayerEnergy[tileY*tilesX+tileX]=debayer_instance.getMidEnergy();
}
for (chn=0;chn<nChn;chn++) {
tile[chn]=fht_instance.multiply(tile[chn],both_masks[(chn==greenChn)?0:1],false);
fht_instance.inverseTransform(tile[chn]);
fht_instance.swapQuadrants(tile[chn]);
/* accumulate result */
/*This is (now was) a synchronized method. It is possible to make threads to write to non-overlapping regions of the outPixles, but as the accumulation
* takes just small fraction of several FHTs, it should be OK - reasonable number of threads will spread and not "stay in line"
*/
//accumulateSquareTile(
nonSyncAccumulateSquareTile (
outPixles[chn], // float pixels array to accumulate tile
tile[chn], // data to accumulate to the pixels array
imgWidth, // width of pixels array
tileX*step, // left corner X
tileY*step); // top corner Y
}
if ((tileY==yTileDebug) && (tileX==xTileDebug) && (SDFA_instance!=null)) SDFA_instance.showArrays (tile.clone(),debayerParameters.size,debayerParameters.size, "B00");
final int numFinished=tilesFinishedAtomic.getAndIncrement();
// final double dprogr= (1.0+numFinished)/numberOfKernels;
if (numFinished % (numberOfKernels/50+1) == 0) {
// System.out.print(numFinished);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// System.out.println(" --- "+numFinished+"("+numberOfKernels+"): "+dprogr);
IJ.showProgress(numFinished, numberOfKernels);
}
});
}
} }
if ((tileY==yTileDebug) && (tileX==xTileDebug) && (SDFA_instance!=null)) SDFA_instance.showArrays (tile.clone(),debayerParameters.size,debayerParameters.size, "B00");
} }
} };
}; }
} startAndJoin(threads);
startAndJoin(threads); IJ.showProgress(tilesFinishedAtomic.get(), numberOfKernels);
// this.debugLevel=wasDebugLevel; }
// System.out.println("tilesFinishedAtomic.get()="+tilesFinishedAtomic.get()+", numberOfKernels="+numberOfKernels);
if (updateStatus) IJ.showStatus("Reducing sampling aliases DONE");
IJ.showProgress(1.0);
/* prepare result stack to return */ /* prepare result stack to return */
ImageStack outStack=new ImageStack(imgWidth,imgHeight); ImageStack outStack=new ImageStack(imgWidth,imgHeight);
for (chn=0;chn<nChn;chn++) { for (chn=0;chn<nChn;chn++) {
outStack.addSlice(imageStack.getSliceLabel(chn+1), outPixles[chn]); outStack.addSlice(imageStack.getSliceLabel(chn+1), outPixles[chn]);
} }
debayerEnergyWidth= (debayerEnergy!=null)?tilesX:0; // for the image to be displayed externally debayerEnergyWidth= (debayerEnergy!=null)?tilesX:0; // for the image to be displayed externally
// if (debayerParameters.showEnergy) { if (globalDebugLevel>0) System.out.println("Reducing sampling aliases done in "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
// SDFA_INSTANCE.showArrays (debayerEnergy,tilesX,tilesY, "Debayer-Energy");
// }
return outStack; return outStack;
} }
...@@ -273,6 +313,31 @@ public class DebayerScissors { ...@@ -273,6 +313,31 @@ public class DebayerScissors {
} }
} }
} }
void nonSyncAccumulateSquareTile(
float [] pixels, // float pixels array to accumulate tile
double [] tile, // data to accumulate to the pixels array
int width, // width of pixels array
int x0, // left corner X
int y0) { // top corner Y
int length=tile.length;
int size=(int) Math.sqrt(length);
int i,j,x,y;
int height=pixels.length/width;
int index=0;
for (i=0;i<size;i++) {
y=y0+i;
if ((y>=0) && (y<height)) {
index=i*size;
for (j=0;j<size;j++) {
x=x0+j;
if ((x>=0) && (x<width)) pixels[y*width+x]+=tile [index];
index++;
}
}
}
}
synchronized void accumulateSquareTile( synchronized void accumulateSquareTile(
double [] pixels, // float pixels array to accumulate tile double [] pixels, // float pixels array to accumulate tile
double [] tile, // data to accumulate to the pixels array double [] tile, // data to accumulate to the pixels array
......
...@@ -39,7 +39,7 @@ public class DenseCorrespondence { ...@@ -39,7 +39,7 @@ public class DenseCorrespondence {
private void disparitySweepTile ( public void disparitySweepTile ( // never used so far
int tileX, int tileX,
int tileY, int tileY,
CyclopeanTile [][] allCyclopeanMap, CyclopeanTile [][] allCyclopeanMap,
......
...@@ -5989,6 +5989,8 @@ List calibration ...@@ -5989,6 +5989,8 @@ List calibration
imp.setProperty("channel", ""+numSensor); imp.setProperty("channel", ""+numSensor);
imp.setProperty("comment_subcamera", "number of the subcamera with individual IP, starting with 0"); imp.setProperty("comment_subcamera", "number of the subcamera with individual IP, starting with 0");
imp.setProperty("subcamera", ""+camerasInterface.getSubCamera(numSensor)); imp.setProperty("subcamera", ""+camerasInterface.getSubCamera(numSensor));
imp.setProperty("sensor_port",""+camerasInterface.getSensorPort(numSensor));
imp.setProperty("comment_subchannel", "number of the sensor port on a subcamera (0..2)"); imp.setProperty("comment_subchannel", "number of the sensor port on a subcamera (0..2)");
imp.setProperty("subchannel", ""+camerasInterface.getSubChannel(numSensor)); imp.setProperty("subchannel", ""+camerasInterface.getSubChannel(numSensor));
imp.setProperty("comment_entrancePupilForward", "entrance pupil distance from the azimuth/radius/height, outwards in mm"); imp.setProperty("comment_entrancePupilForward", "entrance pupil distance from the azimuth/radius/height, outwards in mm");
......
...@@ -2213,7 +2213,7 @@ public class EyesisAberrations { ...@@ -2213,7 +2213,7 @@ public class EyesisAberrations {
public double [][][][] createPSFMap( public double [][][][] createPSFMap(
final MatchSimulatedPattern commonMatchSimulatedPattern, // to be cloned in threads, using common data final MatchSimulatedPattern commonMatchSimulatedPattern, // to be cloned in threads, using common data
final ImagePlus imp_sel, // linearized Bayer mosaic image form the camera, GR/BG final ImagePlus imp_sel, // linearized Bayer mosaic image from the camera, GR/BG
final int [][][] sampleList, // optional (or null) 2-d array: list of coordinate pairs (2d - to match existent pdfKernelMap structure) final int [][][] sampleList, // optional (or null) 2-d array: list of coordinate pairs (2d - to match existent pdfKernelMap structure)
final double overexposedAllowed, // fraction of pixels OK to be overexposed final double overexposedAllowed, // fraction of pixels OK to be overexposed
final SimulationPattern.SimulParameters simulParameters, final SimulationPattern.SimulParameters simulParameters,
...@@ -2400,7 +2400,7 @@ public class EyesisAberrations { ...@@ -2400,7 +2400,7 @@ public class EyesisAberrations {
}; };
} }
startAndJoin(threads); startAndJoin(threads);
if (globalDebugLevel>1) System.out.println("Threads done at "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)); if (globalDebugLevel>1) System.out.println("Threads done at "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
// globalDebugLevel=saved_globalDebugLevel; // globalDebugLevel=saved_globalDebugLevel;
if (debugLateralShifts) { if (debugLateralShifts) {
boolean [] debugUsedColors=new boolean [debugNumColors]; boolean [] debugUsedColors=new boolean [debugNumColors];
......
...@@ -39,6 +39,8 @@ import ij.process.ImageProcessor; ...@@ -39,6 +39,8 @@ import ij.process.ImageProcessor;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import javax.swing.SwingUtilities;
import loci.common.services.DependencyException; import loci.common.services.DependencyException;
import loci.common.services.ServiceException; import loci.common.services.ServiceException;
import loci.formats.FormatException; import loci.formats.FormatException;
...@@ -1712,92 +1714,153 @@ public class EyesisCorrections { ...@@ -1712,92 +1714,153 @@ public class EyesisCorrections {
final AtomicInteger ai = new AtomicInteger(0); final AtomicInteger ai = new AtomicInteger(0);
final int numberOfKernels= tilesY*tilesX*nChn; final int numberOfKernels= tilesY*tilesX*nChn;
final int numberOfKernelsInChn=tilesY*tilesX; final int numberOfKernelsInChn=tilesY*tilesX;
int ichn,indx,dx,dy,tx,ty,li;
final int [] nonOverlapSeq = new int[numberOfKernels];
int [] nextFirstFindex=new int[16*nChn];
indx = 0;
li=0;
for (ichn=0;ichn<nChn;ichn++) for (dy=0;dy<4;dy++) for (dx=0;dx<4;dx++) {
for (ty=dy; ty < tilesY; ty+=4) for (tx=dx; tx < tilesX; tx+=4){
nonOverlapSeq[indx++] = ichn*numberOfKernelsInChn+ ty*tilesX + tx;
}
nextFirstFindex[li++] = indx;
}
final AtomicInteger aStopIndex = new AtomicInteger(0);
final AtomicInteger tilesFinishedAtomic = new AtomicInteger(1); // first finished will be 1
if (globalDebugLevel>1)
System.out.println("Eyesis_Corrections:convolveStackWithKernelStack :\n"+
"globalDebugLevel="+globalDebugLevel+"\n"+
"imgWidth="+imgWidth+"\n"+
"imgHeight="+imgHeight+"\n"+
"tilesX="+tilesX+"\n"+
"tilesY="+tilesY+"\n"+
"nChn="+nChn+"\n"+
"step="+step+"\n"+
"size="+size+"\n"+
"kernelSize="+kernelSize+"\n"+
"kernelWidth="+kernelWidth+"\n"+
"kernelNumHor="+kernelNumHor+"\n"+
"numberOfKernelsInChn="+numberOfKernelsInChn+"\n");
if (updateStatus) IJ.showStatus("Convolving image with kernels, "+nChn+" channels, "+tilesY+" rows");
final long startTime = System.nanoTime(); final long startTime = System.nanoTime();
for (int ithread = 0; ithread < threads.length; ithread++) { for (li = 0; li < nextFirstFindex.length; li++){
threads[ithread] = new Thread() { aStopIndex.set(nextFirstFindex[li]);
public void run() { if (li>0){
float [] pixels=null; // will be initialized at first use ai.set(nextFirstFindex[li-1]);
float [] kernelPixels=null; // will be initialized at first use }
double [] kernel= new double[kernelSize*kernelSize]; // System.out.println("\n=== nextFirstFindex["+li+"] =" + nextFirstFindex[li]+" === ");
double [] inTile= new double[kernelSize*kernelSize]; for (int ithread = 0; ithread < threads.length; ithread++) {
double [] outTile= new double[size * size]; threads[ithread] = new Thread() {
double [] doubleKernel= new double[size * size]; public void run() {
int chn,tileY,tileX; float [] pixels=null; // will be initialized at first use
int chn0=-1; float [] kernelPixels=null; // will be initialized at first use
// double debug_sum; double [] kernel= new double[kernelSize*kernelSize];
// int i; double [] inTile= new double[kernelSize*kernelSize];
DoubleFHT fht_instance =new DoubleFHT(); // provide DoubleFHT instance to save on initializations (or null) double [] outTile= new double[size * size];
for (int nTile = ai.getAndIncrement(); nTile < numberOfKernels; nTile = ai.getAndIncrement()) { double [] doubleKernel= new double[size * size];
chn=nTile/numberOfKernelsInChn; int chn,tileY,tileX;
tileY =(nTile % numberOfKernelsInChn)/tilesX; int chn0=-1;
tileX = nTile % tilesX; // double debug_sum;
if (tileX==0) { // int i;
if (updateStatus) IJ.showStatus("Convolving image with kernels, channel "+(chn+1)+" of "+nChn+", row "+(tileY+1)+" of "+tilesY); DoubleFHT fht_instance =new DoubleFHT(); // provide DoubleFHT instance to save on initializations (or null)
if (globalDebugLevel>2) System.out.println("Processing kernels, channel "+(chn+1)+" of "+nChn+", row "+(tileY+1)+" of "+tilesY+" : "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)); // for (int nTile0 = ai.getAndIncrement(); nTile0 < numberOfKernels; nTile0 = ai.getAndIncrement()) {
} for (int nTile0 = ai.getAndIncrement(); nTile0 < aStopIndex.get(); nTile0 = ai.getAndIncrement()) {
//aStopIndex
if (chn!=chn0) { int nTile = nonOverlapSeq[nTile0];
pixels= (float[]) imageStack.getPixels(chn+1); chn=nTile/numberOfKernelsInChn;
kernelPixels=(float[]) kernelStack.getPixels(chn+1); tileY =(nTile % numberOfKernelsInChn)/tilesX;
chn0=chn; tileX = nTile % tilesX;
if (tileX < 4) {
int trow=(tileY+ ((tileY & 3) * tilesY))/4;
if (updateStatus) IJ.showStatus("Convolving image with kernels, channel "+(chn+1)+" of "+nChn+", row "+(trow+1)+" of "+tilesY);
if (globalDebugLevel>2) System.out.println("Processing kernels, channel "+(chn+1)+" of "+nChn+", row "+(trow+1)+" of "+tilesY+" : "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
}
if (chn!=chn0) {
pixels= (float[]) imageStack.getPixels(chn+1);
kernelPixels=(float[]) kernelStack.getPixels(chn+1);
chn0=chn;
}
/* Read source image tile */
extractSquareTile( pixels, // source pixel array,
inTile, // will be filled, should have correct size before call
slidingWindow, // window (same size as the kernel)
imgWidth, // width of pixels array
tileX*step, // left corner X
tileY*step); // top corner Y
/* zero pad twice the original size*/
outTile=extendFFTInputTo (inTile, size);
/* FHT transform of the source image data*/
fht_instance.swapQuadrants(outTile);
fht_instance.transform( outTile);
/* read convolution kernel */
extractOneKernel(kernelPixels, // array of combined square kernels, each
kernel, // will be filled, should have correct size before call
kernelNumHor, // number of kernels in a row
//tileX*kernelSize, // horizontal number of kernel to extract
//tileY*kernelSize); // vertical number of kernel to extract
tileX, // horizontal number of kernel to extract
tileY); // vertical number of kernel to extract
/* zero pad twice the original size*/
doubleKernel=extendFFTInputTo (kernel, size);
// debug_sum=0;
// for (i=0;i<doubleKernel.length;i++) debug_sum+=doubleKernel[i];
// if (globalDebugLevel>1) System.out.println("kernel sum="+debug_sum);
//if ((tileY==tilesY/2) && (tileX==tilesX/2)) SDFA_INSTANCE.showArrays(doubleKernel,size,size, "doubleKernel-"+chn);
/* FHT transform of the kernel */
fht_instance.swapQuadrants(doubleKernel);
fht_instance.transform( doubleKernel);
/* multiply in frequency domain */
outTile= fht_instance.multiply(outTile, doubleKernel, false);
/* FHT inverse transform of the product - back to space domain */
fht_instance.inverseTransform(outTile);
fht_instance.swapQuadrants(outTile);
/* accumulate result */
//if ((tileY==tilesY/2) && (tileX==tilesX/2)) SDFA_INSTANCE.showArrays(outTile,size,size, "out-"+chn);
/*This is synchronized method. It is possible to make threads to write to non-overlapping regions of the outPixels, but as the accumulation
* takes just small fraction of several FHTs, it should be OK - reasonable number of threads will spread and not "stay in line"
*/
// Add smart synchronization - wait only if is too far ahead. First test - no synchronization at all
//accumulateSquareTile(
// System.out.print(tileY+":"+tileX+"/"+chn+"("+nTile0+"/"+nTile+") ");
// if (tileX < 4)System.out.println();
nonSyncAccumulateSquareTile(
outPixels[chn], // float pixels array to accumulate tile
outTile, // data to accumulate to the pixels array
imgWidth, // width of pixels array
(tileX-1)*step, // left corner X
(tileY-1)*step); // top corner Y
final int numFinished=tilesFinishedAtomic.getAndIncrement();
if (numFinished % (numberOfKernels/100+1) == 0) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
IJ.showProgress(numFinished,numberOfKernels);
}
});
}
//numberOfKernels
} }
/* Read source image tile */
extractSquareTile( pixels, // source pixel array,
inTile, // will be filled, should have correct size before call
slidingWindow, // window (same size as the kernel)
imgWidth, // width of pixels array
tileX*step, // left corner X
tileY*step); // top corner Y
/* zero pad twice the original size*/
outTile=extendFFTInputTo (inTile, size);
/* FHT transform of the source image data*/
fht_instance.swapQuadrants(outTile);
fht_instance.transform( outTile);
/* read convolution kernel */
extractOneKernel(kernelPixels, // array of combined square kernels, each
kernel, // will be filled, should have correct size before call
kernelNumHor, // number of kernels in a row
//tileX*kernelSize, // horizontal number of kernel to extract
//tileY*kernelSize); // vertical number of kernel to extract
tileX, // horizontal number of kernel to extract
tileY); // vertical number of kernel to extract
/* zero pad twice the original size*/
doubleKernel=extendFFTInputTo (kernel, size);
// debug_sum=0;
// for (i=0;i<doubleKernel.length;i++) debug_sum+=doubleKernel[i];
// if (globalDebugLevel>1) System.out.println("kernel sum="+debug_sum);
//if ((tileY==tilesY/2) && (tileX==tilesX/2)) SDFA_INSTANCE.showArrays(doubleKernel,size,size, "doubleKernel-"+chn);
/* FHT transform of the kernel */
fht_instance.swapQuadrants(doubleKernel);
fht_instance.transform( doubleKernel);
/* multiply in frequency domain */
outTile= fht_instance.multiply(outTile, doubleKernel, false);
/* FHT inverse transform of the product - back to space domain */
fht_instance.inverseTransform(outTile);
fht_instance.swapQuadrants(outTile);
/* accumulate result */
//if ((tileY==tilesY/2) && (tileX==tilesX/2)) SDFA_INSTANCE.showArrays(outTile,size,size, "out-"+chn);
/*This is synchronized method. It is possible to make threads to write to non-overlapping regions of the outPixels, but as the accumulation
* takes just small fraction of severtal FHTs, it should be OK - reasonable number of threads will spread and not "stay in line"
*/
accumulateSquareTile(outPixels[chn], // float pixels array to accumulate tile
outTile, // data to accumulate to the pixels array
imgWidth, // width of pixels array
(tileX-1)*step, // left corner X
(tileY-1)*step); // top corner Y
} }
} };
}; }
} startAndJoin(threads);
startAndJoin(threads); }
if (globalDebugLevel > 1) System.out.println("Threads done at "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)); if (updateStatus) IJ.showStatus("Convolution DONE");
if (globalDebugLevel > 1) System.out.println("Threads done in "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
IJ.showProgress(1.0);
/* prepare result stack to return */ /* prepare result stack to return */
ImageStack outStack=new ImageStack(imgWidth,imgHeight); ImageStack outStack=new ImageStack(imgWidth,imgHeight);
for (i=0;i<nChn;i++) { for (i=0;i<nChn;i++) {
outStack.addSlice(imageStack.getSliceLabel(i+1), outPixels[i]); outStack.addSlice(imageStack.getSliceLabel(i+1), outPixels[i]);
} }
if (globalDebugLevel > 0) System.out.println("Convolution done in "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
return outStack; return outStack;
} }
/* Adds zero pixels around the image, "extending canvas" */ /* Adds zero pixels around the image, "extending canvas" */
...@@ -1928,6 +1991,32 @@ public class EyesisCorrections { ...@@ -1928,6 +1991,32 @@ public class EyesisCorrections {
} }
} }
} }
void nonSyncAccumulateSquareTile(
float [] pixels, // float pixels array to accumulate tile
double [] tile, // data to accumulate to the pixels array
int width, // width of pixels array
int x0, // left corner X
int y0) { // top corner Y
int length=tile.length;
int size=(int) Math.sqrt(length);
int i,j,x,y;
int height=pixels.length/width;
int index=0;
for (i=0;i<size;i++) {
y=y0+i;
if ((y>=0) && (y<height)) {
index=i*size;
for (j=0;j<size;j++) {
x=x0+j;
if ((x>=0) && (x<width)) pixels[y*width+x]+=tile [index];
index++;
}
}
}
}
synchronized void accumulateSquareTile( synchronized void accumulateSquareTile(
double [] pixels, // float pixels array to accumulate tile double [] pixels, // float pixels array to accumulate tile
double [] tile, // data to accumulate to the pixels array double [] tile, // data to accumulate to the pixels array
......
...@@ -3464,7 +3464,7 @@ private Panel panel1,panel2,panel3,panel4,panel5,panel5a, panel6,panel7,panelPos ...@@ -3464,7 +3464,7 @@ private Panel panel1,panel2,panel3,panel4,panel5,panel5a, panel6,panel7,panelPos
continue; continue;
} }
convolutionKernelStack=imp_kernels.getStack(); convolutionKernelStack=imp_kernels.getStack();
if (DEBUG_LEVEL>1) System.out.println("Using kernel stack "+kernelPath+" for convolution with "+result[nFile][nChn][nSubChn].getTitle()); if (DEBUG_LEVEL>1) System.out.println("(1)Using kernel stack "+kernelPath+" for convolution with "+result[nFile][nChn][nSubChn].getTitle());
stack_d= convolveStackWithKernelStack( stack_d= convolveStackWithKernelStack(
stack, // stack with 3 colors/slices with the image stack, // stack with 3 colors/slices with the image
convolutionKernelStack, // stack with 3 colors/slices convolution kernels convolutionKernelStack, // stack with 3 colors/slices convolution kernels
...@@ -3492,7 +3492,7 @@ private Panel panel1,panel2,panel3,panel4,panel5,panel5a, panel6,panel7,panelPos ...@@ -3492,7 +3492,7 @@ private Panel panel1,panel2,panel3,panel4,panel5,panel5a, panel6,panel7,panelPos
continue; continue;
} }
convolutionKernelStack=imp_kernels.getStack(); convolutionKernelStack=imp_kernels.getStack();
if (DEBUG_LEVEL>1) System.out.println("Using Gaussian stack "+kernelPath+" for convolution with "+result[nFile][nChn][nSubChn].getTitle()); if (DEBUG_LEVEL>1) System.out.println("(2)Using Gaussian stack "+kernelPath+" for convolution with "+result[nFile][nChn][nSubChn].getTitle());
stack_g= convolveStackWithKernelStack( stack_g= convolveStackWithKernelStack(
stack, // stack with 3 colors/slices with the image stack, // stack with 3 colors/slices with the image
convolutionKernelStack, // stack with 3 colors/slices convolution kernels convolutionKernelStack, // stack with 3 colors/slices convolution kernels
...@@ -3592,7 +3592,7 @@ private Panel panel1,panel2,panel3,panel4,panel5,panel5a, panel6,panel7,panelPos ...@@ -3592,7 +3592,7 @@ private Panel panel1,panel2,panel3,panel4,panel5,panel5a, panel6,panel7,panelPos
continue; continue;
} }
convolutionKernelStack=imp_kernels.getStack(); convolutionKernelStack=imp_kernels.getStack();
if (DEBUG_LEVEL>1) System.out.println("Using Gaussian stack "+kernelPath+" for convolution with "+result[nFile][nChn][nSubChn].getTitle()); if (DEBUG_LEVEL>1) System.out.println("(3)Using Gaussian stack "+kernelPath+" for convolution with "+result[nFile][nChn][nSubChn].getTitle());
stack_g= convolveStackWithKernelStack( stack_g= convolveStackWithKernelStack(
stack, // stack with 3 colors/slices with the image stack, // stack with 3 colors/slices with the image
convolutionKernelStack, // stack with 3 colors/slices convolution kernels convolutionKernelStack, // stack with 3 colors/slices convolution kernels
...@@ -3977,7 +3977,6 @@ private Panel panel1,panel2,panel3,panel4,panel5,panel5a, panel6,panel7,panelPos ...@@ -3977,7 +3977,6 @@ private Panel panel1,panel2,panel3,panel4,panel5,panel5a, panel6,panel7,panelPos
final int tilesY=imgHeight/step-1; // vertical number of overlapping tiles in the source image (should be expanded from the registerd one by "step" in each direction) final int tilesY=imgHeight/step-1; // vertical number of overlapping tiles in the source image (should be expanded from the registerd one by "step" in each direction)
final int kernelWidth=kernelStack.getWidth(); final int kernelWidth=kernelStack.getWidth();
final int kernelNumHor=kernelWidth/(size/2); final int kernelNumHor=kernelWidth/(size/2);
final int nChn=imageStack.getSize(); final int nChn=imageStack.getSize();
final float [][] outPixels=new float[nChn][length]; // GLOBAL same as input final float [][] outPixels=new float[nChn][length]; // GLOBAL same as input
// float [][] outPixels=new float[nChn][length]; // same as input // float [][] outPixels=new float[nChn][length]; // same as input
...@@ -3988,6 +3987,21 @@ private Panel panel1,panel2,panel3,panel4,panel5,panel5a, panel6,panel7,panelPos ...@@ -3988,6 +3987,21 @@ private Panel panel1,panel2,panel3,panel4,panel5,panel5a, panel6,panel7,panelPos
final AtomicInteger ai = new AtomicInteger(0); final AtomicInteger ai = new AtomicInteger(0);
final int numberOfKernels= tilesY*tilesX*nChn; final int numberOfKernels= tilesY*tilesX*nChn;
final int numberOfKernelsInChn=tilesY*tilesX; final int numberOfKernelsInChn=tilesY*tilesX;
if (MASTER_DEBUG_LEVEL>1)
System.out.println("Eyesis_Correction:convolveStackWithKernelStack :\n"+
"MASTER_DEBUG_LEVEL="+MASTER_DEBUG_LEVEL+"\n"+
"imgWidth="+imgWidth+"\n"+
"imgHeight="+imgHeight+"\n"+
"tilesX="+tilesX+"\n"+
"tilesY="+tilesY+"\n"+
"step="+step+"\n"+
"kernelSize="+kernelSize+"\n"+
"tilesX="+tilesX+"\n"+
"tilesY="+tilesY+"\n"+
"kernelWidth="+kernelWidth+"\n"+
"kernelNumHor="+kernelNumHor+"\n"+
"numberOfKernelsInChn="+numberOfKernelsInChn+"\n");
final long startTime = System.nanoTime(); final long startTime = System.nanoTime();
for (int ithread = 0; ithread < threads.length; ithread++) { for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() { threads[ithread] = new Thread() {
...@@ -4153,8 +4167,8 @@ private Panel panel1,panel2,panel3,panel4,panel5,panel5a, panel6,panel7,panelPos ...@@ -4153,8 +4167,8 @@ private Panel panel1,panel2,panel3,panel4,panel5,panel5a, panel6,panel7,panelPos
tileY = nTile /tilesX; tileY = nTile /tilesX;
tileX = nTile % tilesX; tileX = nTile % tilesX;
if (tileX==0) { if (tileX==0) {
if (updateStatus) IJ.showStatus("Reducing sampling aliases, row "+(tileY+1)+" of "+tilesY); if (updateStatus) IJ.showStatus("(2)Reducing sampling aliases, row "+(tileY+1)+" of "+tilesY);
if (MASTER_DEBUG_LEVEL>2) System.out.println("Reducing sampling aliases, row "+(tileY+1)+" of "+tilesY+" : "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)); if (MASTER_DEBUG_LEVEL>1) System.out.println("(2)Reducing sampling aliases, row "+(tileY+1)+" of "+tilesY+" : "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
} }
if ((tileY==yTileDebug) && (tileX==xTileDebug)) DEBUG_LEVEL=4; if ((tileY==yTileDebug) && (tileX==xTileDebug)) DEBUG_LEVEL=4;
......
...@@ -346,6 +346,7 @@ public class JP46_Reader_camera implements PlugIn, ActionListener { ...@@ -346,6 +346,7 @@ public class JP46_Reader_camera implements PlugIn, ActionListener {
boolean showDemux=showImage && demux; boolean showDemux=showImage && demux;
if (demux) showImage=false; if (demux) showImage=false;
double [] xtraExif=new double[1]; // ExposureTime double [] xtraExif=new double[1]; // ExposureTime
// System.out.println("imp_src is "+((imp_src!=null)?"not ":"")+"null"); // System.out.println("imp_src is "+((imp_src!=null)?"not ":"")+"null");
try { try {
......
...@@ -25,10 +25,14 @@ ...@@ -25,10 +25,14 @@
** **
*/ */
import java.awt.Point;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet; import java.util.BitSet;
import java.util.Collections;
import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
...@@ -135,10 +139,19 @@ public class PixelMapping { ...@@ -135,10 +139,19 @@ public class PixelMapping {
if ((channel<0) || (channel>=this.sensors.length)) return -1; if ((channel<0) || (channel>=this.sensors.length)) return -1;
return this.sensors[channel].getSubCamera(); return this.sensors[channel].getSubCamera();
} }
/*
public int getSensorPort(int channel ){
if ((channel<0) || (channel>=this.sensors.length)) return -1;
return this.sensors[channel].getSensorPort();
}
*/
public boolean isChannelAvailable(int channel){ public boolean isChannelAvailable(int channel){
return (this.sensors != null) && (channel>=0) && (channel<this.sensors.length) && (this.sensors[channel]!=null); return (this.sensors != null) && (channel>=0) && (channel<this.sensors.length) && (this.sensors[channel]!=null);
} }
/*
public int [] channelsForSubCamera(int subCamera){ public int [] channelsForSubCamera(int subCamera){
if (this.sensors == null) return null; if (this.sensors == null) return null;
...@@ -149,6 +162,50 @@ public class PixelMapping { ...@@ -149,6 +162,50 @@ public class PixelMapping {
for (int i=0;i<this.sensors.length;i++) if ((this.sensors[i]!=null) &&(this.sensors[i].subcamera==subCamera)) result[numChannels++]=i; for (int i=0;i<this.sensors.length;i++) if ((this.sensors[i]!=null) &&(this.sensors[i].subcamera==subCamera)) result[numChannels++]=i;
return result; return result;
} }
*/
// Updating for nc393. subCamera here is 0..9 for Eyesis4pi393 - 0-based index of the file, so it combines physical camera (separate IP)
// as stored in "subcamera" field of the calibration file and "sensor_port". sensor_port may start from non-0, so we need to count all combinations
public int [] channelsForSubCamera(int subCamera){
// ArrayList<ArrayList<ArrayList<Integer>>> camera_IPs = new ArrayList<ArrayList<ArrayList<Integer>>>();
ArrayList<Point> cam_port = new ArrayList<Point>();
for (int i=0;i<this.sensors.length;i++) if (this.sensors[i]!=null) {
Point cp = new Point(this.sensors[i].subcamera, this.sensors[i].sensor_port);
if (!cam_port.contains(cp)){
cam_port.add(cp);
}
}
Point [] cam_port_arr = cam_port.toArray(new Point[0]);
Arrays.sort(cam_port_arr, new Comparator<Point>() {
@Override
public int compare(Point o1, Point o2) {
return (o1.x>o2.x)? 1:((o1.x < o2.x)?-1:(o1.y > o2.y)? 1:((o1.y < o2.y)?-1:0));
}
});
// for (int i=0; i<cam_port_arr.length;i++){
// System.out.println("----- physical camera #"+cam_port_arr[i].x+", sensor_port="+cam_port_arr[i].y);
// }
System.out.println("----- This filename subcamera "+subCamera+": physical camera "+cam_port_arr[subCamera].x+", sensor_port "+cam_port_arr[subCamera].y);
if (subCamera >= cam_port_arr.length) {
System.out.println("Error: Subcamera "+subCamera+" > that total namera of sensor ports in the system = "+cam_port_arr.length);
return null;
}
if (this.sensors == null) return null;
int numChannels=0;
for (int i=0;i<this.sensors.length;i++) if (this.sensors[i]!=null) {
if (new Point(this.sensors[i].subcamera, this.sensors[i].sensor_port).equals(cam_port_arr[subCamera])) numChannels++;
}
int [] result=new int [numChannels];
numChannels=0;
for (int i=0;i<this.sensors.length;i++) if (this.sensors[i]!=null){
if (new Point(this.sensors[i].subcamera, this.sensors[i].sensor_port).equals(cam_port_arr[subCamera])) result[numChannels++]=i;
}
return result;
}
public void removeChannel(int channel){ public void removeChannel(int channel){
if ((this.sensors != null) && (channel>=0) && (channel<this.sensors.length)) this.sensors[channel]=null; if ((this.sensors != null) && (channel>=0) && (channel<this.sensors.length)) this.sensors[channel]=null;
} }
...@@ -9403,7 +9460,8 @@ public class PixelMapping { ...@@ -9403,7 +9460,8 @@ public class PixelMapping {
private BitSet innerMask=null; private BitSet innerMask=null;
private int []borderMask=null; private int []borderMask=null;
public int getNumberOfPlanes(){return this.maximums.length;} public int getNumberOfPlanes(){return this.maximums.length;}
public int getForegroundPlane(){return this.foregroundIndex;} @SuppressWarnings("unused")
public int getForegroundPlane(){return this.foregroundIndex;}
public double getPlaneDisparity (int plane){return this.maximums[plane][0];} public double getPlaneDisparity (int plane){return this.maximums[plane][0];}
public void setPlaneDisparity (double disparity, int plane){this.maximums[plane][0]=disparity;} public void setPlaneDisparity (double disparity, int plane){this.maximums[plane][0]=disparity;}
public double getPlaneStrength (int plane){return this.maximums[plane][1];} public double getPlaneStrength (int plane){return this.maximums[plane][1];}
...@@ -9441,14 +9499,16 @@ public class PixelMapping { ...@@ -9441,14 +9499,16 @@ public class PixelMapping {
this.auxData=new float[n][]; this.auxData=new float[n][];
for (int i=0;i<n;i++) this.auxData[i]=null; for (int i=0;i<n;i++) this.auxData[i]=null;
} }
public void resetAux(){ @SuppressWarnings("unused")
public void resetAux(){
this.auxData=null; this.auxData=null;
} }
public void setAux(int n, float [] data){ public void setAux(int n, float [] data){
if (this.auxData==null) initAux(n+1); if (this.auxData==null) initAux(n+1);
this.auxData[n]=data; this.auxData[n]=data;
} }
public float [][] getAux (){ @SuppressWarnings("unused")
public float [][] getAux (){
return this.auxData; return this.auxData;
} }
public float [] getAux (int n){ public float [] getAux (int n){
...@@ -9460,17 +9520,21 @@ public class PixelMapping { ...@@ -9460,17 +9520,21 @@ public class PixelMapping {
this.likely=new float[this.numPlanes][]; this.likely=new float[this.numPlanes][];
for (int i=0;i<this.numPlanes;i++) this.likely[i]=null; for (int i=0;i<this.numPlanes;i++) this.likely[i]=null;
} }
public void resetLikely(){ @SuppressWarnings("unused")
public void resetLikely(){
this.likely=null; this.likely=null;
} }
public void setLikely(int n, float [] data){ @SuppressWarnings("unused")
public void setLikely(int n, float [] data){
if (this.likely==null) initLikely(); if (this.likely==null) initLikely();
this.likely[n]=data; this.likely[n]=data;
} }
public float [][] getLikely (){ @SuppressWarnings("unused")
public float [][] getLikely (){
return this.likely; return this.likely;
} }
public float [] getLikely (int n){ @SuppressWarnings("unused")
public float [] getLikely (int n){
if ((this.likely==null) || (this.likely.length<=n)) return null; if ((this.likely==null) || (this.likely.length<=n)) return null;
return this.likely[n]; return this.likely[n];
} }
...@@ -9479,17 +9543,21 @@ public class PixelMapping { ...@@ -9479,17 +9543,21 @@ public class PixelMapping {
this.unlikely=new float[this.numPlanes][]; this.unlikely=new float[this.numPlanes][];
for (int i=0;i<this.numPlanes;i++) this.unlikely[i]=null; for (int i=0;i<this.numPlanes;i++) this.unlikely[i]=null;
} }
public void resetUnlikely(){ @SuppressWarnings("unused")
public void resetUnlikely(){
this.unlikely=null; this.unlikely=null;
} }
public void setUnlikely(int n, float [] data){ @SuppressWarnings("unused")
public void setUnlikely(int n, float [] data){
if (this.unlikely==null) initUnlikely(); if (this.unlikely==null) initUnlikely();
this.unlikely[n]=data; this.unlikely[n]=data;
} }
public float [][] getUnlikely(){ @SuppressWarnings("unused")
public float [][] getUnlikely(){
return this.unlikely; return this.unlikely;
} }
public float [] getUnlikely(int n){ @SuppressWarnings("unused")
public float [] getUnlikely(int n){
if ((this.unlikely==null) || (this.unlikely.length<=n)) return null; if ((this.unlikely==null) || (this.unlikely.length<=n)) return null;
return this.unlikely[n]; return this.unlikely[n];
} }
...@@ -9577,7 +9645,8 @@ public class PixelMapping { ...@@ -9577,7 +9645,8 @@ public class PixelMapping {
* @param disparityTolerance - consider "this" as being withing disparityTolerance of disparity. NaN - do not filter by this * @param disparityTolerance - consider "this" as being withing disparityTolerance of disparity. NaN - do not filter by this
* @return * @return
*/ */
public boolean [] getEnabledNonOccluded( @SuppressWarnings("unused")
public boolean [] getEnabledNonOccluded(
double disparityFG, double disparityFG,
double disparity, double disparity,
double disparityTolerance){ double disparityTolerance){
...@@ -15527,6 +15596,7 @@ public class PixelMapping { ...@@ -15527,6 +15596,7 @@ public class PixelMapping {
public int channel= -1; public int channel= -1;
public int subcamera= -1; public int subcamera= -1;
public int subchannel=-1; public int subchannel=-1;
public int sensor_port=-1;
// TODO: add serial# (and temperature?) // TODO: add serial# (and temperature?)
public double azimuth; // azimuth of the lens entrance pupil center, degrees, clockwise looking from top public double azimuth; // azimuth of the lens entrance pupil center, degrees, clockwise looking from top
public double radius; // mm, distance from the rotation axis public double radius; // mm, distance from the rotation axis
...@@ -16094,6 +16164,9 @@ public class PixelMapping { ...@@ -16094,6 +16164,9 @@ public class PixelMapping {
public int getChannel(){return this.channel;} public int getChannel(){return this.channel;}
public int getSubChannel(){return this.subchannel;} public int getSubChannel(){return this.subchannel;}
public int getSubCamera(){return this.subcamera;} public int getSubCamera(){return this.subcamera;}
public int getSensorPort(){return this.sensor_port;}
public void setSensorDataFromImageStack(ImagePlus imp){ public void setSensorDataFromImageStack(ImagePlus imp){
// int corrX=0,corrY=1,corrMask=2; // int corrX=0,corrY=1,corrMask=2;
if (imp == null){ if (imp == null){
...@@ -16170,6 +16243,9 @@ public class PixelMapping { ...@@ -16170,6 +16243,9 @@ public class PixelMapping {
// older files do not have these properties // older files do not have these properties
if (imp.getProperty("subcamera")!=null) this.subcamera= Integer.parseInt((String) imp.getProperty("subcamera")); if (imp.getProperty("subcamera")!=null) this.subcamera= Integer.parseInt((String) imp.getProperty("subcamera"));
if (imp.getProperty("subchannel")!=null) this.subchannel=Integer.parseInt((String) imp.getProperty("subchannel")); if (imp.getProperty("subchannel")!=null) this.subchannel=Integer.parseInt((String) imp.getProperty("subchannel"));
if (imp.getProperty("sensor_port")!=null) this.sensor_port=Integer.parseInt((String) imp.getProperty("sensor_port"));
// now read the calibration data and mask // now read the calibration data and mask
this.pixelCorrection=null; this.pixelCorrection=null;
......
/** /**
** -----------------------------------------------------------------------------** ** -----------------------------------------------------------------------------**
** deBayerScissors.java ** deBayerScissors.java
** **
** Frequency-domain de-mosoaic filters generation ** Frequency-domain de-mosoaic filters generation
** **
** **
** Copyright (C) 2010 Elphel, Inc. ** Copyright (C) 2010 Elphel, Inc.
** **
** -----------------------------------------------------------------------------** ** -----------------------------------------------------------------------------**
** **
** focus_tuning.java is free software: you can redistribute it and/or modify ** focus_tuning.java is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by ** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or ** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version. ** (at your option) any later version.
** **
** This program is distributed in the hope that it will be useful, ** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of ** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details. ** GNU General Public License for more details.
** **
** You should have received a copy of the GNU General Public License ** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
** -----------------------------------------------------------------------------** ** -----------------------------------------------------------------------------**
** **
*/ */
import ij.process.*; import ij.process.*;
import ij.plugin.filter.GaussianBlur; import ij.plugin.filter.GaussianBlur;
import java.util.HashSet; import java.util.HashSet;
public class deBayerScissors { public class deBayerScissors {
private PolarSpectrums pol_instace=null; private PolarSpectrums pol_instace=null;
private double [][][] lopass=null; private double [][][] lopass=null;
private int size; private int size;
private double lastMidEnergy; // last midrange spectral energy private double lastMidEnergy; // last midrange spectral energy
private showDoubleFloatArrays SDFA_instance; // just for debugging? private showDoubleFloatArrays SDFA_instance; // just for debugging?
private DoubleFHT fht_instance; private DoubleFHT fht_instance;
private int [][] aliasMapRedBlue={
public double getMidEnergy() {return lastMidEnergy; } // instead of the DOUBLE_DEBUG_RESULT {-2,-2},{-2,-1},{-2,0},{-2,1},
public deBayerScissors( {-1,-2},{-1,-1},{-1,0},{-1,1},
int isize, // size of the square array, centar is at size/2, size/2, only top half+line will be used { 0,-2},{ 0,-1}, { 0,1},
double polarStep, // maximal step in pixels on the maxRadius for 1 angular step (i.e. 0.5) { 1,-2},{ 1,-1},{ 1,0},{ 1,1}};
double debayer_width_green, // result green mask mpy by scaled default (diamond) private int [][][][] speedTable = null;
double debayer_width_redblue, // result red/blue mask mpy by scaled default (square)
double debayer_width_redblue_main, // green mask when applied to red/blue, main (center) public double getMidEnergy() {return lastMidEnergy; } // instead of the DOUBLE_DEBUG_RESULT
double debayer_width_redblue_clones){// green mask when applied to red/blue, clones public deBayerScissors(
size=isize; int isize, // size of the square array, centar is at size/2, size/2, only top half+line will be used
fht_instance= new DoubleFHT(); double polarStep, // maximal step in pixels on the maxRadius for 1 angular step (i.e. 0.5)
SDFA_instance= new showDoubleFloatArrays(); double debayer_width_green, // result green mask mpy by scaled default (diamond)
pol_instace=new PolarSpectrums(size, // size of the square array, centar is at size/2, size/2, only top half+line will be used double debayer_width_redblue, // result red/blue mask mpy by scaled default (square)
Math.PI, double debayer_width_redblue_main, // green mask when applied to red/blue, main (center)
size/2-2, // width of the polar array - should be <= size/2-2 double debayer_width_redblue_clones){// green mask when applied to red/blue, clones
polarStep, //0.5, //0.75, //2.0, //0.5, // maximal step in pixels on the maxRadius for 1 angular step (i.e. 0.5) size=isize;
4);// angular symmetry - 0- none,1 - pi corresponds to integer, 2 - pi/2 corresponds to integer, n - pi/n corresponds to integer angular step fht_instance= new DoubleFHT();
SDFA_instance= new showDoubleFloatArrays();
lopass= createAliasFilters (debayer_width_green, // result green mask mpy by scaled default (diamond) pol_instace=new PolarSpectrums(size, // size of the square array, centar is at size/2, size/2, only top half+line will be used
debayer_width_redblue, // result red/blue mask mpy by scaled default (square) Math.PI,
debayer_width_redblue_main, // green mask when applied to red/blue, main (center) size/2-2, // width of the polar array - should be <= size/2-2
debayer_width_redblue_clones, // green mask when applied to red/blue, clones polarStep, //0.5, //0.75, //2.0, //0.5, // maximal step in pixels on the maxRadius for 1 angular step (i.e. 0.5)
size, // side of the square 4);// angular symmetry - 0- none,1 - pi corresponds to integer, 2 - pi/2 corresponds to integer, n - pi/n corresponds to integer angular step
4); // should be 4 now
} lopass= createAliasFilters (debayer_width_green, // result green mask mpy by scaled default (diamond)
debayer_width_redblue, // result red/blue mask mpy by scaled default (square)
/* returns 2 masks (0:0 in the top left corner, match fht) [0] - for greens, [1] - for red/blue */ debayer_width_redblue_main, // green mask when applied to red/blue, main (center)
/* Possible improvements: - 1 make the initial green mask (or actually "fan"-like image) to have sharper ends. debayer_width_redblue_clones, // green mask when applied to red/blue, clones
2. detect periodic (line of spots) on the spectrum aplitudes (corresponds to thin lines) and use this size, // side of the square
4); // should be 4 now
int hsize=size/2;
int subpixel=4; // hardwired - when changing it will need to change alias maps
int aliasX=size/subpixel;
speedTable = new int [hsize+1][size][aliasMapRedBlue.length][3];
int i,j,nAlias,x,y;
for (i = 0;i <= hsize;i++) for (j = 0;j < size;j++) {
speedTable[i][j][0][0] = i*size+j;
speedTable[i][j][0][1] = ((size-i) % size) * size + ((size-j) % size);
for(nAlias=0;nAlias<aliasMapRedBlue.length; nAlias++) {
y = (i-aliasX*aliasMapRedBlue[nAlias][0]+size) % size;
x = (j-aliasX*aliasMapRedBlue[nAlias][1]+size) % size;
if (y > hsize) {
y = size - y;
x = (size - x) % size;
}
if (y>hsize) {
y=size-y;
x=(size-x)%size;
}
speedTable[i][j][nAlias][2]=y*size+x;
}
}
}
/* returns 2 masks (0:0 in the top left corner, match fht) [0] - for greens, [1] - for red/blue */
/* Possible improvements: - 1 make the initial green mask (or actually "fan"-like image) to have sharper ends.
2. detect periodic (line of spots) on the spectrum amplitudes (corresponds to thin lines) and use this
info to confirm this area to belong to the main spectrum */ info to confirm this area to belong to the main spectrum */
public double [][] aliasScissors(double [] green_fht, // fht array for green, will be masked in-place public double [][] aliasScissors(double [] green_fht, // fht array for green, will be masked in-place
double debayer_threshold, // no high frequencies - use default uniform filter double debayer_threshold, // no high frequencies - use default uniform filter
double debayer_gamma, // power function applied to the amplitudes before generating spectral masks double debayer_gamma, // power function applied to the amplitudes before generating spectral masks
double debayer_bonus, // scale far pixels as (1.0+bonus*r/rmax) double debayer_bonus, // scale far pixels as (1.0+bonus*r/rmax)
double mainToAlias,// relative main/alias amplitudes to enable pixels (i.e. 0.5 means that if alias is >0.5*main, the pixel will be masked out) double mainToAlias,// relative main/alias amplitudes to enable pixels (i.e. 0.5 means that if alias is >0.5*main, the pixel will be masked out)
double debayer_mask_blur, // for both masks sigma for Gaussian blur of the binary masks (<0 -do not use "scissors") double debayer_mask_blur, // for both masks sigma for Gaussian blur of the binary masks (<0 -do not use "scissors")
boolean debayer_use_scissors, // use "scissors", if false - just apply "diamond" ands "square" with DEBAYER_WIDTH_GREEN and DEBAYER_WIDTH_REDBLUE boolean debayer_use_scissors, // use "scissors", if false - just apply "diamond" ands "square" with DEBAYER_WIDTH_GREEN and DEBAYER_WIDTH_REDBLUE
int this_debug){ // internal debug level int this_debug){ // internal debug level
int length=green_fht.length; int length=green_fht.length;
int size=(int) Math.sqrt(length); int size=(int) Math.sqrt(length);
double [] green_mask; double [] green_mask;
double [] red_blue_mask; double [] red_blue_mask;
double [] green_amp=fht_instance.calculateAmplitude(green_fht); double [] green_amp=fht_instance.calculateAmplitude(green_fht);
int i,j; int i,j;
/**normalize amplitudes, apply gamma */ /**normalize amplitudes, apply gamma */
double dmax=0.0; double dmax=0.0;
for (i=0;i<green_amp.length;i++) if (green_amp[i]>dmax) dmax=green_amp[i]; for (i=0;i<green_amp.length;i++) if (green_amp[i]>dmax) dmax=green_amp[i];
dmax=1.0/dmax; dmax=1.0/dmax;
for (i=0;i<green_amp.length;i++) green_amp[i]= Math.pow(green_amp[i]*dmax,debayer_gamma); for (i=0;i<green_amp.length;i++) green_amp[i]= Math.pow(green_amp[i]*dmax,debayer_gamma);
if (this_debug>2) SDFA_instance.showArrays(green_amp, "DT-gam"); // only top half+1 will be used if (this_debug>2) SDFA_instance.showArrays(green_amp, "DT-gam"); // only top half+1 will be used
double midRangeSpectral=pol_instace.maxAmpInRing (green_amp); double midRangeSpectral=pol_instace.maxAmpInRing (green_amp);
boolean useFancyDebayer=(midRangeSpectral>=debayer_threshold); boolean useFancyDebayer=(midRangeSpectral>=debayer_threshold);
lastMidEnergy= midRangeSpectral; // for optional monitoring outside of this class lastMidEnergy= midRangeSpectral; // for optional monitoring outside of this class
if (useFancyDebayer && debayer_use_scissors) { /* calculate and apply "scissors" masks */ if (useFancyDebayer && debayer_use_scissors) { /* calculate and apply "scissors" masks */
green_mask= calcGreensAliasMaskRays (green_amp, // normalized amplitude spectrum, (0,0) in the center green_mask= calcGreensAliasMaskRays (green_amp, // normalized amplitude spectrum, (0,0) in the center
pol_instace, // initialized instance pol_instace, // initialized instance
debayer_bonus, // hack - here it is "bonus" debayer_bonus, // hack - here it is "bonus"
this_debug);// this_debug);//
if (this_debug>3) SDFA_instance.showArrays(green_mask, "G-raw"); if (this_debug>3) SDFA_instance.showArrays(green_mask, "G-raw");
if (debayer_mask_blur>0) { if (debayer_mask_blur>0) {
blurDouble(green_mask, size, debayer_mask_blur, debayer_mask_blur, 0.01); blurDouble(green_mask, size, debayer_mask_blur, debayer_mask_blur, 0.01);
if (this_debug>3) SDFA_instance.showArrays(green_mask, "G-blurred"); if (this_debug>3) SDFA_instance.showArrays(green_mask, "G-blurred");
} }
double [] green_mask_for_redblue_main= green_mask.clone(); double [] green_mask_for_redblue_main= green_mask.clone();
double [] green_mask_for_redblue_clones=green_mask.clone(); double [] green_mask_for_redblue_clones=green_mask.clone();
for (i=0;i<green_mask.length;i++) { for (i=0;i<green_mask.length;i++) {
green_mask_for_redblue_main[i]*= lopass[2][0][i]; green_mask_for_redblue_main[i]*= lopass[2][0][i];
green_mask_for_redblue_clones[i]*=lopass[2][1][i]; green_mask_for_redblue_clones[i]*=lopass[2][1][i];
} }
if (this_debug>2) { if (this_debug>2) {
SDFA_instance.showArrays(green_mask_for_redblue_main, "MAIN"); SDFA_instance.showArrays(green_mask_for_redblue_main, "MAIN");
SDFA_instance.showArrays(green_mask_for_redblue_main, "CLONES"); SDFA_instance.showArrays(green_mask_for_redblue_main, "CLONES");
} }
/* Maybe here we need to unmasked (wide bandwidth) green_amp? */ /* Maybe here we need to unmasked (wide bandwidth) green_amp? */
red_blue_mask= calcRedBlueAliasMaskRays (green_amp, // both halves are needed ?? red_blue_mask= calcRedBlueAliasMaskRays (
green_mask_for_redblue_main, // may be null if amp_pixels is already masked green_amp, // both halves are needed ??
green_mask_for_redblue_clones, green_mask_for_redblue_main, // may be null if amp_pixels is already masked
pol_instace, // initialized instance (if null - skip rays processing) green_mask_for_redblue_clones,
mainToAlias,// relative main/alias amplitudes to enable lixels (i.e. 0.5 means that if alias is >0.5*main, the pixel will be masked out) pol_instace, // initialized instance (if null - skip rays processing)
debayer_bonus, // scale far pixels as (1.0+bonus*r/rmax) mainToAlias,// relative main/alias amplitudes to enable pixels (i.e. 0.5 means that if alias is >0.5*main, the pixel will be masked out)
this_debug);// relative main/alias amplitudes to enable lixels (i.e. 0.5 means that if alias is >0.5*main, the pixel will be masked out) debayer_bonus, // scale far pixels as (1.0+bonus*r/rmax)
this_debug);// relative main/alias amplitudes to enable pixels (i.e. 0.5 means that if alias is >0.5*main, the pixel will be masked out)
/* add double mainToAlias){// relative main/alias amplitudes to enable pixels (i.e. 0.5 means that if alias is >0.5*main, the pixel will be masked out) */
/* add double mainToAlias){// relative main/alias amplitudes to enable pixels (i.e. 0.5 means that if alias is >0.5*main, the pixel will be masked out) */
if (this_debug>3) SDFA_instance.showArrays(red_blue_mask, "RB-raw");
if (debayer_mask_blur>0) { if (this_debug>3) SDFA_instance.showArrays(red_blue_mask, "RB-raw");
blurDouble(red_blue_mask, size,debayer_mask_blur, debayer_mask_blur, 0.01); if (debayer_mask_blur>0) {
if (this_debug>3) SDFA_instance.showArrays(red_blue_mask, "RB-blurred"); blurDouble(red_blue_mask, size,debayer_mask_blur, debayer_mask_blur, 0.01);
} if (this_debug>3) SDFA_instance.showArrays(red_blue_mask, "RB-blurred");
for (i=0;i<red_blue_mask.length;i++) red_blue_mask[i]*=lopass[1][1][i]; // scaled, red-blue - was red_blue_lopass[i]; }
} else { // debayer_mask_blur<0 : use default masks for (i=0;i<red_blue_mask.length;i++) red_blue_mask[i]*=lopass[1][1][i]; // scaled, red-blue - was red_blue_lopass[i];
green_mask=lopass[1][0].clone(); //green_lopass.clone(); variable (wide) filter here) } else { // debayer_mask_blur<0 : use default masks
red_blue_mask=lopass[1][1].clone(); //red_blue_lopass.clone(); green_mask=lopass[1][0].clone(); //green_lopass.clone(); variable (wide) filter here)
if (!useFancyDebayer) for (i=0;i<green_mask.length;i++) { // no high-frequency componnets detected - reduce noise by extra (narrow) filtering red_blue_mask=lopass[1][1].clone(); //red_blue_lopass.clone();
green_mask[i]*= lopass[0][0][i]; // *= green_lopass[i]; if (!useFancyDebayer) for (i=0;i<green_mask.length;i++) { // no high-frequency componets detected - reduce noise by extra (narrow) filtering
red_blue_mask[i]*=lopass[0][1][i]; // *=red_blue_lopass[i]; green_mask[i]*= lopass[0][0][i]; // *= green_lopass[i];
} red_blue_mask[i]*=lopass[0][1][i]; // *=red_blue_lopass[i];
} }
/* Swap quadrants in the masks to match FHT arrays (0:0 in the top left corner) */ }
fht_instance.swapQuadrants(green_mask); /* Swap quadrants in the masks to match FHT arrays (0:0 in the top left corner) */
fht_instance.swapQuadrants(red_blue_mask); fht_instance.swapQuadrants(green_mask);
/* return both masks */ fht_instance.swapQuadrants(red_blue_mask);
double [][] result =new double [2][]; /* return both masks */
result[0]= green_mask; double [][] result =new double [2][];
result[1]= red_blue_mask; result[0]= green_mask;
// if (this_debug>3) SDFA_instance.showArrays(result, "before_norm_masks"); result[1]= red_blue_mask;
// if (this_debug>3) SDFA_instance.showArrays(result, "before_norm_masks");
/* normalize masks to have exactly 1.0 at 0:0 - it can be reduced by blurring */
for (i=0;i<result.length;i++) { /* normalize masks to have exactly 1.0 at 0:0 - it can be reduced by blurring */
dmax=1.0/result[i][0]; for (i=0;i<result.length;i++) {
for (j=0;j<result[i].length;j++) result[i][j]*=dmax; dmax=1.0/result[i][0];
} for (j=0;j<result[i].length;j++) result[i][j]*=dmax;
// if (this_debug>3) SDFA_instance.showArrays(result, "masks"); }
return result; // if (this_debug>3) SDFA_instance.showArrays(result, "masks");
} return result;
}
public double [] calcRedBlueAliasMaskRays (double [] green_amp, // both halves are needed ??
double [] green_mask, // may be null if amp_pixels is already masked public double [] calcRedBlueAliasMaskRays (
double [] green_mask_clones, // mask (more inclusive than just green_mask) to be used with clones double [] green_amp, // both halves are needed ??
PolarSpectrums pol_instace, // initialized instance (if null - skip rays processing) double [] green_mask, // may be null if amp_pixels is already masked
double mainToAlias,// relative main/alias amplitudes to enable lixels (i.e. 0.5 means that if alias is >0.5*main, the pixel will be masked out) double [] green_mask_clones, // mask (more inclusive than just green_mask) to be used with clones
double bonus, // scale far pixels as (1.0+bonus*r/rmax) PolarSpectrums pol_instace, // initialized instance (if null - skip rays processing)
int this_debug){// relative main/alias amplitudes to enable lixels (i.e. 0.5 means that if alias is >0.5*main, the pixel will be masked out) double mainToAlias,// relative main/alias amplitudes to enable lixels (i.e. 0.5 means that if alias is >0.5*main, the pixel will be masked out)
double bonus, // scale far pixels as (1.0+bonus*r/rmax)
int length=green_amp.length; int this_debug){// relative main/alias amplitudes to enable lixels (i.e. 0.5 means that if alias is >0.5*main, the pixel will be masked out)
int size = (int) Math.sqrt(length);
int hsize=size/2; int length=green_amp.length;
int subpixel=4; // hardwired - when changing it will need to change alias maps int size = (int) Math.sqrt(length);
int aliasX=size/subpixel; int hsize=size/2;
int i,j,index,index_back,x,y; // int subpixel=4; // hardwired - when changing it will need to change alias maps
double [] amp= green_amp.clone(); // int aliasX=size/subpixel;
double [] amp_clones=green_amp.clone(); int i,j,index,index_back; //,x,y;
if (green_mask!=null) for (i=0;i<amp.length;i++) amp[i]*=green_mask[i]; double [] amp= green_amp.clone();
if (green_mask_clones!=null) for (i=0;i<amp_clones.length;i++) amp_clones[i]*=green_mask_clones[i]; double [] amp_clones=green_amp.clone();
double [] mask= new double [length]; if (green_mask!=null) for (i=0;i<amp.length;i++) amp[i]*=green_mask[i];
for (i=0;i<length;i++) mask[i]=0.0; if (green_mask_clones!=null) for (i=0;i<amp_clones.length;i++) amp_clones[i]*=green_mask_clones[i];
/* Combine into mask by comparing pixels[] from the zero and 7 aliases */ double [] mask= new double [length];
double d; for (i=0;i<length;i++) mask[i]=0.0;
int nAlias; /* Combine into mask by comparing pixels[] from the zero and 7 aliases */
int [][] aliasMapRedBlue={{-2,-2},{-2,-1},{-2,0},{-2,1}, double d;
{-1,-2},{-1,-1},{-1,0},{-1,1}, int nAlias;
{ 0,-2},{ 0,-1}, { 0,1}, /*
{ 1,-2},{ 1,-1},{ 1,0},{ 1,1}}; int [][] aliasMapRedBlue={
{-2,-2},{-2,-1},{-2,0},{-2,1},
/* int [][] aliasMap={{-1,-1},{-1,0},{-1,1}, {-1,-2},{-1,-1},{-1,0},{-1,1},
{ 0,-1}, { 0,1}, { 0,-2},{ 0,-1}, { 0,1},
{ 1,-1},{ 1,0},{ 1,1}};*/ { 1,-2},{ 1,-1},{ 1,0},{ 1,1}};
/* First step - mask out all the pixels where at least one of the alias amplitude is above the main one */ // First step - mask out all the pixels where at least one of the alias amplitude is above the main one
if (this_debug>2) SDFA_instance.showArrays(amp.clone(), "amp"); if (this_debug>2) SDFA_instance.showArrays(amp.clone(), "amp");
if (this_debug>2) SDFA_instance.showArrays(amp_clones, "amp_clones"); if (this_debug>2) SDFA_instance.showArrays(amp_clones, "amp_clones");
for (i=0;i<=hsize;i++) for (j=0;j<size;j++) { for (i=0;i<=hsize;i++) for (j=0;j<size;j++) {
index=i*size+j; index=i*size+j;
index_back=((size-i) % size) * size + ((size-j) % size); index_back=((size-i) % size) * size + ((size-j) % size);
d=amp[index]*mainToAlias; d=amp[index]*mainToAlias;
if (d>0.0) { if (d>0.0) {
mask[index]=1.0; mask[index]=1.0;
mask[index_back]=1.0; mask[index_back]=1.0;
// isGreater=true; // isGreater=true;
for(nAlias=0;nAlias<aliasMapRedBlue.length; nAlias++) { for(nAlias=0;nAlias<aliasMapRedBlue.length; nAlias++) {
y=(i-aliasX*aliasMapRedBlue[nAlias][0]+size) % size; y=(i-aliasX*aliasMapRedBlue[nAlias][0]+size) % size;
x=(j-aliasX*aliasMapRedBlue[nAlias][1]+size) % size; x=(j-aliasX*aliasMapRedBlue[nAlias][1]+size) % size;
if (y>hsize) { if (y>hsize) {
y=size-y; y=size-y;
x=(size-x)%size; x=(size-x)%size;
} }
if (amp_clones[y*size+x]>d) { if (amp_clones[y*size+x]>d) {
mask[index]=-1.0; mask[index]=-1.0;
mask[index_back]=-1.0; mask[index_back]=-1.0;
break; break;
} }
}
} }
} }
if (this_debug>2) SDFA_instance.showArrays(mask, "mask"); }
*/
if (pol_instace==null) return mask; /*
/* Now apply mask to amplitudes and use ray processing (same as with greens)*/ speedTable = new int [hsize][size][aliasMapRedBlue.length][3];
for (i=0;i<amp.length;i++) amp[i]*=mask[i]; int i,j,nAlias,x,y;
if (this_debug>2) SDFA_instance.showArrays(amp, "amp-mask"); for (i=0;i<=hsize;i++) for (j=0;j<size;j++) {
double [] polar_amp=pol_instace.cartesianToPolar(amp); speedTable[i][j][0][0] = i*size+j;
if (this_debug>2) SDFA_instance.showArrays(polar_amp.clone(),pol_instace.getWidth(),pol_instace.getHeight(), "RB-polar-amp"); speedTable[i][j][0][1] = ((size-i) % size) * size + ((size-j) % size);
double k= bonus/pol_instace.getWidth(); for(nAlias=0;nAlias<aliasMapRedBlue.length; nAlias++) {
for (i=0;i<pol_instace.getHeight();i++) for (j=0;j<pol_instace.getWidth();j++) polar_amp[i*pol_instace.getWidth()+j]*=1.0+k*j; y = (i-aliasX*aliasMapRedBlue[nAlias][0]+size) % size;
double [] polar_mask_pixels=pol_instace.genPolarRedBlueMask(polar_amp,0); // 0 - just 1.0/0.0, 1 - "analog" x = (j-aliasX*aliasMapRedBlue[nAlias][1]+size) % size;
double [] cart_mask_pixels= pol_instace.polarToCartesian (polar_mask_pixels,size,0.0); if (y > hsize) {
if (this_debug>2) { y = size - y;
SDFA_instance.showArrays(polar_amp, pol_instace.getWidth(),pol_instace.getHeight(), "RB-amp-bonus"); x = (size - x) % size;
SDFA_instance.showArrays(polar_mask_pixels,pol_instace.getWidth(),pol_instace.getHeight(), "pRBm"); }
SDFA_instance.showArrays(cart_mask_pixels,size,size, "cRBm"); if (y>hsize) {
} y=size-y;
if (this_debug>2) { x=(size-x)%size;
double [] polar_mask_pixels1=pol_instace.genPolarRedBlueMask(polar_amp,1); }
double [] cart_mask_pixels1= pol_instace.polarToCartesian (polar_mask_pixels1,size,0.0); speedTable[i][j][nAlias][2]=y*size+x;
SDFA_instance.showArrays(polar_mask_pixels1,pol_instace.getWidth(),pol_instace.getHeight(), "pRBm1"); }
SDFA_instance.showArrays(cart_mask_pixels1,size,size, "cRBm1"); }
} */
return cart_mask_pixels;
// First step - mask out all the pixels where at least one of the alias amplitude is above the main one
} if (this_debug>2) SDFA_instance.showArrays(amp.clone(), "amp");
if (this_debug>2) SDFA_instance.showArrays(amp_clones, "amp_clones");
public double [] calcGreensAliasMaskRays (double [] amp_pixels, // normalized amplitude spectrum, (0,0) in the center for (i=0;i<=hsize;i++) for (j=0;j<size;j++) {
PolarSpectrums pol_instace, // initialized instance index = speedTable[i][j][0][0]; // i*size+j;
double bonus, // scale far pixels as (1.0+bonus*r/rmax) index_back = speedTable[i][j][0][1]; //((size-i) % size) * size + ((size-j) % size);
int this_debug){// relative main/alias amplitudes to enable lixels (i.e. 0.5 means that if alias is >0.5*main, the pixel will be masked out) d=amp[index]*mainToAlias;
int length=amp_pixels.length; if (d>0.0) {
int size = (int) Math.sqrt(length); mask[index]=1.0;
double [] polar_amp_pixels=pol_instace.cartesianToPolar(amp_pixels); mask[index_back]=1.0;
if (this_debug>2) SDFA_instance.showArrays(polar_amp_pixels.clone(),pol_instace.getWidth(),pol_instace.getHeight(), "polar-amp"); for(nAlias=0;nAlias<aliasMapRedBlue.length; nAlias++) {
if (amp_clones[speedTable[i][j][nAlias][2]]>d) {
double k= bonus/pol_instace.getWidth(); mask[index]=-1.0;
for (int i=0;i<pol_instace.getHeight();i++) for (int j=0;j<pol_instace.getWidth();j++) polar_amp_pixels[i*pol_instace.getWidth()+j]*=1.0+k*j; mask[index_back]=-1.0;
double [] polar_green_mask_pixels=pol_instace.genPolarGreenMask(polar_amp_pixels,0); // 0 - just 1.0/0.0, 1 - "analog" break;
double [] cart_green_mask_pixels= pol_instace.polarToCartesian (polar_green_mask_pixels,size,0.0); }
if (this_debug>2) { }
SDFA_instance.showArrays(polar_amp_pixels, pol_instace.getWidth(),pol_instace.getHeight(), "amp-bonus"); }
SDFA_instance.showArrays(polar_green_mask_pixels,pol_instace.getWidth(),pol_instace.getHeight(), "pgm"); }
SDFA_instance.showArrays(cart_green_mask_pixels,size,size, "cgm");
} // End of replacement code
if (this_debug>2) { if (this_debug>2) SDFA_instance.showArrays(mask, "mask");
double [] polar_green_mask_pixels1=pol_instace.genPolarGreenMask(polar_amp_pixels,1);
double [] cart_green_mask_pixels1= pol_instace.polarToCartesian (polar_green_mask_pixels1,size,0.0); if (pol_instace==null) return mask;
SDFA_instance.showArrays(polar_green_mask_pixels1,pol_instace.getWidth(),pol_instace.getHeight(), "PGM1"); /* Now apply mask to amplitudes and use ray processing (same as with greens)*/
SDFA_instance.showArrays(cart_green_mask_pixels1,size,size, "CGM1"); for (i=0;i<amp.length;i++) amp[i]*=mask[i];
} if (this_debug>2) SDFA_instance.showArrays(amp, "amp-mask");
return cart_green_mask_pixels; double [] polar_amp=pol_instace.cartesianToPolar(amp);
int width = pol_instace.getWidth();
} int height = pol_instace.getHeight();
if (this_debug>2) SDFA_instance.showArrays(polar_amp.clone(),width, height, "RB-polar-amp");
double k= bonus/width;
double [][][] createAliasFilters (double debayer_width_green, // result green mask mpy by scaled default (diamond) for (i=0;i<pol_instace.getHeight();i++) for (j = 0; j < width; j++) polar_amp[i * width + j]*=1.0+k*j;
double debayer_width_redblue, // result red/blue mask mpy by scaled default (square) double [] polar_mask_pixels=pol_instace.genPolarRedBlueMask(polar_amp,0); // 0 - just 1.0/0.0, 1 - "analog"
double debayer_width_redblue_main, // green mask when applied to red/blue, main (center), square double [] cart_mask_pixels= pol_instace.polarToCartesian (polar_mask_pixels,size,0.0);
double debayer_width_redblue_clones, // green mask when applied to red/blue, clones , square if (this_debug>2) {
int size, // side of the square SDFA_instance.showArrays(polar_amp, width, height, "RB-amp-bonus");
int subpixel){ // should be 4 now SDFA_instance.showArrays(polar_mask_pixels, width, height, "pRBm");
int i; SDFA_instance.showArrays(cart_mask_pixels, size, size, "cRBm");
double [] cosMask= createCosMask (size, subpixel); // oversampling }
double [][] [] lopass =new double [3][2][]; if (this_debug>2) {
lopass[0][0]=new double [size*size]; double [] polar_mask_pixels1=pol_instace.genPolarRedBlueMask(polar_amp,1);
for (i=0;i<lopass[0][0].length;i++) lopass[0][0][i]=1.0; double [] cart_mask_pixels1= pol_instace.polarToCartesian (polar_mask_pixels1,size,0.0);
lopass[0][1]=lopass[0][0].clone(); SDFA_instance.showArrays(polar_mask_pixels1, width, height, "pRBm1");
lopass[1][0]=lopass[0][0].clone(); SDFA_instance.showArrays(cart_mask_pixels1, size, size, "cRBm1");
lopass[1][1]=lopass[0][0].clone(); }
lopass[2][0]=lopass[0][0].clone(); return cart_mask_pixels;
lopass[2][1]=lopass[0][0].clone();
maskBayerAliases (lopass[0][0], // FHT array to be filtered }
cosMask, // cosine mask array
true); // this fht array is for the checkerboard greens
maskBayerAliases (lopass[0][1], // FHT array to be filtered public double [] calcGreensAliasMaskRays (double [] amp_pixels, // normalized amplitude spectrum, (0,0) in the center
cosMask, // cosine mask array PolarSpectrums pol_instace, // initialized instance
false); // this fht array is for the checkerboard greens double bonus, // scale far pixels as (1.0+bonus*r/rmax)
int this_debug){// relative main/alias amplitudes to enable lixels (i.e. 0.5 means that if alias is >0.5*main, the pixel will be masked out)
cosMask= createCosMask ((int) Math.round(size*debayer_width_green), subpixel); // oversampling int length=amp_pixels.length;
maskBayerAliases (lopass[1][0], // FHT array to be filtered int size = (int) Math.sqrt(length);
cosMask, // cosine mask array double [] polar_amp_pixels=pol_instace.cartesianToPolar(amp_pixels);
true); // this fht array is for the checkerboard greens if (this_debug>2) SDFA_instance.showArrays(polar_amp_pixels.clone(),pol_instace.getWidth(),pol_instace.getHeight(), "polar-amp");
cosMask= createCosMask ((int) Math.round(size*debayer_width_redblue), subpixel); // oversampling
maskBayerAliases (lopass[1][1], // FHT array to be filtered double k= bonus/pol_instace.getWidth();
cosMask, // cosine mask array for (int i=0;i<pol_instace.getHeight();i++) for (int j=0;j<pol_instace.getWidth();j++) polar_amp_pixels[i*pol_instace.getWidth()+j]*=1.0+k*j;
false); // this fht array is for the checkerboard greens double [] polar_green_mask_pixels=pol_instace.genPolarGreenMask(polar_amp_pixels,0); // 0 - just 1.0/0.0, 1 - "analog"
double [] cart_green_mask_pixels= pol_instace.polarToCartesian (polar_green_mask_pixels,size,0.0);
cosMask= createCosMask ((int) Math.round(size*debayer_width_redblue_main), subpixel); // oversampling if (this_debug>2) {
maskBayerAliases (lopass[2][0], // FHT array to be filtered SDFA_instance.showArrays(polar_amp_pixels, pol_instace.getWidth(),pol_instace.getHeight(), "amp-bonus");
cosMask, // cosine mask array SDFA_instance.showArrays(polar_green_mask_pixels,pol_instace.getWidth(),pol_instace.getHeight(), "pgm");
false); // this fht array is for the checkerboard greens SDFA_instance.showArrays(cart_green_mask_pixels,size,size, "cgm");
cosMask= createCosMask ((int) Math.round(size*debayer_width_redblue_clones), subpixel); // oversampling }
maskBayerAliases (lopass[2][1], // FHT array to be filtered
cosMask, // cosine mask array if (this_debug>2) {
false); // this fht array is for the checkerboard greens double [] polar_green_mask_pixels1=pol_instace.genPolarGreenMask(polar_amp_pixels,1);
double [] cart_green_mask_pixels1= pol_instace.polarToCartesian (polar_green_mask_pixels1,size,0.0);
SDFA_instance.showArrays(polar_green_mask_pixels1,pol_instace.getWidth(),pol_instace.getHeight(), "PGM1");
fht_instance.swapQuadrants(lopass[0][0]); SDFA_instance.showArrays(cart_green_mask_pixels1,size,size, "CGM1");
fht_instance.swapQuadrants(lopass[0][1]); }
fht_instance.swapQuadrants(lopass[1][0]); return cart_green_mask_pixels;
fht_instance.swapQuadrants(lopass[1][1]);
fht_instance.swapQuadrants(lopass[2][0]); }
fht_instance.swapQuadrants(lopass[2][1]);
return lopass;
} double [][][] createAliasFilters (double debayer_width_green, // result green mask mpy by scaled default (diamond)
double debayer_width_redblue, // result red/blue mask mpy by scaled default (square)
void maskBayerAliases (double [] fht, // FHT array to be filtered double debayer_width_redblue_main, // green mask when applied to red/blue, main (center), square
double [] cosMask, // cosine mask array double debayer_width_redblue_clones, // green mask when applied to red/blue, clones , square
boolean isChecker) { // this fht array is for the checkerboard greens int size, // side of the square
int size= (int) Math.sqrt(fht.length); int subpixel){ // should be 4 now
int iy,ix, ix1,iy1; int i;
int tsize= (cosMask.length-1)/(isChecker?1:2); double [] cosMask= createCosMask (size, subpixel); // oversampling
int index=0; double [][] [] lopass =new double [3][2][];
int hsizeM1=(size/2)-1; lopass[0][0]=new double [size*size];
if (isChecker) { for (i=0;i<lopass[0][0].length;i++) lopass[0][0][i]=1.0;
lopass[0][1]=lopass[0][0].clone();
for (iy=0;iy<size;iy++) { lopass[1][0]=lopass[0][0].clone();
iy1=(iy+hsizeM1)%size -hsizeM1; lopass[1][1]=lopass[0][0].clone();
for (ix=0;ix<size;ix++) { lopass[2][0]=lopass[0][0].clone();
ix1=(ix+hsizeM1)%size -hsizeM1; lopass[2][1]=lopass[0][0].clone();
if (((ix1+iy1)>-tsize) && maskBayerAliases (lopass[0][0], // FHT array to be filtered
((ix1-iy1)>-tsize) && cosMask, // cosine mask array
((ix1+iy1)<=tsize) && true); // this fht array is for the checkerboard greens
((ix1-iy1)<=tsize)) fht[index++]*=cosMask[Math.abs(ix1+iy1)]*cosMask[Math.abs(ix1-iy1)]; maskBayerAliases (lopass[0][1], // FHT array to be filtered
else fht[index++]=0.0; cosMask, // cosine mask array
} false); // this fht array is for the checkerboard greens
}
cosMask= createCosMask ((int) Math.round(size*debayer_width_green), subpixel); // oversampling
} else { maskBayerAliases (lopass[1][0], // FHT array to be filtered
for (iy=0;iy<size;iy++) { cosMask, // cosine mask array
iy1=(iy+hsizeM1)%size -hsizeM1; true); // this fht array is for the checkerboard greens
for (ix=0;ix<size;ix++) { cosMask= createCosMask ((int) Math.round(size*debayer_width_redblue), subpixel); // oversampling
ix1=(ix+hsizeM1)%size -hsizeM1; maskBayerAliases (lopass[1][1], // FHT array to be filtered
if ((iy1>-tsize) && (iy1<=tsize) && (ix1>-tsize) && (ix1<=tsize)) fht[index++]*=cosMask[2*Math.abs(iy1)]*cosMask[2*Math.abs(ix1)]; cosMask, // cosine mask array
else fht[index++]=0.0; false); // this fht array is for the checkerboard greens
}
} cosMask= createCosMask ((int) Math.round(size*debayer_width_redblue_main), subpixel); // oversampling
} maskBayerAliases (lopass[2][0], // FHT array to be filtered
} cosMask, // cosine mask array
false); // this fht array is for the checkerboard greens
cosMask= createCosMask ((int) Math.round(size*debayer_width_redblue_clones), subpixel); // oversampling
double [] createCosMask (int fftsize, // FHT array to be filtered - just length is used maskBayerAliases (lopass[2][1], // FHT array to be filtered
int subdiv // oversampling cosMask, // cosine mask array
) { // this fht array is for the checkerboard greens false); // this fht array is for the checkerboard greens
int size= 2*fftsize/subdiv;
double [] cosMask=new double [size+1];
for (int i=0;i<=size;i++) cosMask[i]=0.5*(1.0+Math.cos(i*Math.PI/size)); fht_instance.swapQuadrants(lopass[0][0]);
return cosMask; fht_instance.swapQuadrants(lopass[0][1]);
} fht_instance.swapQuadrants(lopass[1][0]);
fht_instance.swapQuadrants(lopass[1][1]);
// temporary using float implementation in ImageJ - re-write to directly use double [] arrays fht_instance.swapQuadrants(lopass[2][0]);
public void blurDouble(double[] pixels, fht_instance.swapQuadrants(lopass[2][1]);
int width, return lopass;
double sigmaX, }
double sigmaY,
double precision) { void maskBayerAliases (double [] fht, // FHT array to be filtered
// public void blurFloat(red_blue_mask, DEBAYER_MASK_BLUR, DEBAYER_MASK_BLUR, 0.01); double [] cosMask, // cosine mask array
int i; boolean isChecker) { // this fht array is for the checkerboard greens
int height = pixels.length/width; int size= (int) Math.sqrt(fht.length);
float [] fpixels=new float [pixels.length]; int iy,ix, ix1,iy1;
for (i=0;i<pixels.length;i++) fpixels[i]= (float) pixels[i]; int tsize= (cosMask.length-1)/(isChecker?1:2);
FloatProcessor fp = new FloatProcessor(width, height, fpixels, null); int index=0;
GaussianBlur gb = new GaussianBlur(); int hsizeM1=(size/2)-1;
gb.blurFloat(fp, sigmaX, sigmaY, precision); if (isChecker) {
for (i=0;i<pixels.length;i++) pixels[i]=fpixels[i];
} for (iy=0;iy<size;iy++) {
/* ====================================================== */ iy1=(iy+hsizeM1)%size -hsizeM1;
public class PolarSpectrums { for (ix=0;ix<size;ix++) {
public int radius=0; ix1=(ix+hsizeM1)%size -hsizeM1;
public int iRadiusPlus1; // number of radius steps if (((ix1+iy1)>-tsize) &&
public int iAngle; ((ix1-iy1)>-tsize) &&
public double aStep; ((ix1+iy1)<=tsize) &&
public double rStep; ((ix1-iy1)<=tsize)) fht[index++]*=cosMask[Math.abs(ix1+iy1)]*cosMask[Math.abs(ix1-iy1)];
public int size; else fht[index++]=0.0;
public int length; }
// Make them private later, after debugging }
private int [][] polar2CartesianIndices; // for each polar angle/radius (angle*iRadiusPlus1+radius) - 4 interpolation corners (0:0, dx:0, 0:dy, dx:dy), the first (0:0) being the closest to the polar point
private double [][] polar2CartesianFractions; // a pair of dx, dy for interpolations (used with ) polar2CartesianIndices[][]] } else {
private int [][] cartesian2PolarIndices; // each per-pixel array is a list of indices in polar array pointing to this cell (may be empty) for (iy=0;iy<size;iy++) {
private int [] cartesian2PolarIndex; // Cartesian->polar array index (cell closest to the center). Is it possible that cartesian2PolarIndices does not include this one? iy1=(iy+hsizeM1)%size -hsizeM1;
private int [][] polarGreenMap=null ; // each element is a variable length integer array with a list of the alias indices for (ix=0;ix<size;ix++) {
private int [][] polarRedBlueMap=null ; // each element is a variable length integer array with a list of the alias indices ix1=(ix+hsizeM1)%size -hsizeM1;
private int [][] sameCartesian=null ; // each element is a variable length integer array with a list of indices of the other polar cells that belong (point to) the same cartesian cell if ((iy1>-tsize) && (iy1<=tsize) && (ix1>-tsize) && (ix1<=tsize)) fht[index++]*=cosMask[2*Math.abs(iy1)]*cosMask[2*Math.abs(ix1)];
private int [] cartAmpList = null; // list of indices of the elements of the cartesian array (symmetrical around the center) so the distance is between ampRMinMax[0] and ampRMinMax[1] else fht[index++]=0.0;
private double [] ampRMinMax ={0.0,0.0}; }
public PolarSpectrums() { } // so "Compile and Run" will be happy }
/* Convert cartesian to polar array, dimensions are set in the class constructor. Uses bi-linear interpolation */ }
public double [] cartesianToPolar (double [] cartPixels ) { }
double [] polPixels=new double[iRadiusPlus1*(iAngle+1)];
int i;
for (i=0;i<polPixels.length;i++) { double [] createCosMask (int fftsize, // FHT array to be filtered - just length is used
polPixels[i]=(1-polar2CartesianFractions[i][1])*( (1-polar2CartesianFractions[i][0])*cartPixels[polar2CartesianIndices[i][0]] + polar2CartesianFractions[i][0]*cartPixels[polar2CartesianIndices[i][1]])+ int subdiv // oversampling
polar2CartesianFractions[i][1] *( (1-polar2CartesianFractions[i][0])*cartPixels[polar2CartesianIndices[i][2]] + polar2CartesianFractions[i][0]*cartPixels[polar2CartesianIndices[i][3]]) ; ) { // this fht array is for the checkerboard greens
} int size= 2*fftsize/subdiv;
return polPixels; double [] cosMask=new double [size+1];
} for (int i=0;i<=size;i++) cosMask[i]=0.5*(1.0+Math.cos(i*Math.PI/size));
public double [] polarToCartesian (double [] polPixels , int height, double undefined ) { return polarToCartesian (polPixels , height, undefined, height==size); } return cosMask;
public double [] polarToCartesian (double [] polPixels , double undefined) { return polarToCartesian (polPixels ,size, undefined,false); } }
public double [] polarToCartesian (double [] polPixels , int height ) { return polarToCartesian (polPixels , height, Double.NaN,height==size); }
public double [] polarToCartesian (double [] polPixels ) { return polarToCartesian (polPixels , size, Double.NaN,false); } // temporary using float implementation in ImageJ - re-write to directly use double [] arrays
public double [] polarToCartesian (double [] polPixels, public void blurDouble(double[] pixels,
int height, // for partial arrays int width,
double undefined, // use this value in the undefined areas double sigmaX,
boolean symmHalf){ // add center-symmetrical top to the bottom(spectrums of real signals) double sigmaY,
int length=size*height; double precision) {
double [] cartPixels=new double[length]; // public void blurFloat(red_blue_mask, DEBAYER_MASK_BLUR, DEBAYER_MASK_BLUR, 0.01);
int i,j; int i;
int [] sameCartCell; int height = pixels.length/width;
double d; float [] fpixels=new float [pixels.length];
int l=symmHalf?((size+1)*size/2+1) :(size*height); for (i=0;i<pixels.length;i++) fpixels[i]= (float) pixels[i];
int l2=(size+1)*size; FloatProcessor fp = new FloatProcessor(width, height, fpixels, null);
for (i=0;i<l;i++) { GaussianBlur gb = new GaussianBlur();
sameCartCell=cartesian2PolarIndices[i]; gb.blurFloat(fp, sigmaX, sigmaY, precision);
if (sameCartCell==null) { for (i=0;i<pixels.length;i++) pixels[i]=fpixels[i];
if (cartesian2PolarIndex[i]>=0) cartPixels[i]=polPixels[cartesian2PolarIndex[i]]; }
else cartPixels[i]=undefined; /* ====================================================== */
} else { public class PolarSpectrums {
d=0; public int radius=0;
for (j=0;j<sameCartCell.length;j++) d+=polPixels[sameCartCell[j]]; public int iRadiusPlus1; // number of radius steps
cartPixels[i]=d/sameCartCell.length; public int iAngle;
} public double aStep;
if (symmHalf) { public double rStep;
j=l2-i; public int size;
if (j<length) cartPixels[j] = cartPixels[i]; public int length;
} // Make them private later, after debugging
} private int [][] polar2CartesianIndices; // for each polar angle/radius (angle*iRadiusPlus1+radius) - 4 interpolation corners (0:0, dx:0, 0:dy, dx:dy), the first (0:0) being the closest to the polar point
return cartPixels; private double [][] polar2CartesianFractions; // a pair of dx, dy for interpolations (used with ) polar2CartesianIndices[][]]
} private int [][] cartesian2PolarIndices; // each per-pixel array is a list of indices in polar array pointing to this cell (may be empty)
/* Caculates maximal value of a center-symmetrical array of the amplitudes in a ring. Uses cached table of indices, recalculates if it changed */ private int [] cartesian2PolarIndex; // Cartesian->polar array index (cell closest to the center). Is it possible that cartesian2PolarIndices does not include this one?
public double maxAmpInRing ( double []amps ){ return maxAmpInRing (amps,size*0.118,size*0.236);} // ~=1/3* (Math.sqrt(2)/4), 2/3* (Math.sqrt(2)/4) (center 1/3 ring between center and the closest alias for greens) private int [][] polarGreenMap=null ; // each element is a variable length integer array with a list of the alias indices
public double maxAmpInRing ( double []amps, private int [][] polarRedBlueMap=null ; // each element is a variable length integer array with a list of the alias indices
double rMin, private int [][] sameCartesian=null ; // each element is a variable length integer array with a list of indices of the other polar cells that belong (point to) the same cartesian cell
double rMax private int [] cartAmpList = null; // list of indices of the elements of the cartesian array (symmetrical around the center) so the distance is between ampRMinMax[0] and ampRMinMax[1]
){ private double [] ampRMinMax ={0.0,0.0};
int i,j,x,y; public PolarSpectrums() { } // so "Compile and Run" will be happy
if ((cartAmpList==null) || (rMin!=ampRMinMax[0]) || (rMax!=ampRMinMax[1])) { /* Convert cartesian to polar array, dimensions are set in the class constructor. Uses bi-linear interpolation */
ampRMinMax[0]=rMin; public double [] cartesianToPolar (double [] cartPixels ) {
ampRMinMax[1]=rMax; double [] polPixels=new double[iRadiusPlus1*(iAngle+1)];
double rMin2=rMin*rMin; int i;
double rMax2=rMax*rMax; for (i=0;i<polPixels.length;i++) {
double r2; polPixels[i]=(1-polar2CartesianFractions[i][1])*( (1-polar2CartesianFractions[i][0])*cartPixels[polar2CartesianIndices[i][0]] +
// pass 1 - count number of elements polar2CartesianFractions[i][0]*cartPixels[polar2CartesianIndices[i][1]])+
int numMembers=0; polar2CartesianFractions[i][1] *( (1-polar2CartesianFractions[i][0])*cartPixels[polar2CartesianIndices[i][2]] +
for (i=0;i<=size/2;i++) { polar2CartesianFractions[i][0]*cartPixels[polar2CartesianIndices[i][3]]) ;
y=i-(size/2); }
for (j=0;j<size;j++) { return polPixels;
x=j-(size/2); }
r2=x*x+y*y; public double [] polarToCartesian (double [] polPixels , int height, double undefined ) { return polarToCartesian (polPixels , height, undefined, height==size); }
if ((r2>=rMin2) && (r2<=rMax2)) numMembers++; public double [] polarToCartesian (double [] polPixels , double undefined) { return polarToCartesian (polPixels ,size, undefined,false); }
} public double [] polarToCartesian (double [] polPixels , int height ) { return polarToCartesian (polPixels , height, Double.NaN,height==size); }
} public double [] polarToCartesian (double [] polPixels ) { return polarToCartesian (polPixels , size, Double.NaN,false); }
cartAmpList=new int [numMembers]; public double [] polarToCartesian (double [] polPixels,
// pass 2 - count number of elements fill in the array int height, // for partial arrays
numMembers=0; double undefined, // use this value in the undefined areas
for (i=0;i<=size/2;i++) { boolean symmHalf){ // add center-symmetrical top to the bottom(spectrums of real signals)
y=i-(size/2); int length=size*height;
for (j=0;j<size;j++) { double [] cartPixels=new double[length];
x=j-(size/2); int i,j;
r2=x*x+y*y; int [] sameCartCell;
if ((r2>=rMin2) && (r2<=rMax2)) cartAmpList[numMembers++]=i*size+j; double d;
} int l=symmHalf?((size+1)*size/2+1) :(size*height);
} int l2=(size+1)*size;
} for (i=0;i<l;i++) {
if (cartAmpList.length<1) return Double.NaN; sameCartCell=cartesian2PolarIndices[i];
double max=amps[cartAmpList[0]]; if (sameCartCell==null) {
for (i=1;i<cartAmpList.length;i++) if (max<amps[cartAmpList[i]]) max=amps[cartAmpList[i]]; if (cartesian2PolarIndex[i]>=0) cartPixels[i]=polPixels[cartesian2PolarIndex[i]];
return max; else cartPixels[i]=undefined;
} } else {
/* return polar array width (== radius+1) */ d=0;
public int getWidth() { return iRadiusPlus1; } for (j=0;j<sameCartCell.length;j++) d+=polPixels[sameCartCell[j]];
public int getHeight() { return iAngle+1; } cartPixels[i]=d/sameCartCell.length;
public double [] genPolarGreenMask(double [] polarAmps, // polar array of amplitude values, <0 - stop }
int mode){ // result mode - 0: output mask as 0/1, 1 -output proportional, positive - pass, negative - rejected if (symmHalf) {
return genPolarMask(polarAmps,0,mode); j=l2-i;
} if (j<length) cartPixels[j] = cartPixels[i];
}
public double [] genPolarRedBlueMask(double [] polarAmps, // polar array of amplitude values, <0 - stop }
int mode){ // result mode - 0: output mask as 0/1, 1 -output proportional, positive - pass, negative - rejected return cartPixels;
return genPolarMask(polarAmps,1,mode); }
} /* Caculates maximal value of a center-symmetrical array of the amplitudes in a ring. Uses cached table of indices, recalculates if it changed */
public double maxAmpInRing ( double []amps ){ return maxAmpInRing (amps,size*0.118,size*0.236);} // ~=1/3* (Math.sqrt(2)/4), 2/3* (Math.sqrt(2)/4) (center 1/3 ring between center and the closest alias for greens)
public double maxAmpInRing ( double []amps,
public double [] genPolarMask(double [] polarAmps, // polar array of amplitude values, <0 - stop double rMin,
int type, // 0 - green, 1 red/blue double rMax
int mode){ // result mode - 0: output mask as 0/1, 1 -output proportional, positive - pass, negative - rejected ){
int [][] polarMap=(type>0)?polarRedBlueMap: polarGreenMap; int i,j,x,y;
int length=iRadiusPlus1*(iAngle+1); if ((cartAmpList==null) || (rMin!=ampRMinMax[0]) || (rMax!=ampRMinMax[1])) {
int [] intMap= new int[length]; ampRMinMax[0]=rMin;
int i,ia; ampRMinMax[1]=rMax;
for (i=0;i<intMap.length;i++) intMap[i]=0; double rMin2=rMin*rMin;
int [] rayLength=new int[iAngle+1]; // index (radius)) of the current ray end for this angle double rMax2=rMax*rMax;
boolean [] rayOpen= new boolean[iAngle+1]; // this ray can grow (not blocked) double r2;
for (i=0;i<iAngle;i++) { // pass 1 - count number of elements
rayLength[i]=0; int numMembers=0;
rayOpen[i]=true; for (i=0;i<=size/2;i++) {
} y=i-(size/2);
int lastIndex; for (j=0;j<size;j++) {
int base; x=j-(size/2);
int l; r2=x*x+y*y;
double max; if ((r2>=rMin2) && (r2<=rMax2)) numMembers++;
int newVal; }
int step=0; }
int iMax=0; // index of the best ray cartAmpList=new int [numMembers];
int index=0; // pass 2 - count number of elements fill in the array
boolean good=true; numMembers=0;
while (iMax>=0) { for (i=0;i<=size/2;i++) {
step++; y=i-(size/2);
/* add polar point index */ for (j=0;j<size;j++) {
newVal=good?step:-step; x=j-(size/2);
// index=iMax*iRadiusPlus1+rayLength[iMax]; // rayLength[iMax] should point to a new cell (with intMap[]==0) may ommit - set in the end of the loop and before the loop? r2=x*x+y*y;
intMap[index]=newVal; if ((r2>=rMin2) && (r2<=rMax2)) cartAmpList[numMembers++]=i*size+j;
if (sameCartesian[index]!=null) for (i=0;i<sameCartesian[index].length;i++) intMap[sameCartesian[index][i]]=newVal; }
/* add aliases of point index (as negative values) */ }
if ((good) &&(polarMap[index]!=null)) for (i=0;i<polarMap[index].length;i++) intMap[polarMap[index][i]]=-step; }
/* update ray lengths and status */ if (cartAmpList.length<1) return Double.NaN;
max=-1.0; double max=amps[cartAmpList[0]];
iMax=-1; for (i=1;i<cartAmpList.length;i++) if (max<amps[cartAmpList[i]]) max=amps[cartAmpList[i]];
for (ia=0;ia<=iAngle;ia++) if (rayOpen[ia]) { return max;
base=ia*iRadiusPlus1+1; // second for this angle }
l=base+rayLength[ia]; // first after the pointer /* return polar array width (== radius+1) */
lastIndex=base+iRadiusPlus1; // first in the next row public int getWidth() { return iRadiusPlus1; }
while ((l<lastIndex) && (intMap[l]>0)) l++; public int getHeight() { return iAngle+1; }
rayLength[ia]=l-base; // last "good" ( >0 and in the same row) public double [] genPolarGreenMask(double [] polarAmps, // polar array of amplitude values, <0 - stop
if ((l==lastIndex) || (intMap[l]<0) || (polarAmps[l]<0.0) ) rayOpen[ia]=false; int mode){ // result mode - 0: output mask as 0/1, 1 -output proportional, positive - pass, negative - rejected
else { return genPolarMask(polarAmps,0,mode);
if (polarAmps[l]>max) { }
max=polarAmps[l];
iMax=ia; public double [] genPolarRedBlueMask(
} double [] polarAmps, // polar array of amplitude values, <0 - stop
} int mode)
} { // result mode - 0: output mask as 0/1, 1 -output proportional, positive - pass, negative - rejected
if (iMax>=0) { return genPolarMask(polarAmps, 1, mode);
rayLength[iMax]++; }
index=iMax*iRadiusPlus1+rayLength[iMax];
/* See if any of the aliases of the new point hit the positive value, then this point is prohibited (good=false). Otherwise add it with good=true */ // **** Seems to be most time-critical ****
good=true; public double [] genPolarMask(double [] polarAmps, // polar array of amplitude values, <0 - stop
if (polarMap[index]!=null) for (i=0;i<polarMap[index].length;i++) { int type, // 0 - green, 1 red/blue
if (intMap[polarMap[index][i]]>0) { int mode){ // result mode - 0: output mask as 0/1, 1 -output proportional, positive - pass, negative - rejected
good=false; int [][] polarMap=(type>0)?polarRedBlueMap: polarGreenMap;
break; int length=iRadiusPlus1*(iAngle+1);
} int [] intMap= new int[length];
} int i,ia;
} for (i=0;i<intMap.length;i++) intMap[i]=0;
/* index is set if (iMax>=0) */ int [] rayLength=new int[iAngle+1]; // index (radius)) of the current ray end for this angle
} boolean [] rayOpen= new boolean[iAngle+1]; // this ray can grow (not blocked)
double [] result=new double [intMap.length]; for (i=0;i<iAngle;i++) {
if (mode==0) { rayLength[i]=0;
for (i=0;i<length;i++) result[i]=(intMap[i]>0)?1.0:0.0; rayOpen[i]=true;
} else { }
for (i=0;i<length;i++) result[i]=(intMap[i]>0)?(step-intMap[i]):-(step+intMap[i]); int lastIndex;
} int base;
return result; int l;
} double max;
public PolarSpectrums( int newVal;
int isize, // size of the square array, centar is at size/2, size/2, only top half+line will be used int step=0;
double fullAngle, // i.e. Math.PI, 2*Math.PI int iMax=0; // index of the best ray
int maxRadius, // width of the polar array - should be <= size/2-2 int index=0;
double outerStep, // maximal step in pixels on the maxRadius for 1 angular step (i.e. 0.5) boolean good=true;
int symm // angular symmetry - 0- none,1 - pi corresponds to integer, 2 - pi/2 corresponds to integer, n - pi/n corresponds to integer angular step while (iMax>=0) {
) { step++;
size= isize; /* add polar point index */
length=size*size; newVal=good?step:-step;
if (maxRadius>(size/2-2)) maxRadius=(size/2-2); intMap[index]=newVal;
radius=maxRadius; if (sameCartesian[index]!=null)
if (symm==0) aStep=fullAngle/Math.ceil(fullAngle*radius/outerStep); for (i=0;i<sameCartesian[index].length;i++)
else aStep=Math.PI/symm/Math.ceil(Math.PI*radius/outerStep/symm); intMap[sameCartesian[index][i]]=newVal;
iRadiusPlus1=(int) Math.ceil(radius/outerStep)+1; /* add aliases of point index (as negative values) */
rStep=radius/(iRadiusPlus1-1.0); if ((good) &&(polarMap[index]!=null))
iAngle=(int) Math.round(fullAngle/aStep); for (i=0;i<polarMap[index].length;i++)
polar2CartesianIndices= new int [(iAngle+1)*iRadiusPlus1][4]; // [0] - closest one intMap[polarMap[index][i]]=-step;
polar2CartesianFractions=new double [(iAngle+1)*iRadiusPlus1][2]; /* update ray lengths and status */
int ia,ir,y,x,i,j; //,PolarIndex; max=-1.0;
double a,r,cos,sin,dy,dx; iMax=-1;
cartesian2PolarIndex= new int[length]; for (ia=0;ia<=iAngle;ia++) if (rayOpen[ia]) {
cartesian2PolarIndices=new int[length][]; base=ia*iRadiusPlus1+1; // second for this angle
@SuppressWarnings("unchecked") l=base+rayLength[ia]; // first after the pointer
HashSet <Integer> [] polarList= (HashSet <Integer> []) new HashSet[length]; lastIndex=base+iRadiusPlus1; // first in the next row
for (i=0;i<length;i++) { while ((l<lastIndex) && (intMap[l]>0)) l++;
polarList[i]=new HashSet <Integer>(); // 16, 0.75 rayLength[ia]=l-base; // last "good" ( >0 and in the same row)
} if ((l==lastIndex) || (intMap[l]<0) || (polarAmps[l]<0.0) )
Integer PolarIndex,CartesianIndex; rayOpen[ia]=false;
for (ia=0;ia<=iAngle;ia++) { else if (polarAmps[l]>max) {
a=ia*aStep; max=polarAmps[l];
cos=Math.cos(a); iMax=ia;
sin=Math.sin(a); }
for (ir=0;ir<iRadiusPlus1;ir++) {
PolarIndex=ia*iRadiusPlus1+ir; }
r=ir*rStep; if (iMax>=0) {
dy=r*sin; rayLength[iMax]++;
y=(int) Math.round(dy); index=iMax*iRadiusPlus1+rayLength[iMax];
dy-=y; /* See if any of the aliases of the new point hit the positive value, then this point is prohibited (good=false). Otherwise add it with good=true */
i=size/2-y; good=true;
dx=r*cos; if (polarMap[index]!=null) for (i=0;i<polarMap[index].length;i++) {
x=(int) Math.round(dx); if (intMap[polarMap[index][i]]>0) {
dx-=x; good=false;
j=x+size/2; break;
CartesianIndex=i*size+j; }
polar2CartesianIndices[PolarIndex][0]=CartesianIndex; }
polarList[CartesianIndex].add(PolarIndex); }
if (dx<0) { /* index is set if (iMax>=0) */
polar2CartesianIndices[PolarIndex][1]=polar2CartesianIndices[PolarIndex][0]-1; }
dx=-dx; double [] result=new double [intMap.length];
} else { if (mode==0) {
polar2CartesianIndices[PolarIndex][1]=polar2CartesianIndices[PolarIndex][0]+1; for (i=0;i<length;i++) result[i]=(intMap[i]>0)?1.0:0.0;
} } else {
if (dy<0) { for (i=0;i<length;i++) result[i]=(intMap[i]>0)?(step-intMap[i]):-(step+intMap[i]);
polar2CartesianIndices[PolarIndex][2]=polar2CartesianIndices[PolarIndex][0]+size; }
polar2CartesianIndices[PolarIndex][3]=polar2CartesianIndices[PolarIndex][1]+size; return result;
dy=-dy; }
} else {
polar2CartesianIndices[PolarIndex][2]=polar2CartesianIndices[PolarIndex][0]-size; public PolarSpectrums(
polar2CartesianIndices[PolarIndex][3]=polar2CartesianIndices[PolarIndex][1]-size; int isize, // size of the square array, center is at size/2, size/2, only top half+line will be used
} double fullAngle, // i.e. Math.PI, 2*Math.PI
polar2CartesianFractions[PolarIndex][0]=dx; int maxRadius, // width of the polar array - should be <= size/2-2
polar2CartesianFractions[PolarIndex][1]=dy; double outerStep, // maximal step in pixels on the maxRadius for 1 angular step (i.e. 0.5)
} int symm // angular symmetry - 0- none,1 - pi corresponds to integer, 2 - pi/2 corresponds to integer, n - pi/n corresponds to integer angular step
} ) {
for (i=0;i<length;i++) { size= isize;
y=size/2-(i/size); length=size*size;
x=(i % size)- size/2; if (maxRadius>(size/2-2)) maxRadius=(size/2-2);
r=Math.sqrt(x*x+y*y); radius=maxRadius;
a=Math.atan2(y,x); if (symm==0) aStep=fullAngle/Math.ceil(fullAngle*radius/outerStep);
if (a<0) a+=2*Math.PI; else aStep=Math.PI/symm/Math.ceil(Math.PI*radius/outerStep/symm);
ir =(int) Math.round(r/rStep); iRadiusPlus1=(int) Math.ceil(radius/outerStep)+1;
ia= (int) Math.round(a/aStep); rStep=radius/(iRadiusPlus1-1.0);
if ((ir>=0) && (ir<iRadiusPlus1) && (ia>=0) && (ia<=iAngle)) { iAngle=(int) Math.round(fullAngle/aStep);
cartesian2PolarIndex[i]=ia*iRadiusPlus1+ir; polar2CartesianIndices= new int [(iAngle+1)*iRadiusPlus1][4]; // [0] - closest one
if (polarList[i].size()==0) cartesian2PolarIndices[i]=null; polar2CartesianFractions=new double [(iAngle+1)*iRadiusPlus1][2];
else { int ia,ir,y,x,i,j; //,PolarIndex;
cartesian2PolarIndices[i]=new int[polarList[i].size()]; double a,r,cos,sin,dy,dx;
j=0; cartesian2PolarIndex= new int[length];
for (Integer val : polarList[i]) cartesian2PolarIndices[i][j++]=val; cartesian2PolarIndices=new int[length][];
} @SuppressWarnings("unchecked")
} else { HashSet <Integer> [] polarList= (HashSet <Integer> []) new HashSet[length];
cartesian2PolarIndex[i]=-1; // invalid for (i=0;i<length;i++) {
cartesian2PolarIndices[i]=null; polarList[i]=new HashSet <Integer>(); // 16, 0.75
} }
} Integer PolarIndex,CartesianIndex;
initSameCartesian(); for (ia=0;ia<=iAngle;ia++) {
polarGreenMap= new int [iRadiusPlus1*(iAngle+1)][]; a=ia*aStep;
initAliasMaps(0); cos=Math.cos(a);
polarRedBlueMap=new int [iRadiusPlus1*(iAngle+1)][]; sin=Math.sin(a);
initAliasMaps(1); for (ir=0;ir<iRadiusPlus1;ir++) {
} PolarIndex=ia*iRadiusPlus1+ir;
r=ir*rStep;
public double [] testMapsLengths(int mode) { // 0 - return lengths of "sameCartesian[]", 1 - same for polarGreenMap dy=r*sin;
int [][] map= (mode==0)?sameCartesian:((mode==1)?polarGreenMap:polarRedBlueMap); y=(int) Math.round(dy);
double [] result = new double [map.length]; dy-=y;
for (int i=0; i<map.length;i++) { i=size/2-y;
result[i]=(map[i]==null)?0.0:map[i].length; dx=r*cos;
} x=(int) Math.round(dx);
return result; dx-=x;
} j=x+size/2;
CartesianIndex=i*size+j;
public double [] testGreenMap(int ia, int ir) { polar2CartesianIndices[PolarIndex][0]=CartesianIndex;
double [] result = new double [polarGreenMap.length]; polarList[CartesianIndex].add(PolarIndex);
int i; if (dx<0) {
for ( i=0; i<result.length;i++) result[i]=0.0; polar2CartesianIndices[PolarIndex][1]=polar2CartesianIndices[PolarIndex][0]-1;
int index=ia*iRadiusPlus1+ir; dx=-dx;
if (polarGreenMap[index]!=null){ } else {
for (i=0;i<polarGreenMap[index].length;i++) result [polarGreenMap[index][i]]+=1.0; polar2CartesianIndices[PolarIndex][1]=polar2CartesianIndices[PolarIndex][0]+1;
System.out.println("testGreenMap("+ia+","+ir+"): polarGreenMap["+index+"].length="+polarGreenMap[index].length); }
} else { if (dy<0) {
System.out.println("testGreenMap("+ia+","+ir+"): polarGreenMap["+index+"]=null"); polar2CartesianIndices[PolarIndex][2]=polar2CartesianIndices[PolarIndex][0]+size;
} polar2CartesianIndices[PolarIndex][3]=polar2CartesianIndices[PolarIndex][1]+size;
result [index]=-1.0; dy=-dy;
return result; } else {
} polar2CartesianIndices[PolarIndex][2]=polar2CartesianIndices[PolarIndex][0]-size;
polar2CartesianIndices[PolarIndex][3]=polar2CartesianIndices[PolarIndex][1]-size;
public double [] testRedBlueMap(int ia, int ir) { }
double [] result = new double [polarRedBlueMap.length]; polar2CartesianFractions[PolarIndex][0]=dx;
int i; polar2CartesianFractions[PolarIndex][1]=dy;
for ( i=0; i<result.length;i++) result[i]=0.0; }
int index=ia*iRadiusPlus1+ir; }
if (polarRedBlueMap[index]!=null){ for (i=0;i<length;i++) {
for (i=0;i<polarRedBlueMap[index].length;i++) result [polarRedBlueMap[index][i]]+=1.0; y=size/2-(i/size);
System.out.println("testRedBlueMap("+ia+","+ir+"): polarRedBlueMap["+index+"].length="+polarRedBlueMap[index].length); x=(i % size)- size/2;
} else { r=Math.sqrt(x*x+y*y);
System.out.println("testRedBlueMap("+ia+","+ir+"): polarRedBlueMap["+index+"]=null"); a=Math.atan2(y,x);
} if (a<0) a+=2*Math.PI;
result [index]=-1.0; ir =(int) Math.round(r/rStep);
return result; ia= (int) Math.round(a/aStep);
} if ((ir>=0) && (ir<iRadiusPlus1) && (ia>=0) && (ia<=iAngle)) {
cartesian2PolarIndex[i]=ia*iRadiusPlus1+ir;
if (polarList[i].size()==0) cartesian2PolarIndices[i]=null;
/* Create per-polar pixel list of aliases for green Bayer. For each polar point it shows the polar coordinates of the same (and rotated by pi) point of aliases */ else {
/* current implementation - us cartesian (original) pixels as all/nothing, maybe it makes sense to go directly polar-polar, but then it may leave gaps */ cartesian2PolarIndices[i]=new int[polarList[i].size()];
public void initAliasMaps (int type) { // 0 - green, 1 - Red/Blue j=0;
int [][] aliasMapGreen= {{-2,-2},{-2,0}, // using rollover, so only unique aliases are needed for (Integer val : polarList[i]) cartesian2PolarIndices[i][j++]=val;
{-1,-1},{-1,1}, }
{ 0,-2}, } else {
{ 1,-1},{ 1,1}}; cartesian2PolarIndex[i]=-1; // invalid
int [][] aliasMapRedBlue={{-2,-2},{-2,-1},{-2,0},{-2,1}, cartesian2PolarIndices[i]=null;
{-1,-2},{-1,-1},{-1,0},{-1,1}, }
{ 0,-2},{ 0,-1}, { 0,1}, }
{ 1,-2},{ 1,-1},{ 1,0},{ 1,1}}; initSameCartesian();
int [][] aliasMap=(type>0)?aliasMapRedBlue:aliasMapGreen; polarGreenMap= new int [iRadiusPlus1*(iAngle+1)][];
int [][] polarMap=(type>0)?polarRedBlueMap: polarGreenMap; initAliasMaps(0);
HashSet <Integer> aliasList=new HashSet <Integer>(); polarRedBlueMap=new int [iRadiusPlus1*(iAngle+1)][];
int j,ix,iy, nAlias, dirAlias,ixa,iya, index, polarIndex; initAliasMaps(1);
for (polarIndex=0;polarIndex<polarMap.length;polarIndex++) { }
iy= size/2- (polar2CartesianIndices[polarIndex][0] / size);
ix= (polar2CartesianIndices[polarIndex][0] % size)-size/2 ; public double [] testMapsLengths(int mode) { // 0 - return lengths of "sameCartesian[]", 1 - same for polarGreenMap
aliasList.clear(); int [][] map= (mode==0)?sameCartesian:((mode==1)?polarGreenMap:polarRedBlueMap);
for (nAlias=0;nAlias<aliasMap.length;nAlias++) for (dirAlias=-1;dirAlias<2;dirAlias+=2) { double [] result = new double [map.length];
ixa=(size+ size/2+ aliasMap[nAlias][0]*size/4+ dirAlias*ix) % size; for (int i=0; i<map.length;i++) {
iya=(size+ size/2- aliasMap[nAlias][1]*size/4- dirAlias*iy) % size; result[i]=(map[i]==null)?0.0:map[i].length;
index=iya*size + ixa; }
if (cartesian2PolarIndices[index]==null) { return result;
if (cartesian2PolarIndex[index]>=0) { }
aliasList.add (new Integer(cartesian2PolarIndex[index]));
} public double [] testGreenMap(int ia, int ir) {
} else { double [] result = new double [polarGreenMap.length];
for (j=0;j<cartesian2PolarIndices[index].length;j++) { int i;
aliasList.add (new Integer(cartesian2PolarIndices[index][j])); for ( i=0; i<result.length;i++) result[i]=0.0;
} int index=ia*iRadiusPlus1+ir;
} if (polarGreenMap[index]!=null){
} for (i=0;i<polarGreenMap[index].length;i++) result [polarGreenMap[index][i]]+=1.0;
/* convert set to int[] */ System.out.println("testGreenMap("+ia+","+ir+"): polarGreenMap["+index+"].length="+polarGreenMap[index].length);
if (aliasList.size()==0) polarMap[polarIndex]=null; } else {
else { System.out.println("testGreenMap("+ia+","+ir+"): polarGreenMap["+index+"]=null");
polarMap[polarIndex]=new int[aliasList.size()]; }
j=0; result [index]=-1.0;
for (Integer val : aliasList) polarMap[polarIndex][j++]=val; return result;
} }
}
} public double [] testRedBlueMap(int ia, int ir) {
double [] result = new double [polarRedBlueMap.length];
public void initSameCartesian () { int i;
int i,j, polarIndex, cartesianIndex; for ( i=0; i<result.length;i++) result[i]=0.0;
sameCartesian=new int [iRadiusPlus1*(iAngle+1)][]; int index=ia*iRadiusPlus1+ir;
for (polarIndex=0;polarIndex<sameCartesian.length;polarIndex++) { if (polarRedBlueMap[index]!=null){
cartesianIndex=polar2CartesianIndices[polarIndex][0]; for (i=0;i<polarRedBlueMap[index].length;i++) result [polarRedBlueMap[index][i]]+=1.0;
if ((cartesian2PolarIndices[cartesianIndex]==null) || (cartesian2PolarIndices[cartesianIndex].length<=1)) sameCartesian[polarIndex]=null; System.out.println("testRedBlueMap("+ia+","+ir+"): polarRedBlueMap["+index+"].length="+polarRedBlueMap[index].length);
else { } else {
sameCartesian[polarIndex]=new int [cartesian2PolarIndices[cartesianIndex].length-1]; System.out.println("testRedBlueMap("+ia+","+ir+"): polarRedBlueMap["+index+"]=null");
j=0; }
/* copy all elements but this one - out of bounds may mean that it was not included - bug */ result [index]=-1.0;
for (i=0;i<cartesian2PolarIndices[cartesianIndex].length;i++) if (cartesian2PolarIndices[cartesianIndex][i]!=polarIndex) sameCartesian[polarIndex][j++]=cartesian2PolarIndices[cartesianIndex][i]; return result;
} }
}
}
} /* Create per-polar pixel list of aliases for green Bayer. For each polar point it shows the polar coordinates of the same (and rotated by pi) point of aliases */
/* current implementation - us cartesian (original) pixels as all/nothing, maybe it makes sense to go directly polar-polar, but then it may leave gaps */
public void initAliasMaps (int type) { // 0 - green, 1 - Red/Blue
int [][] aliasMapGreen= {{-2,-2},{-2,0}, // using rollover, so only unique aliases are needed
{-1,-1},{-1,1},
{ 0,-2},
{ 1,-1},{ 1,1}};
int [][] aliasMapRedBlue={{-2,-2},{-2,-1},{-2,0},{-2,1},
{-1,-2},{-1,-1},{-1,0},{-1,1},
{ 0,-2},{ 0,-1}, { 0,1},
{ 1,-2},{ 1,-1},{ 1,0},{ 1,1}};
int [][] aliasMap=(type>0)?aliasMapRedBlue:aliasMapGreen;
int [][] polarMap=(type>0)?polarRedBlueMap: polarGreenMap;
HashSet <Integer> aliasList=new HashSet <Integer>();
int j,ix,iy, nAlias, dirAlias,ixa,iya, index, polarIndex;
for (polarIndex=0;polarIndex<polarMap.length;polarIndex++) {
iy= size/2- (polar2CartesianIndices[polarIndex][0] / size);
ix= (polar2CartesianIndices[polarIndex][0] % size)-size/2 ;
aliasList.clear();
for (nAlias=0;nAlias<aliasMap.length;nAlias++) for (dirAlias=-1;dirAlias<2;dirAlias+=2) {
ixa=(size+ size/2+ aliasMap[nAlias][0]*size/4+ dirAlias*ix) % size;
iya=(size+ size/2- aliasMap[nAlias][1]*size/4- dirAlias*iy) % size;
index=iya*size + ixa;
if (cartesian2PolarIndices[index]==null) {
if (cartesian2PolarIndex[index]>=0) {
aliasList.add (new Integer(cartesian2PolarIndex[index]));
}
} else {
for (j=0;j<cartesian2PolarIndices[index].length;j++) {
aliasList.add (new Integer(cartesian2PolarIndices[index][j]));
}
}
}
/* convert set to int[] */
if (aliasList.size()==0) polarMap[polarIndex]=null;
else {
polarMap[polarIndex]=new int[aliasList.size()];
j=0;
for (Integer val : aliasList) polarMap[polarIndex][j++]=val;
}
}
}
public void initSameCartesian () {
int i,j, polarIndex, cartesianIndex;
sameCartesian=new int [iRadiusPlus1*(iAngle+1)][];
for (polarIndex=0;polarIndex<sameCartesian.length;polarIndex++) {
cartesianIndex=polar2CartesianIndices[polarIndex][0];
if ((cartesian2PolarIndices[cartesianIndex]==null) || (cartesian2PolarIndices[cartesianIndex].length<=1)) sameCartesian[polarIndex]=null;
else {
sameCartesian[polarIndex]=new int [cartesian2PolarIndices[cartesianIndex].length-1];
j=0;
/* copy all elements but this one - out of bounds may mean that it was not included - bug */
for (i=0;i<cartesian2PolarIndices[cartesianIndex].length;i++) if (cartesian2PolarIndices[cartesianIndex][i]!=polarIndex) sameCartesian[polarIndex][j++]=cartesian2PolarIndices[cartesianIndex][i];
}
}
}
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment