001 package edu.nrao.sss.astronomy; 002 003 import java.util.Date; 004 005 import edu.nrao.sss.geom.EarthPosition; 006 import edu.nrao.sss.measure.Frequency; 007 import edu.nrao.sss.measure.LinearVelocity; 008 import edu.nrao.sss.measure.LinearVelocityUnits; 009 010 /** 011 * A calculator of frequency shifts due to the motion of a point on 012 * earth relative to a celestial source. 013 * <p> 014 * <b>Version Info:</b> 015 * <table style="margin-left:2em"> 016 * <tr><td>$Revision: 1994 $</td></tr> 017 * <tr><td>$Date: 2009-02-23 09:03:44 -0700 (Mon, 23 Feb 2009) $</td></tr> 018 * <tr><td>$Author: dharland $ (last person to modify)</td></tr> 019 * </table></p> 020 * 021 * @author David M. Harland 022 * @since 2008-09-09 023 */ 024 public class DopplerTracker 025 { 026 private EarthPosition observer; 027 private SkyPosition skyPosition; 028 private LinearVelocity sourceVelocity; 029 private VelocityFrame sourceFrame; 030 private VelocityConvention velocityConvention; 031 032 private SpectralLine helper; 033 034 /** 035 * Creates a new Doppler tracker with the given parameters. 036 * 037 * @param observer 038 * a point on earth whose velocity relative to a celestial source 039 * will be used for calculating Doppler frequency shifts. 040 * See {@link #setObserver(EarthPosition)} for handling of 041 * a <i>null</i> parameter value. 042 * 043 * @param skyPosition 044 * a point on the celestial sphere where a signal emitting source sits. 045 * See {@link #setSkyPosition(SkyPosition)} for handling of 046 * a <i>null</i> parameter value. 047 * 048 * @param sourceVelocity 049 * the velocity of the source at {@code skyPosition} as measured 050 * against the rest frame given by {@code sourceFrame}. 051 * See {@link #setSourceVelocity(LinearVelocity)} for handling of 052 * a <i>null</i> parameter value. 053 * 054 * @param sourceFrame 055 * the rest frame against which the {@code sourceVelocity} is measured. 056 * See {@link #setVelocityFrame(VelocityFrame)} for handling of 057 * a <i>null</i> parameter value. 058 * 059 * @param velocityConvention 060 * the velocity convention used for calculating shifted frequencies. 061 * See {@link #setVelocityConvention(VelocityConvention)} for handling of 062 * a <i>null</i> parameter value. 063 */ 064 public DopplerTracker(EarthPosition observer, SkyPosition skyPosition, 065 LinearVelocity sourceVelocity, VelocityFrame sourceFrame, 066 VelocityConvention velocityConvention) 067 { 068 setObserver(observer); 069 setSkyPosition(skyPosition); 070 setSourceVelocity(sourceVelocity); 071 setVelocityFrame(sourceFrame); 072 setVelocityConvention(velocityConvention); 073 074 helper = new SpectralLine(); 075 } 076 077 /** 078 * Creates a new Doppler tracker where the observer, sky position, and 079 * velocity are all non-null default values. 080 */ 081 public DopplerTracker() 082 { 083 this(null, null, null, null, null); 084 } 085 086 /** 087 * Creates a new Doppler tracker for the given earth-bound observer. 088 * The sky position will be a non-null default value, and the 089 * velocity of the source will be zero. 090 * 091 * @param observer 092 * a point on earth whose velocity relative to a celestial source 093 * will be used for calculating Doppler frequency shifts. 094 * See {@link #setObserver(EarthPosition)} for handling of 095 * a <i>null</i> parameter value. 096 */ 097 public DopplerTracker(EarthPosition observer) 098 { 099 this(observer, null, null, null, null); 100 } 101 102 /** 103 * Creates a new Doppler tracker for the given observer and celestial 104 * sky position. The velocity of the source at that position will 105 * be zero. 106 * 107 * @param observer 108 * a point on earth whose velocity relative to a celestial source 109 * will be used for calculating Doppler frequency shifts. 110 * See {@link #setObserver(EarthPosition)} for handling of 111 * a <i>null</i> parameter value. 112 * 113 * @param skyPosition 114 * a point on the celestial sphere where a signal emitting source sits. 115 * See {@link #setSkyPosition(SkyPosition)} for handling of 116 * a <i>null</i> parameter value. 117 */ 118 public DopplerTracker(EarthPosition observer, SkyPosition skyPosition) 119 { 120 this(observer, skyPosition, null, null, null); 121 } 122 123 //============================================================================ 124 // CONFIGURATION SETTING 125 //============================================================================ 126 127 /** 128 * Sets the position on earth whose velocity will be measured relative 129 * to a celestial source. 130 * 131 * @param newObserver 132 * a new point on earth. 133 * If this value is <i>null</i> it will be replaced by 134 * a newly created <tt>EarthPosition</tt> object. 135 */ 136 public final void setObserver(EarthPosition newObserver) 137 { 138 observer = (newObserver == null) ? new EarthPosition() : newObserver; 139 } 140 141 /** 142 * Sets the point on the celestial sphere against which the observer's 143 * velocity will be measured. 144 * 145 * @param newPosition 146 * a new point on the celestial sphere. 147 * If this value is <i>null</i> it will be replaced by 148 * a newly created <tt>SimpleSkyPosition</tt> object. 149 */ 150 public final void setSkyPosition(SkyPosition newPosition) 151 { 152 skyPosition = (newPosition == null) ? new SimpleSkyPosition() : newPosition; 153 } 154 155 /** 156 * Sets the rest frame against which velocity values will be calculated. 157 * 158 * @param newFrame 159 * a new rest frame. 160 * If this value is <i>null</i> it will be replaced by 161 * <tt>VelocityFrame.TOPOCENTRIC</tt>. 162 */ 163 public final void setVelocityFrame(VelocityFrame newFrame) 164 { 165 sourceFrame = (newFrame == null) ? VelocityFrame.TOPOCENTRIC : newFrame; 166 } 167 168 /** 169 * Sets the velocity convention to use when shifting frequencies. 170 * 171 * @param newConvention 172 * a new velocity convention. 173 * This value is permitted to be <i>null</i>. To see how this 174 * affects calculations see 175 * {@link SpectralLine#getShiftedFrequency(LinearVelocity, VelocityConvention)}. 176 */ 177 public final void setVelocityConvention(VelocityConvention newConvention) 178 { 179 //OK for this to be null 180 velocityConvention = newConvention; 181 } 182 183 /** 184 * Sets the velocity of the celestial source, relative to the rest frame 185 * held by this object. 186 * 187 * @param newVelocity 188 * a new velocity for a celestial source. 189 * If this value is <i>null</i> it will be replaced by 190 * a newly created <tt>LinearVelocity</tt> object. 191 */ 192 public final void setSourceVelocity(LinearVelocity newVelocity) 193 { 194 sourceVelocity = (newVelocity == null) ? new LinearVelocity() : newVelocity; 195 } 196 197 /** 198 * A convenience method for setting the source velocity and frame. 199 * 200 * @param newVelocity 201 * see {@link #setSourceVelocity(LinearVelocity)}. 202 * 203 * @param newFrame 204 * see {@link #setVelocityFrame(VelocityFrame)}. 205 * 206 * @param newConvention 207 * see {@link #setVelocityConvention(VelocityConvention)}. 208 */ 209 public void setSourceVelocity(LinearVelocity newVelocity, 210 VelocityFrame newFrame, 211 VelocityConvention newConvention) 212 { 213 setSourceVelocity(newVelocity); 214 setVelocityFrame(newFrame); 215 setVelocityConvention(newConvention); 216 } 217 218 /** 219 * A convenience method for setting the position and velocity of a celestial 220 * source. 221 * 222 * @param newPosition 223 * see {@link #setSkyPosition(SkyPosition)}. 224 * 225 * @param newVelocity 226 * see {@link #setSourceVelocity(LinearVelocity)}. 227 * 228 * @param newFrame 229 * see {@link #setVelocityFrame(VelocityFrame)}. 230 * 231 * @param newConvention 232 * see {@link #setVelocityConvention(VelocityConvention)}. 233 */ 234 public void setSource(SkyPosition newPosition, LinearVelocity newVelocity, 235 VelocityFrame newFrame, VelocityConvention newConvention) 236 { 237 setSkyPosition(newPosition); 238 setSourceVelocity(newVelocity); 239 setVelocityFrame(newFrame); 240 setVelocityConvention(newConvention); 241 } 242 243 //============================================================================ 244 // CONFIGURATION QUERIES 245 //============================================================================ 246 247 /** 248 * Returns the position on earth whose velocity will be measured relative 249 * to a celestial source. 250 * This is either the position provided by a client object 251 * or a default position if none was provided. 252 * 253 * @return 254 * the earth position used in the Doppler calculations. 255 */ 256 public EarthPosition getObserver() 257 { 258 return observer; 259 } 260 261 /** 262 * Returns the point on the celestial sphere against which the observer's 263 * velocity will be measured. 264 * This is either the position provided by a client object 265 * or a default position if none was provided. 266 * 267 * @return 268 * the sky position used in the Doppler calculations. 269 */ 270 public SkyPosition getSkyPosition() 271 { 272 return skyPosition; 273 } 274 275 /** 276 * Returns the rest frame against which velocity values will be calculated. 277 * This is either the frame provided by a client object 278 * or a default frame if none was provided. 279 * 280 * @return 281 * the frame of rest used in the Doppler calculations. 282 */ 283 public VelocityFrame getVelocityFrame() 284 { 285 return sourceFrame; 286 } 287 288 /** 289 * Returns the velocity convention used when shifting frequencies. 290 * This is either the convention provided by a client object 291 * or is based on the units of the velocity if none was provided. 292 * 293 * @return 294 * the velocity convention used in the Doppler calculations. 295 */ 296 public VelocityConvention getVelocityConvention() 297 { 298 if (velocityConvention != null) 299 return velocityConvention; 300 301 return 302 sourceVelocity.getUnits().equals(LinearVelocityUnits.Z) ? 303 VelocityConvention.REDSHIFT : VelocityConvention.RADIO; 304 } 305 306 /** 307 * Returns the velocity of the celestial source, relative to the rest frame 308 * held by this object. 309 * This is either the velocity provided by a client object 310 * or a default velocity if none was provided. 311 * 312 * @return 313 * the source velocity used in the Doppler calculations. 314 * 315 * @see #calculateRelativeVelocity(Date) 316 */ 317 public LinearVelocity getSourceVelocity() 318 { 319 return sourceVelocity; 320 } 321 322 //============================================================================ 323 // CALCULATIONS 324 //============================================================================ 325 326 /** 327 * Calculates and returns the relative velocity between the earth-bound 328 * observer and celestial source held by this tracker. 329 * A positive velocity means the observer and signal source are moving 330 * <i>away</i> from each other. 331 * 332 * @param dateTime 333 * the point in time for which the calculation is performed. 334 * 335 * @return 336 * the relative velocity between observer and signal source. 337 * 338 * @throws CoordinateConversionException 339 * 340 */ 341 public LinearVelocity calculateRelativeVelocity(Date dateTime) 342 throws CoordinateConversionException 343 { 344 LinearVelocity observerAwayFromSkyPos = 345 observer.calcVelocityRelativeTo(skyPosition, dateTime, sourceFrame); 346 347 return observerAwayFromSkyPos.add(sourceVelocity); 348 } 349 350 /** 351 * Returns a shifted frequency based on {@code restFreq} and the relative 352 * velocity of the observer to the emitter at {@code dateTime}. 353 * 354 * @param restFreq 355 * a frequency as emitted by a source for which a shifted received 356 * frequency is desired. 357 * 358 * @param dateTime 359 * the point in time for which the relative velocity calculation is 360 * performed. 361 * 362 * @return 363 * a Doppler shifted frequency. 364 * 365 * @throws CoordinateConversionException 366 * 367 */ 368 public Frequency calculateShiftedFrequency(Frequency restFreq, Date dateTime) 369 throws CoordinateConversionException 370 { 371 helper.setFrequency(restFreq); 372 373 return helper.getShiftedFrequency(calculateRelativeVelocity(dateTime), 374 getVelocityConvention()); 375 } 376 }