001 package edu.nrao.sss.astronomy; 002 003 import static java.math.BigDecimal.ONE; 004 import static java.math.BigDecimal.ZERO; 005 006 import java.math.BigDecimal; 007 008 import static edu.nrao.sss.math.MathUtil.MC_INTERM_CALCS; 009 import static edu.nrao.sss.math.MathUtil.POSITIVE_INFINITY; 010 import static edu.nrao.sss.measure.Wave.LIGHT_SPEED_VACUUM_KM_PER_SEC; 011 012 import edu.nrao.sss.math.MathUtil; 013 import edu.nrao.sss.measure.LinearVelocity; 014 import edu.nrao.sss.measure.LinearVelocityUnits; 015 import edu.nrao.sss.util.EnumerationUtility; 016 017 /** 018 * A convention used to convert a rest frequency to a sky frequency. 019 * <p> 020 * A discussion of these conventions may be found at 021 * <a href="http://iram.fr/IRAMFR/ARN/may95/node4.html"> 022 * http://iram.fr/IRAMFR/ARN/may95/node4.html</a> and 023 * <a href="http://www.gb.nrao.edu/~fghigo/gbtdoc/doppler.html"> 024 * http://www.gb.nrao.edu/~fghigo/gbtdoc/doppler.html</a>.</p> 025 * <p> 026 * <b>Version Info:</b> 027 * <table style="margin-left:2em"> 028 * <tr><td>$Revision: 1572 $</td></tr> 029 * <tr><td>$Date: 2008-09-22 16:52:39 -0600 (Mon, 22 Sep 2008) $</td></tr> 030 * <tr><td>$Author: dharland $</td></tr> 031 * </table></p> 032 * 033 * @author David M. Harland 034 * @since 2006-03-31 035 */ 036 public enum VelocityConvention 037 { 038 /** 039 * The optical astronomy 040 * convention for converting a rest frequency to a sky frequency. 041 * <p> 042 * <u>Convention:</u> 043 * <blockquote> 044 * f<sub>sky</sub> = f<sub>rest</sub> * (1 + v/c)<sup>-1</sup> 045 * </blockquote></p> 046 */ 047 OPTICAL(LinearVelocityUnits.KILOMETERS_PER_SECOND) 048 { 049 public BigDecimal getFrequencyShiftFactor(BigDecimal kmPerSec) 050 { 051 //f.sky / f.rest = 1 / (1 + v/c) 052 053 BigDecimal denominator = 054 ONE.add(kmPerSec.divide(LIGHT_SPEED_VACUUM_KM_PER_SEC, 055 MC_INTERM_CALCS)); 056 057 if (denominator.signum() <= 0) 058 return MathUtil.POSITIVE_INFINITY; 059 else 060 return ONE.divide(denominator, MC_INTERM_CALCS); 061 } 062 063 public LinearVelocity getVelocity(BigDecimal f) 064 { 065 //v = [(1-f)/f] * c 066 067 BigDecimal kms; 068 069 if (f.signum() == 0) 070 kms = MathUtil.POSITIVE_INFINITY; 071 else 072 kms = ONE.subtract(f).divide(f, MC_INTERM_CALCS) 073 .multiply(LIGHT_SPEED_VACUUM_KM_PER_SEC); 074 075 return new LinearVelocity(kms, getDefaultUnits()); 076 } 077 }, 078 079 /** 080 * The radio astronomy 081 * convention for converting a rest frequency to a sky frequency. 082 * <p> 083 * <u>Convention:</u> 084 * <blockquote> 085 * f<sub>sky</sub> = f<sub>rest</sub> * (1 - v/c) 086 * </blockquote></p> 087 */ 088 RADIO(LinearVelocityUnits.KILOMETERS_PER_SECOND) 089 { 090 public BigDecimal getFrequencyShiftFactor(BigDecimal kmPerSec) 091 { 092 //f.sky / f.rest = 1 - v/c 093 094 if (kmPerSec.compareTo(LIGHT_SPEED_VACUUM_KM_PER_SEC) >= 0) 095 return BigDecimal.ZERO; 096 else 097 return ONE.subtract(kmPerSec.divide(LIGHT_SPEED_VACUUM_KM_PER_SEC, 098 MC_INTERM_CALCS)); 099 } 100 101 public LinearVelocity getVelocity(BigDecimal f) 102 { 103 //v = (1-f) * c 104 105 BigDecimal kms = ONE.subtract(f).multiply(LIGHT_SPEED_VACUUM_KM_PER_SEC); 106 107 return new LinearVelocity(kms, getDefaultUnits()); 108 } 109 }, 110 111 /** 112 * The red shift 113 * convention for converting a rest frequency to a sky frequency. 114 * <p> 115 * <u>Convention:</u> 116 * <blockquote> 117 * f<sub>sky</sub> = f<sub>rest</sub> * (1 + z)<sup>-1</sup> 118 * </blockquote></p> 119 */ 120 REDSHIFT(LinearVelocityUnits.Z) 121 { 122 public BigDecimal getFrequencyShiftFactor(BigDecimal z) 123 { 124 //f.sky / f.rest = 1 / (1+z) 125 126 if (z.compareTo(ONE.negate()) <= 0) 127 return ZERO; 128 else 129 return ONE.divide(ONE.add(z), MC_INTERM_CALCS); 130 } 131 132 public LinearVelocity getVelocity(BigDecimal f) 133 { 134 //z = (1-f) / f 135 136 BigDecimal z; 137 138 if (f.signum() == 0) 139 z = POSITIVE_INFINITY; 140 else 141 z = ONE.subtract(f).divide(f, MC_INTERM_CALCS); 142 143 return new LinearVelocity(z, getDefaultUnits()); 144 } 145 }, 146 147 /** 148 * The relativistic 149 * convention for converting a rest frequency to a sky frequency. 150 * <p> 151 * <u>Convention:</u> 152 * <blockquote> 153 * f<sub>sky</sub> = f<sub>rest</sub> * 154 * (1 - (v/c)<sup>2</sup>)<sup>½</sup> / (1 + v/c) 155 * </blockquote></p> 156 */ 157 RELATIVISTIC(LinearVelocityUnits.KILOMETERS_PER_SECOND) 158 { 159 public BigDecimal getFrequencyShiftFactor(BigDecimal kmPerSec) 160 { 161 //f.sky / f.rest = sqrt[1 - (v/c)*(v/c)] / (1 + v/c) 162 163 BigDecimal answer; 164 165 BigDecimal c = LIGHT_SPEED_VACUUM_KM_PER_SEC; 166 167 if (kmPerSec.compareTo(c) >= 0) 168 { 169 answer = BigDecimal.ZERO; 170 } 171 else if (kmPerSec.compareTo(c.negate()) <= 0) 172 { 173 answer = MathUtil.POSITIVE_INFINITY; 174 } 175 else 176 { 177 BigDecimal vOverC = kmPerSec.divide(c, MC_INTERM_CALCS); 178 BigDecimal numSq = ONE.subtract(vOverC.multiply(vOverC)); 179 BigDecimal numerator = BigDecimal.valueOf(Math.sqrt(numSq.doubleValue())); 180 BigDecimal denominator = ONE.add(vOverC); 181 182 answer = numerator.divide(denominator, MC_INTERM_CALCS); 183 } 184 185 return answer; 186 } 187 188 public LinearVelocity getVelocity(BigDecimal f) 189 { 190 //v = [(1-f*f) / (1+f*f)] * c 191 192 BigDecimal fSq = f.multiply(f); 193 BigDecimal fNum = ONE.subtract(fSq); 194 BigDecimal fDenom = ONE.add(fSq); 195 BigDecimal kms = fNum.divide(fDenom, MC_INTERM_CALCS) 196 .multiply(LIGHT_SPEED_VACUUM_KM_PER_SEC); 197 198 return new LinearVelocity(kms, getDefaultUnits()); 199 } 200 }; 201 202 //============================================================================ 203 // 204 //============================================================================ 205 206 private LinearVelocityUnits defaultUnits; 207 208 private VelocityConvention(LinearVelocityUnits defaultUnits) 209 { 210 this.defaultUnits = defaultUnits; 211 } 212 213 /** 214 * Returns the default velocity units used by this convention. 215 * 216 * @return the default velocity units used by this convention. 217 */ 218 public LinearVelocityUnits getDefaultUnits() 219 { 220 return defaultUnits; 221 } 222 223 /** 224 * Returns a factor that can be used to shift a rest frequency to one 225 * appropriate for the given velocity. 226 * The velocity value sent to this method will be assumed to be in 227 * the default units of this convention. 228 * <p> 229 * See the descriptions of the individual elements of this enumeration 230 * for the formula used by a given convention.</p> 231 * 232 * @param velocityInDefaultUnits the velocity, in the default units of this 233 * convention, for which a frequency-shifting 234 * factor is desired. 235 */ 236 public abstract BigDecimal 237 getFrequencyShiftFactor(BigDecimal velocityInDefaultUnits); 238 239 /** 240 * Returns the velocity for the given shift factor. 241 * Positive values represent motion away from the observer. 242 * 243 * @param shiftFactor the ratio between the observed frequency and the 244 * rest frequency. 245 * 246 * @return the velocity for the given shift factor. 247 */ 248 public abstract LinearVelocity getVelocity(BigDecimal shiftFactor); 249 250 /** 251 * Returns a factor that can be used to shift a rest frequency to one 252 * appropriate for the given velocity. 253 * 254 * @param velocity the velocity for which a frequency-shifting factor 255 * is desired. 256 * 257 * @return a factor that can be used to shift a rest frequency to one 258 * appropriate for the given velocity. 259 * If {@code velocity} is <i>null</i>, a factor of one will be 260 * returned. 261 */ 262 public BigDecimal getFrequencyShiftFactor(LinearVelocity velocity) 263 { 264 return (velocity == null) ? ONE : 265 getFrequencyShiftFactor(velocity.toUnits(getDefaultUnits())); 266 } 267 268 /** 269 * Returns a default velocity convention. 270 * @return a default velocity convention. 271 */ 272 public static VelocityConvention getDefault() 273 { 274 return RADIO; 275 } 276 277 /** 278 * Returns a text representation of this enumeration constant. 279 * @return a text representation of this enumeration constant. 280 */ 281 public String toString() 282 { 283 return EnumerationUtility.getSharedInstance().enumToString(this); 284 } 285 286 /** 287 * Returns the velocity convention represented by {@code text}. 288 * <p> 289 * For details about the transformation, see 290 * {@link EnumerationUtility#enumFromString(Class, String)}.</p> 291 * 292 * @param text a text representation of a velocity convention. 293 * 294 * @return the velocity convention represented by {@code text}. 295 */ 296 public static VelocityConvention fromString(String text) 297 { 298 return EnumerationUtility.getSharedInstance() 299 .enumFromString(VelocityConvention.class, text); 300 } 301 }