001 package edu.nrao.sss.model.resource.vla; 002 003 import java.math.BigDecimal; 004 import java.util.ArrayList; 005 import java.util.HashMap; 006 import java.util.List; 007 import java.util.Map; 008 import java.util.Set; 009 010 import static edu.nrao.sss.math.MathUtil.MC_INTERM_CALCS; 011 012 import edu.nrao.sss.measure.Frequency; 013 import edu.nrao.sss.measure.FrequencyUnits; 014 import edu.nrao.sss.measure.TimeDuration; 015 import edu.nrao.sss.measure.TimeUnits; 016 017 public enum BandwidthCode 018 { 019 // Max Channels 020 // Nominal --------------- 021 // Code, Contnm, Spec Line, Bandwidth (MHz), IF-1,IF-2,IF-4 022 ZERO (0, true, true, "50.0", 16, 8, 4), 023 ONE (1, true, true, "25.0", 32, 16, 8), 024 TWO (2, true, true, "12.5", 64, 32, 16), 025 THREE(3, true, true, "6.25", 128, 64, 32), 026 FOUR (4, true, true, "3.125", 256, 128, 64), 027 FIVE (5, true, true, "1.5625", 512, 256, 128), 028 SIX (6, true, true, "0.78125", 512, 256, 128), 029 SEVEN(7, true, false, "0.1953125", 0, 0, 0), 030 EIGHT(8, false, true, "0.1953125", 256, 128, 64), 031 NINE (9, false, true, "0.1953125", 512, 256, 128); 032 033 private static List<BandwidthCode> continuumCodes; 034 private static List<BandwidthCode> spectralLineCodes; 035 036 private boolean validForContinuum; 037 private boolean validForSpectralLine; 038 private int codeNumber; 039 private String bwNominal; 040 private Map<IFMode, Integer> channels; 041 042 private BandwidthCode(int codeNum, 043 boolean validForCont, boolean validForSpecLine, 044 String nominalMHz, 045 int mode1Ch, int mode2Ch, int mode4Ch) 046 { 047 codeNumber = codeNum; 048 049 validForContinuum = validForCont; 050 validForSpectralLine = validForSpecLine; 051 052 bwNominal = nominalMHz; 053 054 channels = new HashMap<IFMode, Integer>(); 055 channels.put(IFMode.ONE, mode1Ch); 056 channels.put(IFMode.TWO, mode2Ch); 057 channels.put(IFMode.FOUR, mode4Ch); 058 } 059 060 /** 061 * Returns the subset of codes that may be used for continuum observations. 062 * @return the subset of codes that may be used for continuum observations. 063 */ 064 public static List<BandwidthCode> getContinuumCodes() 065 { 066 if (continuumCodes == null) 067 { 068 continuumCodes = new ArrayList<BandwidthCode>(); 069 070 for (BandwidthCode code : BandwidthCode.values()) 071 if (code.isValidForContinuum()) 072 continuumCodes.add(code); 073 } 074 075 return new ArrayList<BandwidthCode>(continuumCodes); 076 } 077 078 /** 079 * Returns the subset of codes that may be used for spectral line observations. 080 * @return the subset of codes that may be used for spectral line observations. 081 */ 082 public static List<BandwidthCode> getSpectralLineCodes() 083 { 084 if (spectralLineCodes == null) 085 { 086 spectralLineCodes = new ArrayList<BandwidthCode>(); 087 088 for (BandwidthCode code : BandwidthCode.values()) 089 if (code.isValidForSpectralLine()) 090 spectralLineCodes.add(code); 091 } 092 093 return new ArrayList<BandwidthCode>(spectralLineCodes); 094 } 095 096 /** 097 * Returns an integer representation of this band code. 098 * @return an integer representation of this band code. 099 */ 100 public int getCodeNumber() { return codeNumber; } 101 102 /** 103 * Returns <i>true</i> if this bandwidth code is valid for 104 * continuum observations. 105 * @return <i>true</i> if this bandwidth code is valid for 106 * continuum observations. 107 */ 108 public boolean isValidForContinuum() { return validForContinuum; } 109 110 /** 111 * Returns <i>true</i> if this bandwidth code is valid for 112 * spectral line observations. 113 * @return <i>true</i> if this bandwidth code is valid for 114 * spectral line observations. 115 */ 116 public boolean isValidForSpectralLine() { return validForSpectralLine; } 117 118 public Frequency getBandwidthNominal() 119 { 120 return new Frequency(bwNominal, FrequencyUnits.MEGAHERTZ).normalize(); 121 } 122 123 /** 124 * Returns the bandwidth associated with this code in continuum mode. 125 * 126 * @return the bandwidth associated with this code in continuum mode. 127 */ 128 public Frequency getBandwidthForContinuum() 129 { 130 return isValidForContinuum()? 131 new Frequency(bwNominal, FrequencyUnits.MEGAHERTZ).normalize() : 132 new Frequency("0.0", FrequencyUnits.HERTZ); 133 } 134 135 /** 136 * Returns the bandwidth for this code and the given IF mode and processing 137 * options. 138 * 139 * @param ifMode 140 * the IF mode for which the bandwidth is desired. 141 * Normally the IF mode does not influence bandwidth, and this parameter 142 * may be <i>null</i>. However, when channel-zero processing is requested, 143 * we need to know the width of a single channel, and the IF mode is 144 * required for that. (See {@link #getResolution(IFMode, Set)}.) 145 * 146 * @param spectralLineProcessing 147 * a list of the spectral line processing options that will be used. 148 * This parameter may be <i>null</i>. 149 * 150 * @return 151 * the bandwidth for this code and the given IF mode and processing options. 152 */ 153 public Frequency getBandwidthForSpectralLine(IFMode ifMode, 154 Set<ProcessingType> spectralLineProcessing) 155 { 156 //Quick exit if this is not a valid spectral line mode 157 if (!isValidForSpectralLine()) 158 return new Frequency("0.0", FrequencyUnits.HERTZ); 159 160 Frequency bw = new Frequency(bwNominal, FrequencyUnits.MEGAHERTZ); 161 162 if (!performLagProcessing(spectralLineProcessing)) 163 { 164 int ch = getChannels(ifMode, spectralLineProcessing); 165 166 BigDecimal actualChannels = new BigDecimal(ch); 167 BigDecimal idealChannels = actualChannels.add(BigDecimal.ONE); 168 169 bw.divideBy(idealChannels).multiplyBy(actualChannels); 170 } 171 172 return bw.normalize(); 173 } 174 175 /** 176 * Returns the maximum number of spectral channels that can be created 177 * using this band code and the given IF mode and processing options. 178 * 179 * @param ifMode 180 * the IF mode for which the number of channels is desired. 181 * 182 * @param spectralLineProcessing 183 * a list of the spectral line processing options that will be used. 184 * This parameter may be <i>null</i>. 185 * 186 * @return 187 * the maximum number of channels for the given IF mode and 188 * processing options. 189 */ 190 public int getChannels(IFMode ifMode, 191 Set<ProcessingType> spectralLineProcessing) 192 { 193 int ch = channels.get(ifMode); 194 195 if (ch != 0) 196 { 197 if (performHanningSmoothing(spectralLineProcessing)) 198 ch /= 2; 199 200 //JIRA EVL-555: Lose one channel ALL the time in spectral line modes 201 //if (putPseudoContinuumInChannelZero(spectralLineProcessing)) 202 ch--; 203 } 204 205 return ch; 206 } 207 208 /** 209 * Returns the best spectral resolution that can be obtained using 210 * this band code and the given IF mode and processing options. 211 * 212 * @param ifMode 213 * the IF mode for which the resolution is desired. 214 * 215 * @param spectralLineProcessing 216 * a list of the spectral line processing options that will be used. 217 * This parameter may be <i>null</i>. 218 * 219 * @return the best spectral resolution for the given parameters. 220 */ 221 public Frequency getResolution(IFMode ifMode, 222 Set<ProcessingType> spectralLineProcessing) 223 { 224 //Quick exit if this is not a valid spectral line mode 225 if (!isValidForSpectralLine()) 226 return new Frequency("0.0", FrequencyUnits.HERTZ); 227 228 Frequency bw = getBandwidthForSpectralLine(ifMode, spectralLineProcessing); 229 230 int ch = getChannels(ifMode, spectralLineProcessing); 231 232 Frequency resolution = bw.divideBy(new BigDecimal(ch)); 233 234 return resolution.normalize(); 235 } 236 237 /** 238 * Returns the time resolution that can be obtained using 239 * this band code and the given IF mode and processing options. 240 * If this is the continuum bandwidth code, the returned 241 * resolution will be zero. 242 * 243 * @param ifMode 244 * the IF mode for which the resolution is desired. 245 * 246 * @param spectralLineProcessing 247 * a list of the spectral line processing options that will be used. 248 * This parameter may be <i>null</i>. 249 * 250 * @return 251 * the best time resolution for the given parameters. 252 */ 253 public TimeDuration getTimeResolution(IFMode ifMode, 254 Set<ProcessingType> spectralLineProcessing) 255 { 256 //Quick exit if this is not a valid spectral line mode 257 if (!isValidForSpectralLine()) 258 return new TimeDuration("0.0", TimeUnits.SECOND); 259 260 BigDecimal hertz = 261 getResolution(ifMode, spectralLineProcessing).toUnits(FrequencyUnits.HERTZ); 262 263 BigDecimal seconds = BigDecimal.ONE.divide(hertz, MC_INTERM_CALCS); 264 265 return new TimeDuration(seconds, TimeUnits.SECOND).normalize(); 266 } 267 268 /** 269 * Returns the bandwidth associated with this code in spectral line mode. 270 * 271 * @return the bandwidth associated with this code in spectral line mode. 272 */ 273 public Frequency getBandwidthForSpectralLine() 274 { 275 return getBandwidthForSpectralLine(null, null); 276 } 277 278 /** 279 * Returns the maximum number of spectral channels that can be created 280 * using this band code and the given IF mode. 281 * 282 * @param ifMode 283 * the IF mode for which the number of channels is desired. 284 * 285 * @return the maximum number of channels for the given IF mode. 286 */ 287 public int getChannels(IFMode ifMode) 288 { 289 return getChannels(ifMode, null); 290 } 291 292 /** 293 * Returns the best spectral resolution that can be obtained using 294 * this band code and the given IF mode. 295 * 296 * @param ifMode 297 * the IF mode for which the resolution is desired. 298 * 299 * @return the best spectral resolution for the given IF mode. 300 */ 301 public Frequency getResolution(IFMode ifMode) 302 { 303 return getResolution(ifMode, null); 304 } 305 306 /** 307 * Returns the number of lags associated with this bandwith code 308 * and IF mode. 309 * The results from this method make sense only for the 310 * {@link ProcessingType#LAG} spectral line processing option. 311 * 312 * @param ifMode 313 * the IF mode for which the number of lags is desired. 314 * 315 * @return 316 * the number of lags associated with this bandwith code and IF mode. 317 */ 318 public int getLags(IFMode ifMode) 319 { 320 //This embeds knowledge that LAG is not allowed w/ HANNING 321 //or when using Channel Zero for pseudo-continuum. 322 return 2 * channels.get(ifMode); 323 } 324 325 private boolean performHanningSmoothing(Set<ProcessingType> spectralLineProcessing) 326 { 327 //Must explicitly choose to do smoothing; default is to not do so 328 return 329 spectralLineProcessing != null && 330 spectralLineProcessing.contains(ProcessingType.HANNING); 331 } 332 333 private boolean performLagProcessing(Set<ProcessingType> spectralLineProcessing) 334 { 335 //Must explicitly choose lag processing; default is to not do so 336 return 337 spectralLineProcessing != null && 338 spectralLineProcessing.contains(ProcessingType.LAG); 339 } 340 341 //============================================================================ 342 // 343 //============================================================================ 344 /* 345 public static void main(String... args) throws Exception 346 { 347 System.out.println("CONTINUUM"); 348 for (BandwidthCode bwc : BandwidthCode.values()) 349 { 350 System.out.println(bwc.getCodeNumber() + 351 ", bw=" + bwc.getBandwidthForContinuum()); 352 } 353 System.out.println(); 354 355 Set<ProcessingType> procOpts = new HashSet<ProcessingType>(); 356 procOpts.add(ProcessingType.HANNING); 357 358 for (IFMode ifMode : IFMode.values()) 359 { 360 System.out.println("IF MODE " + ifMode); 361 for (BandwidthCode bwc : BandwidthCode.values()) 362 { 363 System.out.println(bwc.getCodeNumber() + 364 ", bw=" + bwc.getBandwidthForSpectralLine(ifMode, null) + 365 ", ch=" + bwc.getChannels(ifMode, null) + 366 ", lags=" + bwc.getLags(ifMode) + 367 ", freqRes=" + bwc.getResolution(ifMode, null) + 368 ", timeRes=" + bwc.getTimeResolution(ifMode, null)); 369 } 370 System.out.println(); 371 372 System.out.println("IF MODE " + ifMode + " w/ HANNING"); 373 for (BandwidthCode bwc : BandwidthCode.values()) 374 { 375 System.out.println(bwc.getCodeNumber() + 376 ", bw=" + bwc.getBandwidthForSpectralLine(ifMode, procOpts) + 377 ", ch=" + bwc.getChannels(ifMode, procOpts) + 378 // ", lags=" + bwc.getLags(ifMode) + 379 ", freqRes=" + bwc.getResolution(ifMode, procOpts) + 380 ", timeRes=" + bwc.getTimeResolution(ifMode, procOpts)); 381 } 382 System.out.println(); 383 } 384 } 385 */ 386 }