001 package edu.nrao.sss.model.source; 002 003 import edu.nrao.sss.astronomy.StokesParameter; 004 import edu.nrao.sss.measure.Angle; 005 import edu.nrao.sss.measure.ArcUnits; 006 import edu.nrao.sss.measure.Frequency; 007 import edu.nrao.sss.measure.FrequencyRange; 008 import edu.nrao.sss.measure.FluxDensity; 009 import edu.nrao.sss.measure.TimeDuration; 010 import edu.nrao.sss.measure.TimeInterval; 011 import edu.nrao.sss.measure.TimeUnits; 012 013 import java.math.BigDecimal; 014 import java.util.Calendar; 015 import java.util.Date; 016 import java.util.TimeZone; 017 018 /** 019 * An observation of the flux from a source performed by the 020 * Very Large Array. 021 * <p> 022 * This class was copied from edu.nrao.legacy.VLAFluxData. 023 * It has not (yet?) been altered to match more closely the 024 * style of the other classes in the SSS Domain Model.</p> 025 * <p> 026 * This class is not suggested for general use.</p> 027 * <p> 028 * <b>Version Info:</b> 029 * <table style="margin-left:2em"> 030 * <tr><td>$Revision: 1314 $</td></tr> 031 * <tr><td>$Date: 2008-05-30 11:31:14 -0600 (Fri, 30 May 2008) $</td></tr> 032 * <tr><td>$Author: dharland $</td></tr> 033 * </table></p> 034 * 035 * @author David M. Harland 036 * @since 2007-05-21 037 */ 038 public class VlaFluxObservation 039 implements Cloneable 040 { 041 //The names of these variables were copied directly from 042 //edu.nrao.legacy.VLAFluxData. 043 public String Source; 044 public double mjad; 045 public String correlator_mode; 046 public double el_end; //Units? 047 public double obs_start; //in Radians 048 public double obs_end; //in Radians 049 public double time_obs; //Length of obsvn? This is an mjd 050 public double ac_freq; //Right circular polarized, in Ghz 051 public double bd_freq; //Left circular polarized 052 public double ac_flux; //in Janskies 053 public double ac_flux_stddev; 054 public double bd_flux; 055 public double bd_flux_stddev; 056 057 /** Used by a factory method of SourceBrightness. */ 058 SourceBrightness[] makeBrightnesses() 059 { 060 //Circular polarizations 061 final int LEFT = 0; 062 final int RIGHT = 1; 063 064 PointBrightness[] result = new PointBrightness[2]; 065 066 result[LEFT] = (PointBrightness) 067 SourceBrightness.createBrightness(BrightnessDistribution.POINT); 068 069 result[LEFT].setPolarization(StokesParameter.LL); 070 071 //XXX The endpoint will have to be changed by the client of this method if 072 //they want something besides infinity. 073 TimeInterval ti = new TimeInterval(); 074 ti.set(getDateFromMjad((int)this.mjad, obs_start), ti.getEnd()); 075 result[LEFT].setValidTime(ti); 076 077 FrequencyRange fr = new FrequencyRange( 078 new Frequency(new BigDecimal(this.ac_freq)), 079 new Frequency(new BigDecimal(this.bd_freq)) 080 ); 081 082 result[LEFT].setValidFrequency(fr); 083 result[LEFT].setPeakFluxDensity(new FluxDensity(BigDecimal.valueOf(this.bd_flux))); 084 085 result[RIGHT] = (PointBrightness)result[LEFT].clone(); 086 result[RIGHT].setPolarization(StokesParameter.RR); 087 result[RIGHT].setPeakFluxDensity(new FluxDensity(BigDecimal.valueOf(this.ac_flux))); 088 089 return result; 090 } 091 092 /** 093 * @return a UTC date representing this particular mjad. 094 * @param mjad A MJAD with no fractional day component 095 * @param rads A fractional day represented in radians. 096 */ 097 private Date getDateFromMjad(int mjad, double rads) 098 { 099 Angle startTime = new Angle(BigDecimal.valueOf(rads), ArcUnits.RADIAN); 100 double startHour = startTime.toUnits(ArcUnits.HOUR).doubleValue(); 101 102 TimeDuration start = new TimeDuration(BigDecimal.valueOf(startHour)); 103 int hour = (int)start.getIntegralPart(TimeUnits.HOUR); 104 int min = (int)start.getIntegralPart(TimeUnits.MINUTE); 105 106 //Ignore anything more precise than seconds 107 int sec = start.getPart(TimeUnits.SECOND).intValue(); 108 109 //Intialize the calendar to the Gregorian date that represents 0.0 MJD 110 Calendar c = Calendar.getInstance(); 111 c.setTimeZone(TimeZone.getTimeZone("UTC")); 112 c.set(1858, Calendar.NOVEMBER, 17, 0, 0, 0); 113 114 //Add the days, hours, etc. 115 c.add(Calendar.DAY_OF_YEAR, mjad); 116 c.add(Calendar.HOUR_OF_DAY, hour); 117 c.add(Calendar.MINUTE, min); 118 c.add(Calendar.SECOND, sec); 119 120 return c.getTime(); 121 } 122 123 /* (non-Javadoc) 124 * @see java.lang.Object#toString() 125 */ 126 @Override 127 public String toString() 128 { 129 StringBuilder buff = new StringBuilder(); 130 131 final String DELIM = ";"; 132 133 buff.append("VLA FLUX OBSERVATION;"); 134 buff.append("Source=").append(Source).append(DELIM); 135 buff.append("mjad=").append(mjad).append(DELIM); 136 buff.append("correlator_mode=").append(correlator_mode).append(DELIM); 137 buff.append("el_end=").append(el_end).append(DELIM); 138 buff.append("obs_start=").append(obs_start).append(DELIM); 139 buff.append("obs_end=").append(obs_end).append(DELIM); 140 buff.append("time_obs=").append(time_obs).append(DELIM); 141 buff.append("ac_freq=").append(ac_freq).append(DELIM); 142 buff.append("bd_freq=").append(bd_freq).append(DELIM); 143 buff.append("ac_flux=").append(ac_flux).append(DELIM); 144 buff.append("ac_flux_stddev=").append(ac_flux_stddev).append(DELIM); 145 buff.append("bd_flux=").append(bd_flux).append(DELIM); 146 buff.append("bd_flux_stddev=").append(bd_flux_stddev).append(DELIM); 147 148 return buff.toString(); 149 } 150 151 /** 152 * Returns a copy of this observation. 153 * <p> 154 * If anything goes wrong during the cloning procedure, 155 * a {@code RuntimeException} will be thrown.</p> 156 */ 157 @Override 158 public VlaFluxObservation clone() 159 { 160 VlaFluxObservation clone = null; 161 162 try 163 { 164 //This line takes care of the primitive & immutable fields properly 165 clone = (VlaFluxObservation)super.clone(); 166 167 //There are no contained objects to clone. 168 } 169 catch (Exception ex) 170 { 171 throw new RuntimeException(ex); 172 } 173 174 return clone; 175 } 176 177 /** Returns <i>true</i> if {@code o} is equal to this observation. */ 178 @Override 179 public boolean equals(Object o) 180 { 181 //Quick exit if o is this 182 if (o == this) 183 return true; 184 185 //Quick exit if o is null 186 if (o == null) 187 return false; 188 189 //Quick exit if classes are different 190 if (!o.getClass().equals(this.getClass())) 191 return false; 192 193 VlaFluxObservation other = (VlaFluxObservation)o; 194 195 return 196 other.Source.equalsIgnoreCase(this.Source) && 197 other.correlator_mode.equalsIgnoreCase(this.correlator_mode) && 198 other.mjad == this.mjad && 199 other.el_end == this.el_end && 200 other.obs_start == this.obs_start && 201 other.obs_end == this.obs_end && 202 other.time_obs == this.time_obs && 203 other.ac_freq == this.ac_freq && 204 other.bd_freq == this.bd_freq && 205 other.ac_flux == this.ac_flux && 206 other.bd_flux == this.bd_flux && 207 other.ac_flux_stddev == this.ac_flux_stddev && 208 other.bd_flux_stddev == this.bd_flux_stddev; 209 } 210 211 /** Returns a hash code value for this observation. */ 212 @Override 213 public int hashCode() 214 { 215 //Taken from the Effective Java book by Joshua Bloch. 216 //The constants 17 & 37 are arbitrary & carry no meaning. 217 int result = 17; 218 219 //You must keep this method in sync w/ equals 220 221 result = 37 * result + Source.hashCode(); 222 result = 37 * result + correlator_mode.hashCode(); 223 224 result = 37 * result + new Double(mjad).hashCode(); 225 result = 37 * result + new Double(el_end).hashCode(); 226 result = 37 * result + new Double(obs_start).hashCode(); 227 result = 37 * result + new Double(obs_end).hashCode(); 228 result = 37 * result + new Double(time_obs).hashCode(); 229 result = 37 * result + new Double(ac_freq).hashCode(); 230 result = 37 * result + new Double(bd_freq).hashCode(); 231 result = 37 * result + new Double(ac_flux).hashCode(); 232 result = 37 * result + new Double(bd_flux).hashCode(); 233 result = 37 * result + new Double(ac_flux_stddev).hashCode(); 234 result = 37 * result + new Double(bd_flux_stddev).hashCode(); 235 236 return result; 237 } 238 }