View Javadoc

1   package org.lcsim.recon.tracking.magfield;
2   
3   import java.io.*;
4   import java.util.ArrayList;
5   import java.util.StringTokenizer;
6   import org.lcsim.recon.tracking.spacegeom.CartesianPointVector;
7   import org.lcsim.recon.tracking.spacegeom.SpacePoint;
8   import org.lcsim.recon.tracking.spacegeom.SpacePointTensor;
9   import org.lcsim.recon.tracking.spacegeom.SpacePointVector;
10  
11  /**
12   *
13   * @author Norman A Graf
14   *
15   * @version $Id:
16   */
17  public class Cartesian3DMagneticFieldMap extends AbstractMagneticField
18  {
19      // Storage space for the table
20  
21      private double[][][] _xField;
22      private double[][][] _yField;
23      private double[][][] _zField;
24      // The dimensions of the table
25      private int _nx, _ny, _nz;
26      // The physical limits of the defined region
27      private double _minx, _maxx, _miny, _maxy, _minz, _maxz;
28      // The physical extent of the defined region
29      private double _dx, _dy, _dz;
30      // Offsets if field map is not in global coordinates
31      private double _xOffset;
32      private double _yOffset;
33      private double _zOffset;
34  
35      public Cartesian3DMagneticFieldMap(InputStream is, double xOffset, double yOffset, double zOffset)
36      {
37          _xOffset = xOffset;
38          _yOffset = yOffset;
39          _zOffset = zOffset;
40  
41          System.out.println("\n-----------------------------------------------------------"
42                  + "\n      Reading Magnetic Field map"
43                  + "\n-----------------------------------------------------------");
44  
45          try {
46              BufferedReader myInput = new BufferedReader(new InputStreamReader(new BufferedInputStream(is)));
47  
48              String thisLine;
49              // ignore the first blank line
50              thisLine = myInput.readLine();
51              // next line has table dimensions
52              thisLine = myInput.readLine();
53              // read in the table dimensions of the file
54              StringTokenizer st = new StringTokenizer(thisLine, " ");
55              _nx = Integer.parseInt(st.nextToken());
56              _ny = Integer.parseInt(st.nextToken());
57              _nz = Integer.parseInt(st.nextToken());
58  
59  
60              // Set up storage space for table
61              _xField = new double[_nx + 1][_ny + 1][_nz + 1];
62              _yField = new double[_nx + 1][_ny + 1][_nz + 1];
63              _zField = new double[_nx + 1][_ny + 1][_nz + 1];
64  
65              // Ignore other header information    
66              // The first line whose second character is '0' is considered to
67              // be the last line of the header.
68              do {
69                  thisLine = myInput.readLine();
70                  st = new StringTokenizer(thisLine, " ");
71              } while (!st.nextToken().trim().equals("0"));
72  
73              // now ready to read in the values in the table
74              // format is:
75              // x y z Bx By Bz
76              //
77              int ix, iy, iz;
78              double xval = 0.;
79              double yval = 0.;
80              double zval = 0.;
81              double bx, by, bz;
82              for (ix = 0; ix < _nx; ix++) {
83                  for (iy = 0; iy < _ny; iy++) {
84                      for (iz = 0; iz < _nz; iz++) {
85                          thisLine = myInput.readLine();
86                          st = new StringTokenizer(thisLine, " ");
87                          xval = Double.parseDouble(st.nextToken());
88                          yval = Double.parseDouble(st.nextToken());
89                          zval = Double.parseDouble(st.nextToken());
90                          bx = Double.parseDouble(st.nextToken());
91                          by = Double.parseDouble(st.nextToken());
92                          bz = Double.parseDouble(st.nextToken());
93                          if (ix == 0 && iy == 0 && iz == 0) {
94                              _minx = xval;
95                              _miny = yval;
96                              _minz = zval;
97                          }
98                          _xField[ix][iy][iz] = bx;
99                          _yField[ix][iy][iz] = by;
100                         _zField[ix][iy][iz] = bz;
101                     }
102                 }
103             }
104 
105             _maxx = xval;
106             _maxy = yval;
107             _maxz = zval;
108 
109             System.out.println("\n ---> ... done reading ");
110             System.out.println(" ---> assumed the order:  x, y, z, Bx, By, Bz "
111                     + "\n ---> Min values x,y,z: "
112                     + _minx + " " + _miny + " " + _minz + " cm "
113                     + "\n ---> Max values x,y,z: "
114                     + _maxx + " " + _maxy + " " + _maxz + " cm "
115                     + "\n ---> The field will be offset by " + _xOffset + " " + _yOffset + " " + _zOffset + " cm ");
116 
117             _dx = _maxx - _minx;
118             _dy = _maxy - _miny;
119             _dz = _maxz - _minz;
120             System.out.println("\n ---> Range of values x,y,z: "
121                     + _dx + " " + _dy + " " + _dz + " cm in z "
122                     + "\n-----------------------------------------------------------");
123 
124             myInput.close();
125         } catch (Exception e) {
126             e.printStackTrace();
127         }
128 
129     }
130 
131     @Override
132     public SpacePointVector field(SpacePoint p)
133     {
134         double x = p.x() + _xOffset;
135         double y = p.y() + _yOffset;
136         double z = p.z() + _zOffset;
137         double[] Bfield = new double[3];
138         // Check that the point is within the defined region 
139         if (x >= _minx && x <= _maxx
140                 && y >= _miny && y <= _maxy
141                 && z >= _minz && z <= _maxz) {
142 
143             // Position of given point within region, normalized to the range
144             // [0,1]
145             double xfraction = (x - _minx) / _dx;
146             double yfraction = (y - _miny) / _dy;
147             double zfraction = (z - _minz) / _dz;
148 
149             double xdindex, ydindex, zdindex;
150 
151             // Position of the point within the cuboid defined by the
152             // nearest surrounding tabulated points
153             double[] xmodf = modf(xfraction * (_nx - 1));
154             double[] ymodf = modf(yfraction * (_ny - 1));
155             double[] zmodf = modf(zfraction * (_nz - 1));
156 
157             // The indices of the nearest tabulated point whose coordinates
158             // are all less than those of the given point
159 
160             int xindex = (int) xmodf[0];
161             int yindex = (int) ymodf[0];
162             int zindex = (int) zmodf[0];
163             double xlocal = xmodf[1];
164             double ylocal = ymodf[1];
165             double zlocal = zmodf[1];
166             // bilinear interpolation
167             Bfield[0] =
168                     _xField[xindex][yindex][zindex] * (1 - xlocal) * (1 - ylocal) * (1 - zlocal)
169                     + _xField[xindex][yindex][zindex + 1] * (1 - xlocal) * (1 - ylocal) * zlocal
170                     + _xField[xindex][yindex + 1][zindex] * (1 - xlocal) * ylocal * (1 - zlocal)
171                     + _xField[xindex][yindex + 1][zindex + 1] * (1 - xlocal) * ylocal * zlocal
172                     + _xField[xindex + 1][yindex][zindex] * xlocal * (1 - ylocal) * (1 - zlocal)
173                     + _xField[xindex + 1][yindex][zindex + 1] * xlocal * (1 - ylocal) * zlocal
174                     + _xField[xindex + 1][yindex + 1][zindex] * xlocal * ylocal * (1 - zlocal)
175                     + _xField[xindex + 1][yindex + 1][zindex + 1] * xlocal * ylocal * zlocal;
176             Bfield[1] =
177                     _yField[xindex][yindex][zindex] * (1 - xlocal) * (1 - ylocal) * (1 - zlocal)
178                     + _yField[xindex][yindex][zindex + 1] * (1 - xlocal) * (1 - ylocal) * zlocal
179                     + _yField[xindex][yindex + 1][zindex] * (1 - xlocal) * ylocal * (1 - zlocal)
180                     + _yField[xindex][yindex + 1][zindex + 1] * (1 - xlocal) * ylocal * zlocal
181                     + _yField[xindex + 1][yindex][zindex] * xlocal * (1 - ylocal) * (1 - zlocal)
182                     + _yField[xindex + 1][yindex][zindex + 1] * xlocal * (1 - ylocal) * zlocal
183                     + _yField[xindex + 1][yindex + 1][zindex] * xlocal * ylocal * (1 - zlocal)
184                     + _yField[xindex + 1][yindex + 1][zindex + 1] * xlocal * ylocal * zlocal;
185             Bfield[2] =
186                     _zField[xindex][yindex][zindex] * (1 - xlocal) * (1 - ylocal) * (1 - zlocal)
187                     + _zField[xindex][yindex][zindex + 1] * (1 - xlocal) * (1 - ylocal) * zlocal
188                     + _zField[xindex][yindex + 1][zindex] * (1 - xlocal) * ylocal * (1 - zlocal)
189                     + _zField[xindex][yindex + 1][zindex + 1] * (1 - xlocal) * ylocal * zlocal
190                     + _zField[xindex + 1][yindex][zindex] * xlocal * (1 - ylocal) * (1 - zlocal)
191                     + _zField[xindex + 1][yindex][zindex + 1] * xlocal * (1 - ylocal) * zlocal
192                     + _zField[xindex + 1][yindex + 1][zindex] * xlocal * ylocal * (1 - zlocal)
193                     + _zField[xindex + 1][yindex + 1][zindex + 1] * xlocal * ylocal * zlocal;
194 
195         } else {
196             Bfield[0] = 0.0;
197             Bfield[1] = 0.0;
198             Bfield[2] = 0.0;
199         }
200 
201         return new CartesianPointVector(p, Bfield[0], Bfield[1], Bfield[2]);
202     }
203 
204     @Override
205     public SpacePointVector field(SpacePoint p, SpacePointTensor g)
206     {
207         throw new UnsupportedOperationException("Not supported yet.");
208     }
209 
210     public double minX()
211     {
212         return _minx + _xOffset;
213     }
214 
215     public double minY()
216     {
217         return _miny + _yOffset;
218     }
219 
220     public double minZ()
221     {
222         return _minz + _zOffset;
223     }
224     
225    public double maxX()
226     {
227         return _maxx + _xOffset;
228     }
229 
230     public double maxY()
231     {
232         return _maxy + _yOffset;
233     }
234 
235     public double maxZ()
236     {
237         return _maxz + _zOffset;
238     }    
239     
240 
241     private double[] modf(double fullDouble)
242     {
243         int intVal = (int) fullDouble;
244         double remainder = fullDouble - intVal;
245 
246         double[] retVal = new double[2];
247         retVal[0] = intVal;
248         retVal[1] = remainder;
249 
250         return retVal;
251     }
252 }