There's now a basic fringing program for use in glish: jfrnge. This is a purely baseline-based fringe: no model-dependent cheating. At the moment, I've made it most applicable to clock-searching. To take full advantage, there are also a couple minor changes to updateclock.pl (ie, what units to use for rate), which should be switched over to at the same time jfrnge replaces the chantime/phaserate combination. The advantages of jfrnge for clock-searching are: *) doesn't need a lag MS *) single-step process to get delay & rate *) written record provided (for exp.folder, automatic insertion into future GPS-offset treasury, etc.) *) optional plots of 2-D fringe *) delay/rate estimates obtainable for much weaker detections than via chantime/phaserate Below we'll go over the specific syntax of jfrnge, mention a few things it doesn't do yet, and end with the consequent changes required to updateclock.pl & phaserate to ensure forward & backward compatibility between the new & old ways. Right now, nothing has been changed in the official versions of anything (ie, what you'd use by logging in as jops). This mail wound up being a little longer than I expected to stimulate discussion before committing updateclock.pl changes. I've tested jfrnge on a variety of jobs (multimode, S/X, diff pols,...), checked consistency with chantime/phaserate, checked delay/rate closures (which work, even on triangles with baselines too weak to get chantime/phaserate solutions), etc. People can see some output/plots from these tests. Demos are easy to arrange. GG048A clock search (this morning, I guess) will be the first non-rehersed use. jfrnge syntax (related input parameters grouped on same line; letter corresponds to note below; default given after "=") jfrnge(MS, {name of meas.set or pre-readms'ed variable} antenna=F, baseline=F, ants=F {a} subband=F, pol=F, {b} weight=0.4, {dflt>0, to minimize strange effects if not set} source=F, scan=F, {c} initvis=1, ntimes=-1, tseg=-1, {d} gap=3, {e} snrmin=7.0, {f} updtclk=T, outfile='', {g} doplot=F) {h} The standard glish-function parameter-passing rules apply (names not required until 1st parameter passed out of order; thereafter all names required). {a} antenna, baseline: AIPS-like control of which baselines to use: all baselines formable from STA_1 = {antenna} & STA_2 = {baseline}. Baselines automatically sorted into VEX-file order, so there's no constraint that antenna_i < baseline_j (although the results will come out that way). ants = shorthand for antenna=baseline = ants (ie, form all baselines from the set {ants}). These stations can be passed as either antenna-ID (0-based, cf mssum) or as 2-letter abbreviations (case insensitive) Any passed station not found in the MS will be ignored, rather than causing the program to fail (accepts either Ef or Eb for Effelsberg). As in standard jive.g usage, F --> all Note the order of antenna,baseline,ants is different from, say, readms (ants,antenna,baseline); I did this to allow passing a single (reference) station right after the MS-name, without having to worry about putting the "F" for ants in between (or to require typing "antenna="). {b} subband = 0-based; pol = 1-based (ie, standard jive.g expectation) You can also pass pol by a string (array): 'll','rr','lr','rl' (case insensitive). Valid strings = any pol that aips++ knows about (stokes.h): other ones we don't use include such as 'i','q','xy','yl','rx',... It may be preferrable to use strings, so you don't have to worry about knowing the pol-index(ices) for the specific experiment. Simple range-check upon input; non-participating subbands/pols ignored. {c} source can be (0-based) souce ID or name (string) scan: a scan-ID number, typically under the current j2ms2 = VEXnumber + 1, but this depends on whether the VEX file used for the job in question was edited. I'd not imagine this parameter would be used much, especially for clock searching, where only one scan would typically be done anyway. As described later, jfrnge will establish solution-interval boundaries at scan-boundaries automatically (even if different scans of same source), so there's no problem in that regard leaving scan=F (for a similar reason, I didn't include a separate frequency-group (ie, mode) parameter). {d} initvis, ntimes --> jive.g format for specifying a time range via integration numbers. If ntimes<0, do all after initvis. As always, these parameters are most useful after noticing a specific problem in a simpler time-based plot (i.e., a tplot of weight including plottime=F in the argument list to plot integration numbers rather than UTC on the x-axis). tseg - essentially AIPS solint [in minutes]: for scans longer than tseg, break up into tseg-long chunks, each with an independent fringe solution. If tseg<0, any scan done in 1 chunk. {e} gap: how many delay/rate points about the 2-D fringe-peak to ignore when computing the noise for the SNR. I've played around with this in testing, don't think changing it would be necessary. (this is a little different from the similar parameter when included by Chris: I've made it an absolute number of points rather than a fraction of N_pt, and have pulled it much closer to the main peak as a means of incorporating the possibility of a nearby sidelobes into the SNR parameter (i.e., making it lower by letting the noise go up). {f} snrmin: don't include solutions with SNR output per SB/pol/scan/seg in [us], [mHz] each bsln gets an (weighted) average dly,rt for input into updateclock.pl (rate units in average = [ps/s] & sign of delay changed; see discussion under updateclock.pl at end). output file made regardless of outfile: if outfile specified, use that name if not, use EXPR.MSNAME.clkfrng, where EXPR & MSNAME taken from the meas.set (MSNAME has any preceeding path info stripped). F --> output per SB/pol/scan/seg in [ns], [ps/s], no bsln-average line computed. no output file written if outfile='' (the default) outfile: If output file (specified or automatically generated) exists, queried whether to overwrite; if not prompted for new name. Fringe-solutions always go to screen {h} doplot: T --> plots 2-D fringe (via gplot1d: you can zoom in using the cursors as in any gplot1d plot [eg, olayspec, phaserate,...]) Right now, you get 2 plots per bsln/sb/pol/scan/seg (1 with the delay points along the x-axis & rate points going into the plot, and the other with rate points along the x-axis & rate points going into the plot). Another of the short-list of improvements is an idea I had to combine the two plots in a non-obnoxious way. The plot stays on screen until you take some action at the "-->" prompt. There are currently 3 actions (followed by a carriage return...): "s" - stop plotting from here on "p" - save current plot to PS file (prompted for name) anything else (including just carriage-return) - go to next plot If you've specified >1 SB or Pol, or have set tseg, you'll have the option before jfrnge starts looping of choosing a single SB & a single pol for which to plot (fringe solutions will still come out for all selected SB/pol, just won't all be plotted), and whether you want to turn off tseg (this would also apply to the jfrnge'ing, not just the plotting). examples: jfrnge an entire MS (='my.ms'): jfrnge('my.ms') jfrnge a clock-search MS, already readms'ed [clk:=readms('my.ms')], using station 'Rf' as the reference: jfrnge(clk,'rf') {don't need to check mssum for ant-ID} use only parallel-hand pols: jfrnge(clk,'rf',F,F,F,['ll','rr']) or jfrnge(clk,'rf',pol=['ll','rr']) or jfrnge(clk,'rf',pol=[1,2]) ACTION: 1. various parsing / consistency-checks for input parameters. If you pass something very unusual, you may be prompted to check whether that's really what you want to do. 2. Loops over bsln/sb/pol/scan/seg (autocorrelations now explicitly skipped). Outputs 1 line per each of the above, with SRC-name, UT of mid-point of the segment, N_int in the segment, N_int meeting weight cut-off, the (single-band) delay & (statistical) uncertainty; the rate & uncertainty, the SNR, and the frequency. 2a. If <80% of the integrations meet the weight cut-off, it tries 2 simple ways of gridding, and if they give sufficiently different (currently 1/1000 delay-point spacing [ie, 625ps for 8MHz BW] & 0.1mHz), both results are printed out in 2 lines, with "0-pad" at end of 2nd line. Neither line will be included in the baseline-average, if updtclk=T. (I haven't put too much thought into improving behavior in this situation, since the servo-errors that would cause this sort of thing will soon be a thing of the past once disks become standard......). CURRENTLY DOESN'T DO: 1. any sort of multi-band delay (no phase-cals, no usb-lsb offsets, etc.) 2. limiting search windows for SBD,DR (no fringe-control file) 3. HOPS-/frngp-like fringe plot 4. apply the fringe-solution to the data to estimate a better delay/rate values (i.e., not just parabolically interpolating the gridded points in a single step) This could also provide more significant closure calculations (without having to worry about effects of vector averaging over a range of frq.point/time for baselines having different residual SBD/DR). updateclock.pl NOW: can be run in -lag or -aips mode (-aips = default) -lag: input delay in [lag] {via fringe_display plots or chantime} -aips: input delay in [us] and rate in [mHz] {via jfrnge.g} Using [mHz] for rate is good for intuition (how long will it take for phase to wrap once), but it's frequency-dependent. updateclock.pl now takes the average freq over all SBs in converting [mHz] to [us/s] to add to the $CLOCK section of the VEX file (each station can have only one clock, not a different clock per SB). Now, since everything is linear, this averaging should be benign, as long as the rate passed to updateclock is a similar average over all SBs. However, some experiments (es44) have widely differing frequencies (S/X in same mode), and different quality of fringe-results at the different frequencies. If you based your rate estimate on, say, only the X-band SBs (because they had higher SNR), you'd have a very biased rate solution, since updateclock would still use the average frequency of all SBs. Since the clock-rate offset for a station would physically be the same for every SB, it seems more straightforward (by my thinking) to keep everything in [ps/s]. jfrnge keeps fringe-rate and delay-rate computations in parallel, removing the need for updateclock (or the user) to do it. Also, the sign of the delay returned from the frequency-based MS via jfrnge has the opposite sign as that inferred from the peak in the lag-based MS (which probably explains why the clock-fixing algorithms initially had the wrong sign (or baseline-order parity) that what I was used to in mkIII). I was going to change this as well in updateclock.pl, but found quite a few sign-convention/baseline-order differences between there & the math in the Clock-Searching Guide (although an even number of them!!), that I decided it was easier to have jfrnge change the sign of the delay in the baseline-average line (if updtclk=T) than to mess further with the updateclock.pl code. Therfore, any input of delay remains as before (ie, can still use fringe_display plots directly). The default modes have been swapped: -aips is the default, and you'll have to explicitly specify "-lag" to input only a delay offset in lags. The units for rate in the default are now [ps/s]. phaserate -- This updateclock.pl change also made a change to phaserate necessary. phaserate now prints out the rate fit (via a 1st-order polynomial fit to phase in a channel, connected simply such that consecutive integrations meeting the weight cut-off are within +/-180deg of each other) in both [mHz] and [ps/s]. For es44, the [mHz] in the S & X SBs are off by factors of ~3 (ie, X/S ratio), you'd have to do the average manually. The rates in [ps/s] are all around the same value. Of course, jfrnge does all this for you automatically, so it's hard to see why you'd be using phaserate for this purpose.....