001    package util.sdss;
002    
003    import java.text.DecimalFormat;
004    import org.eso.fits.*;
005    import java.util.*;
006    
007    /**
008     * A data container to hold the emission line instances and hold a reference
009     * to the source star.
010     */
011    public class Line implements Comparable<Line> {
012    
013        static DecimalFormat formatter = new DecimalFormat("0.00");
014    
015        Star source;
016        
017        public double wavelength;         // Line center
018        public double wavelengthErr;      // Error in line center
019        public double sigma;              // Sigma of fitted Gaussian 
020        public double sigmaErr;           // Error in sigma
021        public double height;             // Height of gaussian  (10^-17 ergs/s/cm^2/Å)
022        public double heightErr;          // Error in height
023        public double equivalentWitdth;   // Equivalent width
024        public double equivalentWitdthErr;// Error in equivalent width
025        public double continuum;          // Value of continuum at line center (10^-17 ergs/s/cm^2/Å)
026        public double index;              // Spectral index
027        public double significance;       // Significance of line in number of sigma
028    
029        //double redshift;
030    
031        public Line(Star aSource, double aWavelength,
032                                  double aWavelengthErr,
033                                  double aSigma,
034                                  double aSigmaErr,
035                                  double aHeight,
036                                  double aHeightErr,
037                                  double anEquivalentWitdth,
038                                  double anEquivalentWitdthErr,
039                                  double aContinuum,
040                                  double anIndex,
041                                  double aSignificance) {
042            source = aSource;
043            wavelength = aWavelength;
044            wavelengthErr = aWavelengthErr;
045            sigma = aSigma;
046            sigmaErr = aSigmaErr;
047            height = aHeight;
048            heightErr = aHeightErr;
049            equivalentWitdth = anEquivalentWitdth;
050            equivalentWitdthErr = anEquivalentWitdthErr;
051            continuum = aContinuum;
052            index = anIndex;
053            significance = aSignificance;      
054        }
055    
056        public Line(Star aSource, double aWavelength) {
057            source = aSource;
058            wavelength = aWavelength;
059        }
060    
061        public Star getSource() {
062            return source;
063        }
064    
065        /** Get the emission line wavelength as centroid of the fitted gaussian line profile */
066        public double getWavelength() {
067            return wavelength;
068        }
069    
070        static double gaussianFactor = Math.sqrt(2.0*Math.PI);
071    
072        /** Get the emission strength as area under the fitted gaussian line profile */
073        public double getStrength() {
074            return height * sigma * gaussianFactor;
075        }
076    
077        public static List<Line> getLines(Star aSource, FitsTable table) {
078            List<Line> lines = new ArrayList<Line>();    
079            for (int i = 0; i < table.getNoRows(); i++) {
080                Line line = new Line(aSource,
081                     table.getColumn(0).getReal(i),
082                     table.getColumn(1).getReal(i),
083                     table.getColumn(4).getReal(i),
084                     table.getColumn(5).getReal(i),
085                     table.getColumn(8).getReal(i),
086                     table.getColumn(9).getReal(i),
087                     table.getColumn(11).getReal(i),
088                     table.getColumn(12).getReal(i),
089                     table.getColumn(10).getReal(i),
090                     table.getColumn(14).getReal(i),
091                     table.getColumn(15).getReal(i));
092                lines.add(line);
093            }
094            return lines;
095        }
096    
097        /** Show emission lines, for testing purposes only */
098        public static void showLines(FitsTable dm) {
099            int nrow = dm.getNoRows();
100            int ncol = dm.getNoColumns();
101            FitsColumn col[] = new FitsColumn[ncol];
102            System.out.println("  Columns: " + ncol + ", Rows: " + nrow);
103            for (int n = 0; n < ncol; n++) {
104                col[n] = dm.getColumn(n);
105                System.out.print("  " + n + " >" + col[n].getLabel() + "<, ");
106                System.out.print(col[n].getRepeat() + " ");
107                System.out.print(col[n].getDataType() + ", >");
108                System.out.print(col[n].getDisplay() + "<, >");
109                System.out.println(col[n].getUnit() + "<");
110                if (col[n].getDataType() == 'F' || col[n].getDataType() == 'E' || col[n].getDataType() == 'D') {
111                    int npix = 0;
112                    double mean, rms, val;
113                    mean = rms = 0.0;
114                    for (int nr=0; nr<nrow; nr++) {
115                        val = col[n].getReal(nr);
116                        if ("wave".equals(col[n].getLabel())) System.out.println(val);
117                        if (Double.isNaN(val)) continue;
118                        npix++;
119                        mean += val;
120                        rms  += val*val;
121                    }
122                    mean = mean/npix;
123                    rms  = rms/npix - mean*mean;
124                    rms = ((0.0<rms) ? Math.sqrt(rms) : 0.0);
125                    System.out.println("      no,mean,rms: " + npix + ", " + (float)mean + ", " + (float)rms);
126                } else if (col[n].getDataType() == 'I' || col[n].getDataType() == 'J' || col[n].getDataType() == 'B') {
127                    int npix = 0;
128                    double mean, rms, val;
129                    mean = rms = 0.0;
130                    for (int nr=0; nr<nrow; nr++) {
131                        val = col[n].getInt(nr);
132                        if (val == Long.MIN_VALUE) continue;
133                        npix++;
134                        mean += val;
135                        rms  += val*val;
136                    }
137                    mean = mean/npix;
138                    rms  = rms/npix - mean*mean;
139                    rms = ((0.0<rms) ? Math.sqrt(rms) : 0.0);
140                    System.out.println("      no,mean,rms: " + npix + ", " + (float)mean + ", " + (float)rms);
141                }
142            }
143        }
144    
145        /** default comparator is based on line wavelength */
146        public int compareTo(Line aLine) {
147            return WAVELENGTH_COMPARATOR.compare(this, aLine);
148        }
149    
150        /** Comparator based on line wavelength. */
151        public static final Comparator<Line> WAVELENGTH_COMPARATOR = new Comparator<Line>() {
152           public int compare(Line line1, Line line2) {
153               if (line1 == null || line2 == null) throw(new NullPointerException("Compare to null Line instance"));
154               return (int)(line2.getWavelength() - line1.getWavelength());   
155           }
156           public boolean equals(Object obj) {
157               return this == obj;
158           }
159        };
160    
161        /** Comparator based on line width. */
162        public static final Comparator<Line> WIDTH_COMPARATOR = new Comparator<Line>() {
163           public int compare(Line line1, Line line2) {
164               if (line1 == null || line2 == null) throw(new NullPointerException("Compare to null Line instance"));
165               return (int)(line2.sigma - line1.sigma);      
166           }
167           public boolean equals(Object obj) {
168               return this == obj;
169           }
170        };
171    
172        /** Comparator based on line strength. Useful only for lines in the same star. */
173        public static final Comparator<Line> STRENGTH_COMPARATOR = new Comparator<Line>() {
174           public int compare(Line line1, Line line2) {
175               if (line1 == null || line2 == null) throw(new NullPointerException("Compare to null Line instance"));
176               return (int)(line2.getStrength() - line1.getStrength());
177           }
178           public boolean equals(Object obj) {
179               return this == obj;
180           }
181        };
182    
183        /** Comparator based on line height. Useful only for lines in the same star. */
184        public static final Comparator<Line> HEIGHT_COMPARATOR = new Comparator<Line>() {
185           public int compare(Line line1, Line line2) {
186               if (line1 == null || line2 == null) throw(new NullPointerException("Compare to null Line instance"));
187               return (int)(line2.height - line1.height); 
188           }
189           public boolean equals(Object obj) {
190               return this == obj;
191           }
192        };
193    
194        //TODO: make this more flexible
195        public String toString() {
196            String wavelengthString = formatter.format(getWavelength());
197            if (wavelengthString.length() == 7) wavelengthString = " " + wavelengthString;
198            return wavelengthString;
199        }
200    }