def test_raw_even_and_odd_length(): """Test raw periodogram of even and odd length sequences versus results obtained using R's spec.pgram function.""" # even-length pgram = Periodogram(dat) rspec = flex.double([ 28.95417436723208, 8.804110562933733, 18.49821426322232, 4.094928274829677, 10.664583495648557, 0.9510798979384458, 4.818019271965207, 8.7890132834726, 0.34895472871642474, 4.298708963847126, 17.808223044747802, 0.43460105379492137, 9.846548561891545, 0.7189166875859443, 1.5700713159868809, 7.006058124904175, 0.34542255079605266, 3.1168239060632974, 1.263928801888548, 0.01861054239907847, 1.6636054250587091, 1.882713242160402, 1.1719572134942402, 1.5202775036250407, 9.849072239357147, 8.154656878294267, 3.5445494165048013, 1.0058616277307482, 4.232126563022536, 5.144050304879019, 3.5369877391028433, 3.096569282327231, 2.8433497727678416, 0.5666508873501074, 1.9719884560263852, 10.127938512870841, 1.7824474672209123, 4.724527776009507, 3.9087766384313976, 6.6956845513767265, 0.6830967285296601, 4.935588195925854, 0.5748537866060414, 1.6844746497921799, 9.263139681830246, 7.47129442196606, 4.762894221668351, 0.3223925047950684, 0.5826957996969294, 0.10068673474008037 ]) rfreq = flex.double(0.01 * e for e in (range(1, 51))) assert approx_equal(pgram.spec, rspec) assert approx_equal(pgram.freq, rfreq) # odd-length dat2 = dat[0:99] pgram = Periodogram(dat2) rspec = flex.double([ 27.378734487215517, 8.300597643964354, 18.601570728645616, 4.401309169508969, 9.81615913184789, 1.2198000269161602, 5.2778352616536175, 8.22707610023193, 0.8865216983472878, 2.8232693965537834, 20.1615730381271, 0.11712370567046958, 8.88090348832551, 0.5966571692115259, 1.9402032941479643, 7.389059053524231, 1.8478623100240048, 2.087060370495997, 1.4918451091166665, 0.29469653682276337, 3.3114401807871734, 0.34065845307496007, 1.2416790352786125, 2.162525614248078, 11.588418669622571, 7.736166858429692, 1.9797555750271172, 2.179422742788905, 7.124078571174135, 1.7626318917205566, 4.097247214701129, 3.484527330303516, 1.2144485874993167, 1.085059335676423, 8.41344396898852, 3.7261271115507744, 0.3362106092460046, 5.5128561313938516, 3.212041963064243, 5.261688734349363, 2.32174787318873, 4.50066920034715, 0.4679419198572981, 2.9281768538056987, 8.883073168591967, 8.952596303235458, 1.2239788162354133, 0.3633295633047963, 0.24463991145416633 ]) rfreq = flex.double(1 / 99 * e for e in (range(1, 50))) assert approx_equal(pgram.spec, rspec) assert approx_equal(pgram.freq, rfreq) print "OK"
def test2(): # compare plots dat = flex.random_double(50) a = Periodogram(dat) b = rpgram(dat) from matplotlib.pyplot import ion ion() a.plot() b.plot()
def test_smoothed_even_and_odd_length(): """Test smoothed periodogram of even and odd length sequences versus results obtained using R's spec.pgram function""" # single kernel smoother, even length pgram = Periodogram(dat, spans=4) rspec = flex.double([ 22.60966340315627, 18.195262628604752, 12.801658008106513, 9.533830316034159, 6.842177109002613, 5.718913361175838, 5.016220391389688, 4.145220428761756, 6.187449533598165, 6.766923476486281, 6.909821176923462, 7.649546371537703, 5.17230337090994, 3.9639665387034815, 3.5977579212052033, 2.709855572127937, 2.971326160175313, 2.0596273980998854, 1.350969309569581, 1.3614783358645521, 1.1957180543273982, 1.371929975931356, 2.582821697871905, 4.389998004175942, 5.470564984068996, 5.702837024958528, 4.936416830929916, 3.8579727997111832, 3.4807017683590322, 3.7410950155083493, 3.82883637355107, 3.0830643475781216, 2.3152645100024487, 2.998560753435843, 3.7448691190604286, 4.131990941949487, 4.893824075832538, 4.706890853446401, 4.14044026592323, 4.029403976076368, 3.639046172087742, 2.595904577911505, 3.042008709376008, 4.431477356793608, 5.271945689431424, 5.625190475689571, 4.369874722298269, 2.363493276128358, 0.9196425124786836, 0.39711770973225585 ]) assert approx_equal(pgram.spec, rspec) # three kernel smoothers with differing lengths, odd length sequence dat2 = dat[0:99] pgram = Periodogram(dat2, spans=[4, 6, 4]) rspec = flex.double([ 17.314055274775985, 15.746715010053997, 13.51918957394817, 11.096669833901974, 8.94488071864728, 7.357033921545414, 6.4291723412721415, 6.06483632171929, 6.0180027558874265, 6.0556124717493125, 6.000976488762685, 5.756178307862047, 5.315663331116168, 4.716140919888478, 4.055823092903159, 3.4305933136199633, 2.8881959432238777, 2.4700815936067313, 2.2043629196392005, 2.1371110039637147, 2.318359384971553, 2.737953359136525, 3.3119078691830612, 3.8971755852383345, 4.358224117959523, 4.610902643634579, 4.617256999182198, 4.404925734628821, 4.07304004821836, 3.742088947852017, 3.4988298970826084, 3.377951237167512, 3.3623755402288427, 3.4107737746104503, 3.493901696666407, 3.5886989978152486, 3.6571955223055133, 3.6669320372957337, 3.6399826234621893, 3.6368323534539106, 3.701389530366984, 3.8389251460239517, 3.9895437773918845, 4.046699282044061, 3.92426466711323, 3.5960187967975505, 3.122909791584781, 2.6492847490141163, 2.349620740074152 ]) assert approx_equal(pgram.spec, rspec) print "OK"
def test1(): # Compare over a range of lengths from 2 to 200 with random data for i in range(2, 201): dat = flex.random_double(i) a = Periodogram(dat) b = rpgram(dat) assert approx_equal(a.freq, b.freq) assert approx_equal(a.spec, b.spec) print "OK"
def test3(): # compare smoothed pgrams with even and odd length sequences for i in range(2): dat = flex.random_double(50 + i) a = Periodogram(dat, spans=4) b = rpgram(dat, spans=4) #from matplotlib.pyplot import ion #ion() #a.plot() #b.plot() assert approx_equal(a.freq, b.freq) assert approx_equal(a.spec, b.spec) print "OK"
def test5(): # compare smoothed pgrams with convolved kernel, even and odd length sequences for i in range(2): dat = flex.random_double(50 + i) a = Periodogram(dat, spans=[4, 4]) b = rpgram(dat, spans=robjects.FloatVector(list([4, 4]))) #from matplotlib.pyplot import ion #ion() #a.plot() #b.plot() assert approx_equal(a.freq, b.freq) assert approx_equal(a.spec, b.spec) print "OK"
def __call__(self, calc_average_residuals=True, calc_periodograms=True, spans=(4, 4)): """Perform analysis and return the results as a list of dictionaries (one for each experiment)""" # if not doing further analysis, return the basic data if not calc_average_residuals and not calc_periodograms: return self._results # if we don't have average residuals already, calculate them if not self._average_residuals: for iexp in range(self._nexp): results_this_exp = self._results[iexp] block_size = results_this_exp.get("block_size") if block_size is None: continue phi_range = results_this_exp["phi_range"] nblocks = results_this_exp["nblocks"] ref_this_exp = self._reflections.select( self._reflections["id"] == iexp) x_resid = ref_this_exp["x_resid"] y_resid = ref_this_exp["y_resid"] phi_resid = ref_this_exp["phi_resid"] phi_obs_deg = ref_this_exp["xyzobs.mm.value"].parts( )[2] * RAD2DEG xr_per_blk = flex.double() yr_per_blk = flex.double() pr_per_blk = flex.double() for i in range(nblocks - 1): blk_start = phi_range[0] + i * block_size blk_end = blk_start + block_size sel = (phi_obs_deg >= blk_start) & (phi_obs_deg < blk_end) xr_per_blk.append(self._av_callback(x_resid.select(sel))) yr_per_blk.append(self._av_callback(y_resid.select(sel))) pr_per_blk.append(self._av_callback(phi_resid.select(sel))) # include max phi in the final block blk_start = phi_range[0] + (nblocks - 1) * block_size blk_end = phi_range[1] sel = (phi_obs_deg >= blk_start) & (phi_obs_deg <= blk_end) xr_per_blk.append(self._av_callback(x_resid.select(sel))) yr_per_blk.append(self._av_callback(y_resid.select(sel))) pr_per_blk.append(self._av_callback(phi_resid.select(sel))) # the first and last block of average residuals (especially those in # phi) are usually bad because rocking curves are truncated at the # edges of the scan. When we have enough blocks and they are narrow, # just replace the extreme values with their neighbours if nblocks > 2 and block_size < 3.0: xr_per_blk[0] = xr_per_blk[1] xr_per_blk[-1] = xr_per_blk[-2] yr_per_blk[0] = yr_per_blk[1] yr_per_blk[-1] = yr_per_blk[-2] pr_per_blk[0] = pr_per_blk[1] pr_per_blk[-1] = pr_per_blk[-2] results_this_exp["av_x_resid_per_block"] = xr_per_blk results_this_exp["av_y_resid_per_block"] = yr_per_blk results_this_exp["av_phi_resid_per_block"] = pr_per_blk self._average_residuals = True # Perform power spectrum analysis on the residuals, converted to microns # and mrad to avoid tiny numbers if calc_periodograms: if self._spectral_analysis: return self._results for exp_data in self._results: exp_data["x_periodogram"] = None exp_data["y_periodogram"] = None exp_data["phi_periodogram"] = None if exp_data["nblocks"] < 5: continue for pname, data in zip( ["x_periodogram", "y_periodogram", "phi_periodogram"], [ exp_data["av_x_resid_per_block"], exp_data["av_y_resid_per_block"], exp_data["av_phi_resid_per_block"], ], ): if (flex.max(data) - flex.min(data)) > 1.0e-8: exp_data[pname] = Periodogram(1000.0 * data, spans=spans) self._spectral_analysis = True # extract further information from the power spectrum for exp_data in self._results: exp_data["x_interval"] = self._analyse_periodogram( exp_data["x_periodogram"]) exp_data["y_interval"] = self._analyse_periodogram( exp_data["y_periodogram"]) exp_data["phi_interval"] = self._analyse_periodogram( exp_data["phi_periodogram"]) return self._results