001 package edu.nrao.sss.astronomy; 002 003 import java.math.BigDecimal; 004 005 import edu.nrao.sss.measure.Frequency; 006 import edu.nrao.sss.measure.LinearVelocity; 007 import edu.nrao.sss.measure.LinearVelocityUnits; 008 import edu.nrao.sss.util.StringUtil; 009 010 /** 011 * A spectral line caused by emission or absorption of a photon. 012 * <p> 013 * This class is based on the definition of a spectral line used by the 014 * <a href="http://www.splatalogue.net/">Splatalogue</a>. 015 * <p> 016 * <b>Version Info:</b> 017 * <table style="margin-left:2em"> 018 * <tr><td>$Revision: 1951 $</td></tr> 019 * <tr><td>$Date: 2009-02-03 16:26:19 -0700 (Tue, 03 Feb 2009) $</td></tr> 020 * <tr><td>$Author: dharland $</td></tr> 021 * </table></p> 022 * 023 * @author David M. Harland 024 * @since 2007-02-28 025 */ 026 public class SpectralLine 027 implements Cloneable 028 { 029 private String species; 030 private String transition; 031 private Frequency frequency; 032 private Frequency uncertainty; 033 private String sourceOfInformation; 034 //private Xxx energyOfLowerState; 035 036 /** Creates a new instance. */ 037 public SpectralLine() 038 { 039 species = ""; 040 transition = ""; 041 frequency = new Frequency(); 042 uncertainty = new Frequency(); 043 sourceOfInformation = ""; 044 } 045 046 //============================================================================ 047 // SIMPLE GET/SET PROPERTIES 048 //============================================================================ 049 050 /** 051 * Sets the frequency for this line. 052 * 053 * @param newFrequency the frequency for this line. If this value is 054 * <i>null</i>, it will be replaced with 055 * {@code new Frequency()}. 056 */ 057 public void setFrequency(Frequency newFrequency) 058 { 059 frequency = (newFrequency == null) ? new Frequency() : newFrequency; 060 } 061 062 /** 063 * Returns the frequency of this line. 064 * @return the frequency of this line. 065 */ 066 public Frequency getFrequency() 067 { 068 return frequency; 069 } 070 071 /** 072 * Sets the source of information for this line. 073 * In <i>Splatalogue</i> this corresponds to <i>Line List</i>. 074 * 075 * @param newSource the source of information for this line. If this value is 076 * <i>null</i>, it will be replaced with the empty string 077 * (<tt>""</tt>). 078 */ 079 public void setSourceOfInformation(String newSource) 080 { 081 sourceOfInformation = newSource; 082 } 083 084 /** 085 * Returns the source of information of this line. 086 * @return the source of information of this line. 087 */ 088 public String getSourceOfInformation() 089 { 090 return sourceOfInformation; 091 } 092 093 /** 094 * Sets the species for this line. 095 * This is the atom or molecule that causes this line 096 * 097 * @param newSpecies the source of this line. If this value is 098 * <i>null</i>, it will be replaced with the empty string 099 * (<tt>""</tt>). 100 */ 101 public void setSpecies(String newSpecies) 102 { 103 species = (newSpecies == null) ? "" : newSpecies; 104 } 105 106 /** 107 * Returns the atom or molecule that generates this line. 108 * @return the atom or molecule that generates this line. 109 */ 110 public String getSpecies() 111 { 112 return species; 113 } 114 115 /** 116 * Sets the transition for this line. 117 * 118 * @param newTransition the transition that causes this line. 119 * If this value <i>null</i>, 120 * it will be replaced with the empty string 121 * (<tt>""</tt>). 122 */ 123 public void setTransition(String newTransition) 124 { 125 transition = (newTransition == null) ? "" : newTransition; 126 } 127 128 /** 129 * Returns the transition that causes this line. 130 * @return the transition that causes this line. 131 */ 132 public String getTransition() 133 { 134 return transition; 135 } 136 137 /** 138 * Sets the uncertainty in the frequency of this line. 139 * 140 * @param newValue the uncertainty in the frequency of this line. 141 * If this value is <i>null</i>, it will be replaced with 142 * {@code new Frequency()}. 143 */ 144 public void setUncertainty(Frequency newValue) 145 { 146 uncertainty = (newValue == null) ? new Frequency() : newValue; 147 } 148 149 /** 150 * Returns the uncertainty in the frequency of this line. 151 * @return the uncertainty in the frequency of this line. 152 */ 153 public Frequency getUncertainty() 154 { 155 return uncertainty; 156 } 157 158 //============================================================================ 159 // 160 //============================================================================ 161 162 /** 163 * Returns the apparent frequency of this line if its source is moving 164 * relative to the observer. 165 * 166 * @param radialVelocity 167 * the velocity of the source of this line away from (positive values) 168 * or toward (negative values) the observer. Note that this is the 169 * component of the source's velocity directly away from or toward 170 * the observer. If this value is <i>null</i> it will be treated as 171 * a velocity of zero. 172 * 173 * @param convention 174 * the convention to use when using <tt>radialVelocity</tt> to calculate 175 * the shifted frequency. If this value is <i>null</i>, the redshift 176 * convention will be used if the velocity is in units of Z and 177 * the radio convention will be used if it is in any other units. 178 * 179 * @return 180 * the frequency of this line shifted for the given velocity. 181 */ 182 public Frequency getShiftedFrequency(LinearVelocity radialVelocity, 183 VelocityConvention convention) 184 { 185 BigDecimal shiftFactor = BigDecimal.ONE; 186 187 if (radialVelocity != null) 188 { 189 if (convention == null) 190 convention = radialVelocity.getUnits().equals(LinearVelocityUnits.Z) ? 191 VelocityConvention.REDSHIFT : VelocityConvention.RADIO; 192 193 shiftFactor = convention.getFrequencyShiftFactor(radialVelocity); 194 } 195 196 return frequency.clone().multiplyBy(shiftFactor); 197 } 198 199 //============================================================================ 200 // 201 //============================================================================ 202 203 /** Returns a text representation of this spectral line. */ 204 @Override 205 public String toString() 206 { 207 StringBuilder buff = new StringBuilder(); 208 209 final String EOL = StringUtil.EOL; 210 211 buff.append("Species: ").append(species).append(EOL); 212 buff.append("Transition: ").append(transition).append(EOL); 213 buff.append("Frequency: ").append(frequency).append(EOL); 214 buff.append("Uncertainty: ").append(uncertainty).append(EOL); 215 buff.append("Source of Info: ").append(sourceOfInformation).append(EOL); 216 217 return buff.toString(); 218 } 219 220 /** 221 * Returns a spectral line that is a copy of this one. 222 * <p> 223 * If anything goes wrong during the cloning procedure, 224 * a {@code RuntimeException} will be thrown.</p> 225 */ 226 @Override 227 public SpectralLine clone() 228 { 229 SpectralLine clone = null; 230 231 try 232 { 233 clone = (SpectralLine)super.clone(); 234 235 clone.frequency = this.frequency.clone(); 236 clone.uncertainty = this.uncertainty.clone(); 237 } 238 catch (Exception ex) 239 { 240 throw new RuntimeException(ex); 241 } 242 243 return clone; 244 } 245 246 /** Returns <i>true</i> if {@code o} is equal to this spectral line. */ 247 @Override 248 public boolean equals(Object o) 249 { 250 //Quick exit if o is this 251 if (o == this) 252 return true; 253 254 //Quick exit if o is null 255 if (o == null) 256 return false; 257 258 //Quick exit if classes are different 259 if (!o.getClass().equals(this.getClass())) 260 return false; 261 262 //A safe cast if we got this far 263 SpectralLine other = (SpectralLine)o; 264 265 return other.species.equals (this.species) && 266 other.transition.equals (this.transition) && 267 other.sourceOfInformation.equals(this.sourceOfInformation) && 268 other.frequency.equals (this.frequency) && 269 other.uncertainty.equals (this.uncertainty); 270 } 271 272 /** Returns a hash code value for this spectral line. */ 273 @Override 274 public int hashCode() 275 { 276 //Taken from the Effective Java book by Joshua Bloch. 277 //The constants 17 & 37 are arbitrary & carry no meaning. 278 int result = 17; 279 280 //This method MUST be kept in synch w/ the equals method. 281 282 result = 37 * result + species.hashCode(); 283 result = 37 * result + transition.hashCode(); 284 result = 37 * result + sourceOfInformation.hashCode(); 285 result = 37 * result + frequency.hashCode(); 286 result = 37 * result + uncertainty.hashCode(); 287 288 return result; 289 } 290 }