text:
1 Introduction
Abstract

The correspondence between theories in anti–de Sitter space and field theories in physical space-time leads to an analytic, semiclassical model for strongly-coupled QCD which has scale invariance at short distances and color confinement at large distances. These equations, for both mesons and baryons, give a very good representation of the observed hadronic spectrum, including a zero mass pion. Light-front holography allows hadronic amplitudes in the AdS fifth dimension to be mapped to frame-independent light-front wavefunctions of hadrons in physical space-time, thus providing a relativistic description of hadrons at the amplitude level. The meson and baryon wavefunctions derived from light-front holography and AdS/QCD also have remarkable phenomenological features, including predictions for the electromagnetic form factors and decay constants. The approach can be systematically improved using light-front Hamiltonian methods. Some novel features of QCD for baryon physics are also discussed.

SLAC–PUB–14381

Applications of AdS/QCD and Light-Front Holography

to Baryon Physics

Stanley J. Brodsky, and Guy F. de Téramond

SLAC National Accelerator Laboratory, Stanford University, Stanford, CA 94309, USA

Universidad de Costa Rica, San José, Costa Rica

1 Introduction

The light-front wavefunctions (LFWFs) of relativistic bound states in quantum chromodynamics provide a fundamental description of the structure and internal dynamics of hadronic states in terms of their constituent quark and gluons at a fixed light-front time , the time marked by the front of a light wave, [1, 2] – rather than at instant time , the ordinary time. Unlike instant time quantization, the Hamiltonian equation of motion in the light front (LF) is frame independent. The simple structure of the light-front vacuum allows an unambiguous definition of the partonic content of a hadron in QCD and of hadronic light-front wavefunctions which relate its quark and gluon degrees of freedom to their asymptotic hadronic state. For example, the proton’s eigenstate , the lightest , eigenstate of the QCD LF Hamiltonian, can be expanded in terms of the light front Fock components: corresponding to its , etc. projections. Here are the light-front momentum fractions of the constituents. The plus momentum and transverse momenta are conserved at fixed , and in each parton wavefunction. Remarkably, the are independent of the hadrons 4-momentum In light-cone gauge , the gluon quanta have and there are no ghosts. Angular momentum on the LF is simply since there are only independent orbital angular momentum. The angular momentum carried by the gluon in the proton as measured by experiment is simply the mean value of summed over Fock states. The structure functions measured by experiment in deep inelastic proton scattering (DIS) are related to the absolute square of the LFWFs summed over Fock states. The proton’s Dirac and Pauli form factors have an exact representation as the spin-conserving and spin-flip overlaps of initial and final wavefunctions, respectively. Unlike the ordinary instant form, there are no diagrams where the current couples to vacuum currents, and the boost of the LFWFs is trivial. Given, the LFWFs, one can compute hadronization at the amplitude level from the coalescence of a set of comoving color-singlet quarks and gluons, [3] in analogy to the formation of moving atoms in quantum electrodynamics. [4]

There are many novel features of baryons which are illuminated using the LFWF representation:

1. The higher Fock states of baryons contain intrinsic heavy quark [5] such as ; these can arise from gluon splitting, but also from multi-connected amplitudes. The intrinsic heavy quark (IQ) contributions are maximal at minimum off-shellness of the LFWF; i.e, when the partons have the same rapidity. This corresponds to , so that the heavy quark have most of the momentum. In a collision the states are materialized and the quarks with the same rapidity such as coalesce to high baryons such as the and the observed at high at the ISR. [6] SELEX [7] has also discovered double charm baryons and at high this way. This suggests using the LHC beam in a fixed target mode to observe very heavy baryons at high such as the [8] Intrinsic heavy quarks also provide a novel mechanism to produce the Higgs meson and at high [9, 10]

2. High hadrons can be created directly from hard subprocesses such as and , rather than from quark of gluon fragmentation. [11] Since the direct hadrons are produced with small transverse size, they are color transparent and can traverse the nuclear medium without absorption. The direct processes have been seen in many experiments. They also account for the remarkable baryon anomaly observed in ion-ion collisions, [12] as well as the anomalously large power-law falloff of the inclusive cross sections for meson and baryon production at fixed and . Since there are no same-side hadrons, the direct processes are energy efficient, requiring the minimum incident parton momentum fractions where the parton distributions are maximal.

3. The Sivers effect in deep inelastic lepton-polarized proton scattering is most easily computed as an interference of the proton’s and LFWFs. [13] The Sivers spin-correlation is , which reflects the different phases of the and amplitudes due to final state interaction of the scattered quark with the proton’s spectators. The Sivers correlation for each quark is thus seen to be proportional to that quark’s contribution to the proton orbital angular momentum. The Sivers correlation has the opposite sign in Drell-Yan reactions [14, 15] because it measures initial state scattering of the annihilating quark. There are many other novel factorization-breaking effects which arise due to initial state or final state scattering of the active quark with the spectators, such as the double Bohr-Mulders correlation which leads to a breakdown of the PQCD Lam-Tung relation in Drell-Yan reactions. [16]

4. The quark condensate, normally identified as a vacuum expectation value is actually an “in-hadron” condensate associated with the sea quark excitations in the hadron’s higher particle number Fock states. [17, 18] The QCD vacuum is trivial - equal to the vacuum of the free theory in the front form, and there is thus no contribution to the cosmological constant within this framework.

2 AdS/QCD and Light Front Holography

The AdS/CFT correspondence [19] between string states on anti–de Sitter (AdS) space-time and conformal gauge field theories (CFT) in physical space-time has brought a new set of tools for studying the dynamics of strongly coupled quantum field theories, and it has led to new analytical insights into the confining dynamics of QCD which is difficult to realize using other methods. Most important, it provides an initial approximation to QCD which is analytically tractable and which can be systematically improved. The original conformal theory can be modified in the far infrared region of AdS space, for example by the introduction of a dilaton background, which yields a confining potential between the colored quarks. The resulting model is usually called AdS/QCD.

3 A Semiclassical Light-Front Approximation to Qcd

The eigenmass of hadrons in light-front theory is determined from the eigenvalue equation

 ⟨ψ(P′)|PμPμ|ψ(P)⟩=M2⟨ψ(P′)|ψ(P)⟩, (1)

where one can expand the initial and final hadronic state in terms of its Fock components. The computation is simplified in the frame where . We find

 M2=∑n∫[dxi][d2k⊥i]∑q(k2⊥q+m2qxq)|ψn(xi,k⊥i)|2+(interactions), (2)

plus similar terms for antiquarks and gluons (. The integrals in (2) are over the internal coordinates of the constituents for each Fock state

 (3)

with phase space normalization .

The LFWF can be expanded in terms of independent position coordinates , , conjugate to the relative coordinates , with . We can also express (2) in terms of the internal impact coordinates with the result

 M2=∑nn−1∏j=1∫dxjd2b⊥jψ∗n(xj,b⊥j)∑q⎛⎝−∇2b⊥q+m2qxq⎞⎠ψn(xj,b⊥j)+(interactions). (4)

The normalization is defined by . To simplify the discussion we will consider a two-parton hadronic bound state. In the limit of zero quark mass

 M2=∫10dxx(1−x)∫d2b⊥ψ∗(x,b⊥)(−∇2b⊥)ψ(x,b⊥)+(interactions). (5)

The functional dependence for a given Fock state is given in terms of the invariant mass

 M2n=(n∑a=1kμa)2=∑ak2⊥a+m2axa→k2⊥x(1−x), (6)

giving the measure of the off-energy shell of the bound state, . Similarly in impact space the relevant variable for a two-parton state is . Thus, to first approximation LF dynamics depend only on the boost invariant variable or , and hadronic properties are encoded in the hadronic mode from the relation

 ψ(x,ζ,φ)=eiLφX(x)ϕ(ζ)√2πζ, (7)

thus factoring out the angular dependence and the longitudinal, , and transverse mode with normalization .

We can write the Laplacian operator in (5) in circular cylindrical coordinates and factor out the angular dependence of the modes in terms of the Casimir representation of orbital angular momentum in the transverse plane. Using (7) we find [20]

 M2=∫dζϕ∗(ζ)√ζ(−d2dζ2−1ζddζ+L2ζ2)ϕ(ζ)√ζ+∫dζϕ∗(ζ)U(ζ)ϕ(ζ), (8)

where all the complexity of the interaction terms in the QCD Lagrangian is summed in the effective potential . The LF eigenvalue equation is thus a light-front wave equation for

 (−d2dζ2−1−4L24ζ2+U(ζ))ϕ(ζ)=M2ϕ(ζ), (9)

a relativistic single-variable LF Schrödinger equation. Its eigenmodes determine the hadronic mass spectrum and represent the probability amplitude to find -partons at transverse impact separation , the invariant separation between pointlike constituents within the hadron [21] at equal LF time. Extension of the results to arbitrary follows from the -weighted definition of the transverse impact variable of the spectator system [21]: , where is the longitudinal momentum fraction of the active quark. One can also generalize the equations to allow for the kinetic energy of massive quarks using Eqs. (2) or (4). In this case, however, the longitudinal mode does not decouple from the effective LF bound-state equations.

4 A Soft-Wall AdS/QCD Model for Mesons

The conformal algebraic structure of AdS/CFT can be extended to include a scale . This procedure breaks conformal invariance and provides a solution for the confinement of modes, while maintaining an integrable algebraic structure. It also allows one to determine the stability conditions for the solutions. The resulting model resembles the soft wall model of Ref. [23]. We write the bound-state LF Hamiltonian as a bilinear product of operators plus a constant to be determined:

 HνLF(ζ)=Π†ν(ζ)Πν(ζ)+C,   ν2≥0, (10)

where the LF generator and its adjoint

 Πν(ζ)=−i⎛⎝ddζ−ν+12ζ−κ2ζ⎞⎠,    Π†ν(ζ)=−i⎛⎝ddζ+ν+12ζ+κ2ζ⎞⎠, (11)

obey the commutation relation

 [Πν(ζ),Π†ν(ζ)]=2ν+1ζ2−2κ2. (12)

For and , the Hamiltonian is positive definite, and . For the Hamiltonian cannot be written as a bilinear product and the Hamiltonian is unbounded from below. The lowest stable solution of the extended LF Hamiltonian corresponds to and and it is massless, . We impose chiral symmetry by choosing and thus identifying the ground state with the pion. With this choice of the constant , the LF Hamiltonian (10) is

 HLF(ζ)=−d2dζ2−1−4L24ζ2+κ4ζ2+2κ2(L−1), (13)

with eigenfunctions

 ϕL(ζ)=κ1+L√2n!(n+L)!ζ1/2+Le−κ2ζ2/2LLn(κ2ζ2), (14)

and eigenvalues . This is illustrated in Fig. 1 for the pseudoscalar meson spectra.

The confining model has also an effective classical gravity description corresponding to an AdS geometry modified by a positive-sign dilaton background , with sign opposite to that of reference of Ref. [23]. The positive dilaton solution has interesting physical implications, since it leads to a confining potential between heavy quarks [25] and to a convenient framework for describing chiral symmetry breaking. [26] It also leads to the identification of a nonperturbative effective strong coupling and -functions which are in agreement with available data and lattice simulations.[27] In the presence of a dilaton profile the wave equation for a spin mode is given by [28]

 [z2∂2z−(3−2J−2κ2z2)z∂z+z2M2−(μR)2]ΦJ=0. (15)

Upon the substitution   and , we find the LF wave equation

 (−d2dζ2−1−4L24ζ2+κ4ζ2+2κ2(L+S−1))ϕμ1⋯μJ=M2ϕμ1⋯μJ, (16)

with and . Equation (16) has eigenfunctions given by (14) and eigenvalues . The results for vector mesons is illustrated in Fig. 1, where the spectrum is built by simply adding for a unit change in the radial quantum number, for a change in one unit in the orbital quantum number and for a change of one unit of spin to the ground state value of . Remarkably, the same rule holds for baryons as shown below.

5 Baryons in Light-Front Holography

The effective light-front wave equation which describes baryonic states in holographic QCD is a linear equation determined by the LF transformation properties of spin 1/2 states. We write

 DLF(ζ)ψ(ζ)=Mψ(ζ), (17)

where is a hermitian operator, , thus . We write as a product , where is the matrix valued (non-hermitian) generator

 Πν(ζ)=−i⎛⎝ddζ−ν+12ζγ⎞⎠. (18)

If follows from the square of , , that the matrices and are anti-commuting hermitian matrices with unit square. The operator and its adjoint thus satisfy the commutation relation

 [Πν(ζ),Π†ν(ζ)]=2ν+1ζ2γ. (19)

The light front Hamiltonian is

 HνLF(ζ)=Πν(ζ)†Πν(ζ)=−d2dζ2+(ν+12)2ζ2−ν+12ζ2γ. (20)

The LF equation , has a two-component solution

 ψ+(ζ)∼√ζJν(ζM),     ψ−(ζ)∼√ζJν+1(ζM), (21)

where . Thus is the four dimensional chirality operator . In the Weyl representation

 γ=(I00−I)    and    iα=(0I−I0). (22)

The effective LF equation for baryons (17) is equivalent to the Dirac equation describing the propagation of spin-1/2 hadronic modes, on AdS space

 [i(zηMNΓM∂N+2Γz)+μR]Ψ=0, (23)

where represent the indices of the full space with coordinates and . Upon the transformation , , we recover (17) with and . Higher spin fermionic modes , , with all polarization indices along the 3+1 coordinates follow by shifting dimensions as shown for the case of mesons.

6 A Soft-Wall Light-Front Model for Baryons

An effective LF equation for baryons with a mass gap is constructed by extending the conformal algebraic structure for baryons described above, following the analogy with the mesons. We write the effective LF Dirac equation (17) in terms of the matrix-valued operator and its adjoint

 Πν(ζ)=−i⎛⎝ddζ−ν+12ζγ−κ2ζγ⎞⎠,   Π†ν(ζ)=−i⎛⎝ddζ+ν+12ζγ+κ2ζγ⎞⎠, (24)

with the commutation relation

 [Πν(ζ),Π†ν(ζ)]=(2ν+1ζ2−2κ2)γ. (25)

The extended baryonic model also has a geometric interpretation. It corresponds to the Dirac equation in AdS space in presence of a linear potential

 [i(zηMNΓM∂N+2Γz)+κ2z+μR]Ψ=0, (26)

as can be shown directly by using the transformation , .

As for the case of the mesons Eq. (10) we write the LF Hamiltonian and chose the same value for : , effectively modifying the wave equation (26). With this choice for the LF Hamiltonian is

 HLF=−d2dζ2+(ν+12)2ζ2−ν+12ζ2γ5+κ4ζ2+κ2(2ν−3)+κ2γ5. (27)

The LF equation , has a two-component solution

 ψ+(ζ)∼ζ12+νe−κ2ζ2/2Lνn(κ2ζ2),    ψ−(ζ)∼ζ32+νe−κ2ζ2/2Lν+1n(κ2ζ2), (28)

and eigenvalues , identical for both plus and minus eigenfunctions.

The baryon interpolating operator , , is a twist 3, dimension operator with scaling behavior given by its twist-dimension . We thus require to match the short distance scaling behavior. Higher spin fermionic modes , , are obtained by shifting dimensions for the fields as in the bosonic case. Thus, as in the meson sector, the increase in the mass squared for higher baryonic states is , and , relative to the lowest ground state, the proton.

The predictions for the positive parity light baryons are shown in Fig. 2. As for the predictions for mesons in Fig. 1, only confirmed PDG [24] states are shown. The Roper state and the are well accounted for in this model as the first and second radial states. Likewise the corresponds to the first radial state of the family. The model is successful in explaining the important parity degeneracy observed in the light baryon spectrum, such as the , pair and the states which are degenerate within error bars. The parity degeneracy of baryons is also a property of the hard wall model, but radial states are not well described by this model. [29] For other recent calculations of the hadronic spectrum based on AdS/QCD, see Refs. [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44].

The proton eigenstate in light-front holography

 ψ(ζ)=ψ+(ζ)u++ψ−(ζ)u−, (29)

has and orbital components combined with spin components and respectively. An interesting feature of light front holography for baryons and massless quarks is that the lowest valence Fock states with and have the same probability

 ∫dζ|ψ+(ζ)|2=∫dζ|ψ−(ζ)|2, (30)

a manifestation of the chiral invariance of the theory for massless quarks. [45] This implies that the quarks carry zero angular momentum in the proton with and .

There are many other interesting predictions for baryons using AdS/QCD and light front holographic methods such as space-like and time-like Dirac and Pauli form factors, valence structure functions, etc. The AdS/QCD LF Hamiltonian also creates Fock states with extra quark-antiquark pairs [46] as in QCD(1+1).

7 Conclusions

We have derived a correspondence between a semiclassical first approximation to QCD quantized on the light-front and hadronic modes propagating on a fixed AdS background. This provides a duality between the bosonic and fermionic wave equations in AdS higher dimensional space and the corresponding LF equations in physical 3 + 1 space. The duality leads to Schrödinger and Dirac-like equations for hadronic bound states in physical space-time when one identifies the AdS fifth dimension coordinate with the LF coordinate . The light-front equations of motion, which are dual to an effective classical gravity theory, possess remarkable algebraic and integrability properties which follow from the underlying conformal properties of the theory. We also extend the algebraic construction to include a confining potential while preserving the integrability of the mesonic and baryonic bound-state equations.

The light-front holographic theory provides successful predictions for the light-quark meson and baryon spectra, as function of hadron spin, quark angular momentum, and radial quantum number. Using the positive dilaton background the pion is massless, corresponding to zero mass quarks, in agreement with chiral invariance arguments. Higher spin light-front equations can be derived by shifting dimensions in the AdS wave equations. [28] Unlike the top-down string theory approach, one is not limited to hadrons of maximum spin , and one can study baryons with finite color Both the hard and soft-wall models predict similar multiplicity of states for mesons and baryons as it is observed experimentally. [47] In the hard-wall model the dependence has the form: . However, in the soft-wall model the observed Regge behavior is found: which has the same slope in radial quantum number and orbital angular momentum.

The semiclassical AdS/QCD approximation to light-front QCD described in this talk breaks down at short distances where hard gluon exchange and quantum corrections become important. However, one can systematically improve the semiclassical approximation by introducing nonzero quark masses and short-range Coulomb corrections, thus extending the predictions of the model to the dynamics and spectra of heavy and heavy-light quark systems. One can also diagonalize the LF Hamiltonian as in DLCQ, but on the orthonormal basis states provided by AdS/QCD. [48] One could also employ Lippmann-Schwinger perturbation theory, systematically correcting the AdS/QCD eigensolutions.

Acknowledgments

Presented by SJB at the International Conference on the Structure of Baryons
BARYONS’10, December 7-11, 2010, Osaka, Japan. This research was supported by the Department of Energy contract DE–AC02–76SF00515. SLAC-PUB-14381

References

• [1] P. A. M. Dirac, Rev. Mod. Phys. 21, 392 (1949).
• [2] For a review of light-front quantization, see S. J. Brodsky, H. -C. Pauli, S. S. Pinsky, Phys. Rept. 301, 299-486 (1998) [hep-ph/9705477].
• [3] S. J. Brodsky, G. de Teramond, R. Shrock, AIP Conf. Proc. 1056, 3-14 (2008) [arXiv:0807.2484 [hep-ph]].
• [4] C. T. Munger, S. J. Brodsky, I. Schmidt, Phys. Rev. D49, 3228-3235 (1994).
• [5] S. J. Brodsky, P. Hoyer, C. Peterson, N. Sakai, Phys. Lett. B93, 451-455 (1980).
• [6] G. Bari, M. Basile, G. Bruni et al., Nuovo Cim. A104, 1787-1800 (1991).
• [7] M. Mattson et al. [ SELEX Collaboration ], Phys. Rev. Lett. 89, 112001 (2002) [hep-ex/0208014].
• [8] S. J. Brodsky, .J Fleuret, J. P. Lansberg, C. Lorce (in progress).
• [9] S. J. Brodsky, B. Kopeliovich, I. Schmidt, J.-Soffer, Phys. Rev. D73, 113005 (2006) [hep-ph/0603238].
• [10] S. J. Brodsky, A. S. Goldhaber, B. Z. Kopeliovich,I. Schmidt, Nucl. Phys. B807, 334-347 (2009) [arXiv:0707.4658 [hep-ph]].
• [11] F. Arleo, S. J. Brodsky, D. S. Hwang, A. Sickles, Phys. Rev. Lett. 105, 062002 (2010) [arXiv:0911.4604 [hep-ph]].
• [12] S. J. Brodsky, A. Sickles, Phys. Lett. B668, 111-115 (2008) [arXiv:0804.4608 [hep-ph]].
• [13] S. J. Brodsky, D. S. Hwang, I. Schmidt, Phys. Lett. B530, 99-107 (2002) [hep-ph/0201296].
• [14] J. C. Collins, Phys. Lett. B536, 43-48 (2002) [hep-ph/0204004].
• [15] S. J. Brodsky, D. S. Hwang, I. Schmidt, Nucl. Phys. B642, 344-356 (2002) [hep-ph/0206259].
• [16] D. Boer, S. J. Brodsky, D. S. Hwang, Phys. Rev. D67, 054003 (2003). [hep-ph/0211110].
• [17] S. J. Brodsky, R. Shrock, Proc. Nat. Acad. Sci. 108, 45-50 (2011) [arXiv:0905.1151 [hep-th]].
• [18] S. J. Brodsky, C. D. Roberts, R. Shrock , P. Tandy, Phys. Rev. C82, 022201 (2010) [arXiv:1005.4610 [nucl-th]].
• [19] J. M. Maldacena, Adv. Theor. Math. Phys. 2, 231 (1998) [Int. J. Theor. Phys. 38, 1113 (1999)] [arXiv:hep-th/9711200].
• [20] G. F. de Teramond and S. J. Brodsky, Phys. Rev. Lett. 102, 081601 (2009) [arXiv:0809.4899 [hep-ph]].
• [21] S. J. Brodsky and G. F. de Teramond, Phys. Rev. Lett. 96, 201601 (2006) [arXiv:hep-ph/0602252]; Phys. Rev. D77, 056007 (2008) [arXiv:0707.3859 [hep-ph]].
• [22] S. J. Brodsky and G. F. de Teramond, Phys. Rev. D 78, 025032 (2008) [arXiv:0804.0452 [hep-ph]].
• [23] A. Karch, E. Katz, D. T. Son and M. A. Stephanov, Phys. Rev. D 74, 015005 (2006) [arXiv:hep-ph/0602229].
• [24] C. Amsler et al. (Particle Data Group), Phys. Lett. B 667 (2008) 1.
• [25] O. Andreev, Phys. Rev. D 73, 107901 (2006) [arXiv:hep-th/0603170].
• [26] F. Zuo, Phys. Rev. D 82, 086011 (2010) [arXiv:0909.4240 [hep-ph]].
• [27] S. J. Brodsky, G. F. de Teramond, A. Deur, Phys. Rev. D81, 096010 (2010) [arXiv:1002.3948 [hep-ph]].
• [28] G. F. de Teramond, S. J. Brodsky, Nucl. Phys. Proc. Suppl. 199, 89-96 (2010) [arXiv:0909.3900 [hep-ph]].
• [29] G. F. de Teramond and S. J. Brodsky, Phys. Rev. Lett. 94, 201601 (2005) [arXiv:hep-th/0501022].
• [30] H. Boschi-Filho and N. R. F. Braga, JHEP 0305, 009 (2003) [arXiv:hep-th/0212207].
• [31] H. Boschi-Filho, N. R. F. Braga and H. L. Carrion, Phys. Rev. D 73, 047901 (2006) [arXiv:hep-th/0507063].
• [32] N. Evans and A. Tedder, Phys. Lett. B 642, 546 (2006) [arXiv:hep-ph/0609112].
• [33] D. K. Hong, T. Inami and H. U. Yee, Phys. Lett. B 646, 165 (2007) [arXiv:hep-ph/0609270].
• [34] P. Colangelo, F. De Fazio, F. Jugeau and S. Nicotri, Phys. Lett. B 652, 73 (2007) [arXiv:hep-ph/0703316].
• [35] H. Forkel, Phys. Rev. D 78, 025001 (2008) [arXiv:0711.1179 [hep-ph]].
• [36] A. Vega and I. Schmidt, Phys. Rev. D 78, 017703 (2008) [arXiv:0806.2267 [hep-ph]].
• [37] K. Nawa, H. Suganuma and T. Kojo, Mod. Phys. Lett. A 23, 2364 (2008) [arXiv:0806.3040 [hep-th]].
• [38] W. de Paula, T. Frederico, H. Forkel and M. Beyer, Phys. Rev. D 79, 075019 (2009) [arXiv:0806.3830 [hep-ph]].
• [39] P. Colangelo, F. De Fazio, F. Giannuzzi, F. Jugeau and S. Nicotri, Phys. Rev. D 78, 055009 (2008) [arXiv:0807.1054 [hep-ph]].
• [40] H. Forkel and E. Klempt, Phys. Lett. B 679, 77 (2009) [arXiv:0810.2959 [hep-ph]].
• [41] H. C. Ahn, D. K. Hong, C. Park and S. Siwach, Phys. Rev. D 80, 054001 (2009) [arXiv:0904.3731 [hep-ph]].
• [42] Y. Q. Sui, Y. L. Wu, Z. F. Xie and Y. B. Yang, Phys. Rev. D 81, 014024 (2010) [arXiv:0909.3887 [hep-ph]].
• [43] M. Kirchbach, C. B. Compean, Phys. Rev. D82, 034008 (2010) [arXiv:1003.1747 [hep-ph]].
• [44] T. Branz, T. Gutsche, V. E. Lyubovitskij et al., Phys. Rev. D82, 074022 (2010) [arXiv:1008.0268 [hep-ph]].
• [45] S. J. Brodsky, G. F. de Teramond, Acta Phys. Pol. B 41, 2605 (2010) [arXiv:1009.4232 [hep-ph]].
• [46] G. F. de Teramond, S. J. Brodsky [arXiv:1010.1204 [hep-ph]].
• [47] E. Klempt and A. Zaitsev, Phys. Rept. 454, 1 (2007) [arXiv:0708.4016 [hep-ph]].
• [48] J. P. Vary, H. Honkanen, J. Li et al., Phys. Rev. C81, 035205 (2010) [arXiv:0905.1411 [nucl-th]].
You are adding the first comment!
How to quickly get a good reply:
• Give credit where it’s due by listing out the positive aspects of a paper before getting into which changes should be made.
• Be specific in your critique, and provide supporting evidence with appropriate references to substantiate general statements.
• Your comment should inspire ideas to flow and help the author improves the paper.

The better we are at sharing our knowledge with each other, the faster we move forward.
The feedback must be of minimum 40 characters and the title a minimum of 5 characters


text:
• 研究论文 •

### 祁连山东段石羊河流域河流纵剖面及其构造意义

1. 1. 中国地震局兰州地震研究所, 兰州 730000;
2. 南京大学地球科学与工程学院, 南京 210000
• 收稿日期:2018-12-05 修回日期:2019-02-19 出版日期:2019-04-20 发布日期:2019-05-21
• 通讯作者: 谢虹,女,副研究员,E-mail:xiehlz@126.com
• 作者简介:高效东,男,1994年生,中国地震局兰州地震研究所活动构造与构造地貌学专业在读硕士研究生,主要研究方向为新活动构造与构造地貌,E-mail:norman_gaoxd@163.com。
• 基金资助:
中国地震局基本科研业务专项（2014IESLZ07）、中国地震局地震行业科研专项（201408023）和国家自然科学基金（41302174）共同资助

### LONGITUDINAL PROFILES AND THEIR TECTONIC SIGNIFICANCE OF THE SHIYANGHE RIVER BASIN IN THE EASTERN QILIANSHAN MOUNTAINS

1. 1. Lanzhou Institute of Seismology, CEA, Lanzhou 730000, China;
2. School of Earth Sciences and Engineering, Nanjing University, Nanjing 210000, China
• Received:2018-12-05 Revised:2019-02-19 Online:2019-04-20 Published:2019-05-21

Abstract: The river system is very sensitive to landscape fluctuations and the pattern of drainage contains the past and present tectonic information and can record the latest even tiny change along the orogenic belt system. Therefore, fluvial geomorphology is always used to describe the shapes of river channels and recognize the different segments of active faults. Qualitative and quantitative geomorphic analyses can provide useful information on detecting active tectonic features and the influence of landscape change and evolution. Quantitative analysis such as analysis of river longitudinal profile and geomorphic indices can help researchers evaluate the relative level of tectonic activity and characterize the geomorphic features of landscape quantitatively.
Our study focuses on the geomorphic analysis of Shiyanghe River Basin which is located in the eastern part of Qilianshan Mountains. The tectonic deformation is very strong since late Cenozoic, and Quaternary active thrust faults, strike-slip faults and active folds are distributed all over the region, indicating that the whole region is suffering from crustal shortening and sinistral shear. In this region, the latest tectonic deformation and tectonic activities have been recorded by its fluvial system.
Based on GIS spatial analysis technology, the longitudinal profiles of seven tributaries(including Gulanghe River, Huangyanghe River, Jintahe River, Zamuhe River, Xiyinghe River, Dongdahe River and Xidahe River)in the Shiyanghe River Basin are extracted by using digital elevation models(DEM)and Matlab script. In channel longitudinal profiles, most tributaries in Shiyanghe River Basin exhibit an increased channel gradient in their midstream and downstream area. This pattern is consistent with the models of transient channel profile which suggests an increase in rock uplift rate or base level fall. The longitudinal profiles of seven tributaries are analyzed synthetically by using the method of bedrock channel erosion model, and the concavity(θ), steepness index(ksn), as well as the knickpoints information(including distribution, elevation, distance from mouth and drainage area)of seven tributaries are obtained. The result shows that each of the tributaries in the Shiyanghe River Basin at least has one major knickpoint. The comprehensive study of the longitudinal profiles, knickpoints and the lithology of the river basin show that the Gulanghe River, Jintahe River, Zamuhe River, Xiyinghe River, Dongdahe River and Xidahe River all have ‘slope-break’ knickpoints, which suggest that they are in a transient state. The knickpoints represent a transient response to the dynamic surface uplift since late Cenozoic. Therefore, we can conclude that the evolution of fluvial geomorphology in eastern Qilian Mountains is mainly related to tectonic activities. Channel segments upstream of knickpoints exhibit lower concavities(mean θ is 0.458±0.053)and higher channel steepness indices(mean ksn is 129.09±1.82). In contrast, lower channel segments are more complanate(mean ksn is 68.162±0.821)and exhibit a higher concavity(mean θ is 0.831±0.147). The distribution of concavity is related to the erosion rate, thence, we can infer that the higher value of concavity in downstream area indicates the higher erosion rate. Because the different steepness index(ks)and the concavity(θ)below and above the reach of knickpoints indicate that they have different development trends in different channel segments, and the distribution of knickpoints represent the evolution process of the longitudinal section of the tributaries. Using the concavity value of the knickpoint, each lower reach longitudinal profile of tributary is fitted. According to the fitted result, the calculated approximate average erosion volume of the Shiyanghe River Basin is 488m since it formed, and the average erosion volume of the six tributaries, which originated in Gulang nappe, is 508.5m. The total amount of erosion is positively correlated with rock uplift when a river is in transient state. Thence, it concludes that the Gulang nappe has experienced a strong uplift. Furthermore, we obtained the spatial distribution of ksn values of the whole fluvial system in the Shiyanghe River Basin from calculating and interpolating the ksn values, and combined the geomorphic parameters results to analyze the tectonic significance of the Shiyanghe River Basin synthetically. The spatial distribution of ksn values of the Shiyanghe River Basin represent the accommodation of geomorphic landscape to the tectonic force and the manner of channels responding to tectonic forces. In this study, most of the channel gradients obtained from midstream are higher than upstream and downstream and ksn values in downstream reaches is less than 60m0.9, the high ksn values are in the Gulang nappe, reaching over 1 400m0.9, which indicates that the Gulang nappe has experienced uplift since the Quaternary. Therefore, we conclude that the regional difference of the ksn is mainly controlled by the uplift rate of bedrocks.
Based on the comprehensive analysis of geomorphic parameters and tectonic background, we conclude that the geomorphic evolution of the Shiyanghe River Basin is in a non-equilibrium state, and the tectonic deformation is the main factor affecting the geomorphic evolution of the eastern Qilianshan Mountains and controlling the present tectonic pattern, geomorphic development and evolution history of the study area.
According to the river longitudinal profiles and modeling analysis, this study indicates that the quantitative geomorphic analyses can provide useful and effective information on detecting active tectonic features and the influence of landscape change and evolution, and the geomorphic indices are useful and appropriate tools to analyze the coupling of tectonic and geomorphy.

format: plain


text:
# 2.5 Introduction to Finite Volume Methods

## 2.5.4 Finite Volume Method for 2-D Convection on a Rectangular Mesh

% Script: convect2d.m

close all;
clear all;

% Specify x range and number of points
x0 = -2;
x1 =  2;
Nx = 40;

% Specify y range and number of points
y0 = -2;
y1 =  2;
Ny = 40;

% Construct mesh
x       = linspace(x0,x1,Nx+1);
y       = linspace(y0,y1,Ny+1);
[xg,yg] = ndgrid(x,y);

% Construct mesh needed for plotting
xp = zeros(4,Nx*Ny);
yp = zeros(4,Nx*Ny);
n = 0;
for j = 1:Ny,
for i = 1:Nx,

n = n + 1;
xp(1,n) = x(i);
yp(1,n) = y(j);

xp(2,n) = x(i+1);
yp(2,n) = y(j);

xp(3,n) = x(i+1);
yp(3,n) = y(j+1);

xp(4,n) = x(i);
yp(4,n) = y(j+1);

end
end

% Calculate midpoint values in each control volume
xmid = 0.5*(x(1:Nx) + x(2:Nx+1));
ymid = 0.5*(y(1:Ny) + y(2:Ny+1));

[xmidg,ymidg] = ndgrid(xmid,ymid);

% Calculate cell size in control volumes (assumed equal)
dx = x(2) - x(1);
dy = y(2) - y(1);
A  = dx*dy;

% Set velocity
u = 1;
v = 1;

% Set final time
tfinal = 10;

% Set timestep
CFL = 1.0;
dt = CFL/(abs(u)/dx + abs(v)/dy);

% Set initial condition to U0 = exp(-x^2 - 20*y^2)
% Note: technically, we should average the initial
% distribution in each cell but I chose to just set
% the value of U in each control volume to the midpoint
% value of U0.
U = exp(-xmidg.^2 - 20*ymidg.^2);
t = 0;

% Loop until t > tfinal
while (t < tfinal),

% The following implement the bc's by creating a larger array
% for U and putting the appropriate values in the first and last
% columns or rows to set the correct bc's
Ubc(2:Nx+1,2:Ny+1) = U; % Copy U into Ubc
Ubc(   1,2:Ny+1)   = U(Nx, :); % Periodic bc
Ubc(Nx+2,2:Ny+1)   = U( 1, :); % Periodic bc
Ubc(2:Nx+1,   1)   = U( :,Ny); % Periodic bc
Ubc(2:Nx+1,Ny+2)   = U( :, 1); % Periodic bc

% Calculate the flux at each interface

% First the i interfaces
F =   0.5*    u *( Ubc(2:Nx+2,2:Ny+1) + Ubc(1:Nx+1,2:Ny+1)) ...
- 0.5*abs(u)*( Ubc(2:Nx+2,2:Ny+1) - Ubc(1:Nx+1,2:Ny+1));

% Now the j interfaces
G =   0.5*    v *( Ubc(2:Nx+1,2:Ny+2) + Ubc(2:Nx+1,1:Ny+1)) ...
- 0.5*abs(v)*( Ubc(2:Nx+1,2:Ny+2) - Ubc(2:Nx+1,1:Ny+1));

% Add contributions to residuals from fluxes
R = (F(2:Nx+1,:) - F(1:Nx,:))*dy + (G(:,2:Ny+1) - G(:,1:Ny))*dx;

% Forward Euler step
U = U - (dt/A)*R;

% Increment time
t = t + dt;

% Plot current solution
Up = reshape(U,1,Nx*Ny);
clf;
[Hp] = patch(xp,yp,Up);
set(Hp,'EdgeAlpha',0);
axis('equal');
caxis([0,1]);
colorbar;
drawnow;

end

## Exercise

Copy the MATLAB® code above and determine which of the following timesteps ($$\Delta t$$) is the largest that still remains stable.

Exercise 1

Answer: The CFL condition (to be discussed in a later module) tells us that $$\Delta t = 0.05$$ is the largest timestep choice that will remain stable.


text:
# DerivativeBase¶

class DerivativeBase[소스]

기반 클래스: qiskit.aqua.operators.converters.converter_base.ConverterBase

Base class for differentiating opflow objects.

Converter for differentiating opflow objects and handling things like properly differentiating combo_fn’s and enforcing product rules when operator coefficients are parameterized.

This is distinct from CircuitGradient converters which use quantum techniques such as parameter shifts and linear combination of unitaries to compute derivatives of circuits.

CircuitGradient - uses quantum techniques to get derivatives of circuits DerivativeBase - uses classical techniques to differentiate opflow data structures

Methods

 convert type operator OperatorBase gradient_wrapper Get a callable function which provides the respective gradient, Hessian or QFI for given parameter values. parameter_expression_grad Get the derivative of a parameter expression w.r.t.


text:
# Homework Help: Show that a Sequence is monotonically decreasing

1. Dec 9, 2014

### Calu

• Member warned about deleting template parts
1. The problem statement, all variables and given/known data

I was wondering how I would go about showing that (an) is monotone decreasing given that an = 1/√n.

I believe I have to show an ≥ an+1, but I'm not sure how to go about doing that.

2. Dec 9, 2014

### Ray Vickson

Well, PF rules require you to make a start on your own. What do you know about the magnitudes of $\sqrt{n}$ and $\sqrt{n+1}$?

3. Dec 9, 2014

### Calu

I know that the magnitude of $\sqrt{n+1}$ is larger than that of $\sqrt{n}$. Therefore I would assume that the opposite would be true for the magnitude of their reciprocals which would make an≥an+1 as required, however I'm not sure how to write this in a more coherent way.

4. Dec 9, 2014

### pasmith

(1) $\sqrt{n + 1} > \sqrt{n}$.
(2) If $n > 0$ then dividing both sides by $\sqrt{n} > 0$ preserves the inequality. Hence $\frac{\sqrt{n + 1} }{\sqrt{n}} > 1$.
(3) Dividing both sides by ... > 0 preserves the inequality. Hence ...


text:
# Interface¶

## Main Interface¶

pinq.as_queryable(iterable)

Constructs a queryable object using iterable as the base data.

Parameters: iterable (Iterable) – iterable object to make queryable. a queryable object with the specified iterable as the underlying data Queryable object TypeError – if iterable is not an Iterable

Usage:

>>> import pinq
>>> queryable = pinq.as_queryable(range(100))

## Queryable’s and Their Methods¶

class pinq.queryable.Queryable(iterator)

Bases: object

A wrapper for iterable objects to allow querying of the underlying data.

aggregate(accumulator, seed=None, result_transform=<function identity>)

Applies an accumulator function over a sequence.

Parameters: accumulator (function) – The accumulator function to apply. seed – (optional) The initial accumulator value. result_transform (function) – (optional) A transform function to apply to the result. The accumulated value. TypeError – if ‘accumulator’ is not callable TypeError – if ‘result_transform’ is not callable
all(predicate)

Determines whether all elements of the sequence satisfy a condition.

Parameters: predicate (function) – A function to test each element for a condition. True if every element satisfies the condition, or the sequence is empty. bool TypeError – if ‘predicate’ is not callable
any(predicate=<function true>)

Determines whether any element of the sequence satisfies a condition.

Parameters: predicate (function) – (optional) A function to test each element for a condition. True if any element satisfies the condition. bool TypeError – if ‘predicate’ is not callable
average(transform=<function identity>)

Computes the average of the elements in the sequence.

Parameters: transform (function:) – (optional) A transform function to invoke on each element of the sequence. The average value of the elements in the sequence. float TypeError – if ‘transform’ is not callable
cast(to_type)

Casts the elements of the sequence to the specified type.

Parameters: to_type (type) – The type to cast elements to. The elements of the sequence cast to the specified type. Queryable TypeError – if ‘to_type’ is not callable
concat(other)

Concatenates two sequences.

Parameters: other (Iterable) – The sequence to concatenate to this sequence. A Queryable containing the concatenated elements of the two input sequences. Queryable TypeError – if ‘other’ is not Iterable
contains(value, equality_comparer=<built-in function eq>)

Determines whether the sequence contains the specified value.

Parameters: value – The value to find in the sequence. equality_comparer (function) – (optional) An equality comparer to compare values. True if the sequence contains the specified value. bool TypeError – if ‘equality_comparer’ is not callable
count(predicate=<function true>)

Returns the number of elements in the sequence.

Parameters: predicate (function) – (optional) A function to test each element for a condition: The number of elements that satisfy the specified condition. int TypeError – if ‘predicate’ is not callable
default_if_empty(default_value=None)

Returns the sequence or a sequence with a single default value if the sequence is empty.

Parameters: default_value – (optional) The default value to return.

:return:This sequence, or a sequence containing ‘default_value’ if it is empty. :rtype: Queryable

difference(other, key_selector=<function identity>)

Returns the set difference of the two sequences.

Parameters: other (Iterable) – An iterable of elements to be removed from this sequence. key_selector (function) – (optional) An function to select a key for comparing values. The set difference of this sequence and the provided sequence. Queryable TypeError – if ‘other’ is not an Interable TypeError – if ‘key_selector’ is not callable
distinct(key_selector=<function identity>)

Returns distinct elements fromt the sequence.

Parameters: key_selector (function) – (optional) An function to select a key for comparing values. A sequence of distinct elements from this sequence. Queryable TypeError – if ‘key_selector’ is not callable
element_at(index)

Returns the element at the specified location in the sequence.

Parameters: index (int) – The zero-based index of the element to retrieve. The element at the specified location in the sequence. TypeError – if ‘index’ is not an int IndexError – if ‘index’ is less than zero or larger than the number of elements
element_at_or_default(index, default_value=None)

Returns the element at the specified index or a default value if it is out of range.

Parameters: index (int) – The zero-based index of the element to retrieve. default_value – (optional) The default value if the index is out of range. The element at the specified location in the sequence. TypeError – if ‘index’ is not an int
except_values(other, key_selector=<function identity>)

Returns the set difference of the two sequences.

Parameters: other (Iterable) – An iterable of elements to be removed from this sequence. key_selector (function) – (optional) An function to select a key for comparing values. The set difference of this sequence and the provided sequence. Queryable TypeError – if ‘other’ is not an Interable TypeError – if ‘key_selector’ is not callable
first(predicate=<function true>)

Returns the first element in the sequence.

Parameters: predicate (function) – (optional) A function to test each element for a condition. The first element of the sequence satisfying the condition. TypeError – if ‘predicate’ is not callable ValueError – if the sequence is empty ValueError – if no element satisfies the condition
first_or_default(predicate=<function true>, default_value=None)

Returns the first element in the sequence or a default value if empty.

Parameters: predicate (function) – (optional) A function to test each element for a condition. default_value – (optional) The default value to return if empty. The first element of the sequence satisfying the condition. TypeError – if ‘predicate’ is not callable
group_by(key_selector, value_transform=<function identity>, result_transform=<function identity>)

Groups the elements of the sequence according to the specified key selector function.

Parameters: key_selector (function) – A function to extract the key for each element. value_transform (function) – A transform function to be applied to each element. result_transform (function) – A transform function to be applied to each group. A sequence where each element represents the transformation of a group and its key. Queryable TypeError – if ‘key_selector’ is not callable TypeError – if ‘value_transform’ is not callable TypeError – if ‘result_transform’ is not callable
group_join(other, key_selector, other_key_selector, result_transform)

Correlates the elements of the two sequences and groups the results.

Parameters: other (Iterable) – The sequence to join this sequence. key_selector (function) – A function to extract a key from each element of this sequence. other_key_selector (function) – A function to extract a key from each element of ‘other’. result_transform (function) – A function to create a result from an item and its matching group. The elements of the two sequences after performing a grouped join. Queryable TypeError – if ‘other’ is not an Iterable TypeError – if ‘key_selector’ is not callable TypeError – if ‘other_key_selector’ is not callable TypeError – if ‘result_transform’ is not callable
intersect(other, key_selector=<function identity>)

Returns the set intersection of the two sequences.

Parameters: other (Iterable) – A sequence to compute the intersection with. key_selector (function) – (optional) A function to extract a key for each element for comparison. A sequence of distinct elements that are in both of the provided seequences. Queryable TypeError – if ‘other’ is not an Iterable TypeError – if ‘key_selector’ is not callable
join(other, key_selector, other_key_selector, result_transform)

Correlates the elements of the two sequences.

Parameters: other (Iterable) – The sequence to join this sequence. key_selector (function) – A function to extract a key from each element of this sequence. other_key_selector (function) – A function to extract a key from each element of ‘other’. result_transform (function) – A function to create a result from an item and its match. The elements of the two sequences after performing an inner join. Queryable TypeError – if ‘other’ is not an Iterable TypeError – if ‘key_selector’ is not callable TypeError – if ‘other_key_selector’ is not callable TypeError – if ‘result_transform’ is not callable
last(predicate=<function true>)

Returns the last item of the sequence.

Parameters: predicate (function) – (optional) A function to test each element for a condition. The last item in the sequence that satisfies the condition. TypeError – if ‘predicate’ is not callable ValueError – if the source iterable is empty ValueError – if no element satisfies condition
last_or_default(predicate=<function true>, default_value=None)

Returns the last item of the sequence.

Parameters: predicate (function) – (optional) A function to test each element for a condition. default_value – (optional) The default value to return if empty. The last item in the sequence that satisfies the condition. TypeError – if ‘predicate’ is not callable ValueError – if the source iterable is empty ValueError – if no element satisfies condition
long_count(predicate=<function true>)

Returns the number of elements in the sequence.

Parameters: predicate (function) – (optional) A function to test each element for a condition: The number of elements that satisfy the specified condition. int TypeError – if ‘predicate’ is not callable
max(transform=<function identity>)

Returns the maximum element in the sequence.

Parameters: transform (function) – (optional) A transformation function to apply to each element. The maximum element in the sequence. int TypeError – if ‘transform’ is not callable
min(transform=<function identity>)

Returns the minimum element in the sequence.

Parameters: transform (function) – (optional) A transformation function to apply to each element. The minimum element in the sequence. int TypeError – if ‘transform’ is not callable
of_type(of_type)

Filters the elements based on the specified type.

Parameters: of_type (type) – The type to keep. The elements of the sequence with the specified type. Queryable TypeError – if ‘of_type’ is not a type
order_by(key_selector)

Sorts the elements of the sequence in ascending order according to a key.

Parameters: key_selector (function) – A function to extract a key from an element. The elements of the sequence sorted in ascending order. OrderedQueryable TypeError – if ‘key_selector’ is not callable
order_by_descending(key_selector)

Sorts the elements of the sequence in descending order according to a key.

Parameters: key_selector (function) – A function to extract a key from an element. The elements of the sequence sorted in descending order. OrderedQueryable TypeError – if ‘key_selector’ is not callable
reverse()

Reverses the order of the elements in the sequence.

Returns: The elements of the sequence in reverse order. Queryable
select(selector)

Returns the elements of the sequence after applying a transform function to each element.

Parameters: selector (function) – A transform function to apply to each element. The elements of the sequence after applying the transform function. Queryable TypeError – if ‘selector’ is not callable
select_many(selector, result_transform=<function select_i.<locals>.<lambda>>)

Projects each element to a sequence and flattens the resulting sequences.

Parameters: selector (function) – A function to transform each element into a sequence. result_transform (function) – (optional) A transform function for items of the selected sequence. A flattened sequence of transformed elements. Queryable TypeError – if ‘selector’ is not callable TypeError – if ‘result_transform’ is not callable
sequence_equal(other, equality_comparer=<built-in function eq>)

Determines whether two sequences are equal.

Parameters: other (Iterable) – The sequence to compare elements to. equality_comparer (function) – (optional) The equality comparison function to use. True if the sequences are equal, false otherwise. bool TypeError – if ‘other’ is not an Iterable TypeError – if ‘equality_comparer’ is not callable
single(predicate=<function true>)

Returns the only element of the sequence.

Parameters: predicate (function) – (optional) A function to test an element for a condition. The single element of the sequence satisfying the condition. TypeError – if ‘predicate’ is not callable ValueError – if the sequence is empty ValueError – if no element satisfies the condition ValueError – if more than one element satisfies the condition
single_or_default(predicate=<function true>, default_value=None)

Returns the only element of the sequence.

Parameters: predicate (function) – (optional) A function to test an element for a condition. default_value – (optional) The default value to return if empty. The single element of the sequence satisfying the condition. TypeError – if ‘predicate’ is not callable ValueError – if more than one element satisfies the condition
skip(num)

Skips a specified number of elements in the sequence and returns the remaining elements.

Parameters: num (int) – The number of elements to skip. A sequence containing the elements after position ‘num’. Queryable TypeError – if ‘num’ is not an int
skip_while(predicate)

Skip elements of the sequence while the specified condition is true.

Parameters: predicate (function) – The condition to check for. Elements of the sequence after the first item to fail the specified condition. Queryable TypeError – if ‘condition’ is not callable
sum(transform=<function identity>)

Computes the sum of the sequence by invoking a transform on each element.

Parameters: transform (function) – (optional) A transform function to apply to each element. The sum of the elements of the sequence. int TypeError – if ‘transform’ is not callable
take(num)

Takes the specified number of elements from the start of the sequence.

Parameters: num (int) – The number of elements to take. The specified number of elements from the start of the sequence. Queryable TypeError – if ‘num’ is not an int
take_while(predicate)

Takes elements from the start of the sequence while the specified condition holds.

Parameters: predicate (function) – The condition to check for. The elements from the start of the sequence that satisfy the condition. Queryable TypeError – if ‘predicate’ is not callable
to_dict(key_selector, value_selector=<function identity>)

Creates a dictionary object according to the specified key selector function.

Parameters: key_selector (function) – A function to extract the key for the dictionary entry. value_selector (function) – (optional) A function to extract the value for the dictionary entry. A dictionary of the elements in the sequence. dict TypeError – if ‘key_selector’ is not callable TypeError – if ‘value_selector’ is not callable
to_dictionary(key_selector, value_selector=<function identity>)

Creates a dictionary object according to the specified key selector function.

Parameters: key_selector (function) – A function to extract the key for the dictionary entry. value_selector (function) – (optional) A function to extract the value for the dictionary entry. A dictionary of the elements in the sequence. dict TypeError – if ‘key_selector’ is not callable TypeError – if ‘value_selector’ is not callable
to_list()

Creates a list object from the sequence.

Returns: A list of the elements in the sequence. list
union(other, key_selector=<function identity>)

Returns the set union of two sequences.

Parameters: other (Iterable) – The second sequence to produce the union with. key_selector (function) – (optional) A function to extract a key for comparison. The set union of the two sequences. Queryable TypeError – if ‘other’ is not an Iterable TypeError – if ‘key_selector’ is not callable
where(predicate)

Filters the sequence of values based on the specified condition.

Parameters: predicate – A function to check an element for a condition. The elements of the sequence that satisfy the condition. Queryable TypeError – if ‘predicate’ is not callable
zip(other, result_transform)

Applies a function to the corresponding elements of the two sequences.

Parameters: other (Iterable) – The other input sequence. result_transform (function) – A function that combines the corresponding elements. A sequence of elements of the two sequences combined using ‘result_transform’. Queryable TypeError – if ‘other’ is not an Iterable TypeError – if ‘result_transform’ is not callable
class pinq.queryable.OrderedQueryable(iterator, keys)

A wrapper for ordered sequences.

then_by(key_selector)

Performs a subsequenct ordering on the elements of an ordered sequence.

Parameters: key (function) – A function to extract a key to use for comparisons. The elements of the sequence in ascending order according to the key Queryable TypeError – if ‘key_selector’ is not callable
then_by_descending(key_selector)

Performs a subsequenct ordering on the elements of an ordered sequence.

Parameters: key (function) – A function to extract a key to use for comparisons. The elements of the sequence in descending order according to the key Queryable TypeError – if ‘key_selector’ is not callable


text:
## My Blank Pages VI: Programming in Igor Pro

It has been a long time since I wrote a book review.

A few months ago I read on IgorExchange that Martin Schmid had written a book about programming Igor. I snapped up a copy. I’m a competent Igor programmer but I was hoping that this book would be useful for lab members that want to learn.

Learning Igor – like most IDEs or programming languages – is tough going. There’s a booklet from WaveMetrics (the company that sells Igor Pro) called Getting Started – which is really good. There are a few other guides on the web (Payam’s guide, Thomas Braun’s coding conventions, quantixed’s own translator), but other resources are pretty scarce. The Igor Manual itself is excellent but it’s many, many pages long and is only meant to be consulted. So I was intrigued whether Martin Schmid’s book would fill the gap between Getting Started and more advanced guides.

What makes Igor Pro so fantastic is the way that you can use it for so many different things: image processing, statistics, graphing, curve fitting, instrument control and so on. Part of the challenge of writing a book on Igor Programming is deciding what to cover. Schmid deals with this by covering basic programming and core-intermediate topics such as dialogs, loops, string magic etc. The book stops short of any specialised applications. So it’s a really useful intermediate programming guide. It’s a great little book and is recommended for those who want to dig further after doing the Getting Started exercises.

I knew I would learn something from the book because there’s always alternative ways to do stuff in Igor: things that you didn’t know about or little tricks to do stuff faster. What I was surprised about was the first thing mentioned in the book was new to me. The author favours module-static programming. All of my Igor programming has been done in the global pragma and I have avoided this more C-like way of encapsulating programs that I’ve written so far. Module-static works well because it eliminates naming conflicts. I have dealt with name conflicts by using static functions which are called from the top of the stack, and the top has a unique name (arguably this is the same as module-static, but not identical). As the Igor Manual says “this gets tedious after a while” and that’s true. Although in my defence, name conflicts are generally not a problem for the way I work because I favour a reproducible approach. A new experiment is started – one user-written ipf is opened – and the code is run. This means naming conflicts are minimised. The book has actually convinced me that module-static is a good thing, especially since my Igor code is now deployed around the lab and naming conflicts could easily become a problem. It’s an advanced programming technique but is dealt with early by the author and it kind of works. After this, more basic programming topics are covered in depth.

There’s always room for improvement: there are several example programs at the back which need to be rekeyed to run, since this is a paper book and no electronic version is available AFAIK. The author has put one up here to save rekeying and another here, but otherwise you need to type in the examples to see what will happen. This is too long-winded. I’ve been spoiled reading texts about R where the examples can all be run from a markdown file inside RStudio. It would’ve been nice if the code was made available for this book. I don’t think it would compromise the value of the book since it is the text that is most valuable.

The book is available at Amazon for £7.99 at the time of writing.

My Blank Pages is a track by Velvet Crush. This is an occasional series of book reviews.

## Pledging My Time III

I’ve previously crunched times for local Half and Full Marathons here on quantixed. Last weekend was the Kenilworth Half Marathon (2018) over a new course. I thought I’d have a look at the distributions of times and paces of the runners. The times are available here. If the Time and Category for finishers are saved as a csv, the script below works to generate the following plots.

Aggregated stats for the race are here. The beeswarm plot nicely shows the distribution of runners times and paces per category. There’s a bimodality to some of the age groups which is interesting. You can see from the average times that people get slower as they get older, as expected.

There was a roughly 2:1 split of M:F runners with a similar proportion in all categories. The ratio is similar for DNSers. The winning times were Andrew Savery of Leamington C A & C in MV35 with 01:12:51 and Polly Keen of Nuneaton Harriers in F sen with 01:23:46.

Congrats to everyone who ran and thanks to the organisers and all the supporters out on the course.

require(ggplot2)
require(ggbeeswarm)
file_name <- file.choose()
df1 <- read.csv(file_name, header = TRUE, stringsAsFactors = FALSE)
# aggregate M and F to a new category called Gender
df1$Gender <- ifelse(startsWith(df1$Category,"F"),"F","M")
# format Date column to POSIXct
df1$Time <- as.POSIXct(strptime(df1$Time, format = "%H:%M:%S"))
orig_var <- as.POSIXct("00:00:00", format = "%H:%M:%S")
p1 <- ggplot( data = df1, aes(x = Category,y = Time, color = Category)) +
geom_quasirandom(alpha = 0.5, stroke = 0) +
stat_summary(fun.y = mean, geom = "point", size=2, aes(group = 1)) +
scale_y_datetime(date_labels = "%H:%M:%S", limits = c(orig_var,NA))
p1
# instead of finishing time, let's look at pace (min/km)
df1$Pace <- as.numeric(difftime(df1$Time, orig_var) / 21.1) * 3600
df1$Pace <- as.POSIXct(df1$Pace, origin = orig_var, format = "%H:%M:%S")
p2 <- ggplot( data = df1, aes(x = Category,y = Pace, color = Category)) +
geom_quasirandom(alpha = 0.5, stroke = 0) +
stat_summary(fun.y = mean, geom = "point", size=2, aes(group = 1)) +
scale_y_datetime(date_labels = "%M:%S", limits = c(orig_var,NA))
p2
# calculate speeds rather than pace
df1$Speed <- 21.1 / as.numeric(difftime(df1$Time, orig_var))
p3 <- ggplot( data = df1, aes(x = Category, y = Speed, color = Category)) +
geom_quasirandom(alpha = 0.5, stroke = 0) +
stat_summary(fun.y = mean, geom = "point", size=2, aes(group = 1)) +
ylim(0,NA) + ylab("Speed (km/h)")
p3
# now make the same plots but by Gender rather than Category
p4 <- ggplot( data = df1, aes(x = Gender,y = Time, color = Gender)) +
geom_quasirandom(alpha = 0.5, stroke = 0) +
stat_summary(fun.y = mean, geom = "point", size=2, aes(group = 1)) +
scale_y_datetime(date_labels = "%H:%M:%S", limits = c(orig_var,NA))
p4
p5 <- ggplot( data = df1, aes(x = Gender,y = Pace, color = Gender)) +
geom_quasirandom(alpha = 0.5, stroke = 0) +
stat_summary(fun.y = mean, geom = "point", size=2, aes(group = 1)) +
scale_y_datetime(date_labels = "%M:%S", limits = c(orig_var,NA))
p5
p6 <- ggplot( data = df1, aes(x = Gender, y = Speed, color = Gender)) +
geom_quasirandom(alpha = 0.5, stroke = 0) +
stat_summary(fun.y = mean, geom = "point", size=2, aes(group = 1)) +
ylim(0,NA) + ylab("Speed (km/h)")
p6
ggsave("raceTimeByCat.png", plot = p1)
ggsave("racePaceByCat.png", plot = p2)
ggsave("raceSpeedByCat.png", plot = p3)
ggsave("raceTimeByGen.png", plot = p4)
ggsave("racePaceByGen.png", plot = p5)
ggsave("raceSpeedByGen.png", plot = p6)

Edit 2018-09-12T18:52:43Z I wasn’t happy with the plots and added a few more lines to look at gender as well as category. And show speed as well as pace and finishing time.

The post title is taken from “Pledging My Time” a track from Blonde on Blonde by Bob Dylan

## Rip It Up: Grabbing movies from Twitter for use in ImageJ

Some great scientific data gets posted on Twitter. Sometimes I want to take a closer look and this post describes a strategy to do so.

Edit: I received a request to take down the 3D volume images derived from the example dataset I used in this post. I’ve edited the post below so that is now a general guide.

Grab the video

It can be a bit difficult to the grab video from Twitter. The best way I’ve found is using youtube-dl. This works for downloading video and audio from YouTube to view offline, but it also works for other embedded video content on other websites.

youtube-dl -o '%(title)s.%(ext)s' https://twitter.com/username/status/tweetID

this downloads an mp4 file which is automatically named.

Convert to avi

Now, mp4 is a compressed file format which cannot be read directly by FIJI/ImageJ. Conversion to avi means that the file can be loaded. I like to use another command line tool, ffmpeg for video conversions.

ffmpeg -i originalFile.mp4 -pix_fmt nv12 -f avi -vcodec rawvideo convertedFile.avi

Now we have an avi file called convertedFile.avi that we can use.

The avi can be loaded into FIJI. At this point you can analyse the video. However, in the case of the video I was interested in, the data had been pseudocolored and was now in RGB format. I wanted to look at the original data. Converting to grayscale does not give the correct representation but conversion back to grayscale is possible if you know the LUT was applied. Even if you don’t, it’s possible to take a guess at the LUT and do the conversion.

Converting RGB to original values

I found a nice gist that does the conversion for a single image. I just modified this code to work for a stack. It requires the LUT to be displayed vertically in a window called LUT. Caution: this code runs very slowly because every pixel in every slice needs to be recalculated and ImageJ is slow… I took a guess that mpl-inferno was used (I don’t think is exactly right but it worked well enough). You can display the built-in LUTs in FIJI using Color > Display LUTs… and from there you can make the LUT window which the macro uses for the calculation. The macro to convert stacks to grayscale using the LUT is here.

I had a nice grayscale version of the data (inverted because I wanted to look at the volume). This let me see how the layers in the original video add together to make the full structure. I used ClearVolume which can be installed via Update Site in FIJI. I just made a quick video to show it in action (see below). You’ll have to take my word for it (video removed).

So extracting scientific data from Twitter or another online source is pretty straightforward. The extra complication was getting rid of the pseudocoloring, but once this was done, something very close to the original data was available.  Nonetheless this workflow is a fun way to take a closer look at some of the cool movies that people post on Twitter. I hope you find it useful.

The post title comes from “Rip It Up” by Orange Juice. A popular title in my library with versions from several different artists. I was thinking what is described is similar to ripping video content.

## Ferrous: new paper on FerriTagging proteins in cells

We have a new paper out. It’s not exactly news, because the paper has been up on bioRxiv since December 2016 and hasn’t changed too much. All of the work was done by Nick Clarke when he was a PhD student in the lab. This post is to explain our new paper to a general audience.

The paper in a nutshell

We have invented a new way to tag proteins in living cells so that you can see them by light microscopy and by electron microscopy.

Why would you want to do that?

Proteins do almost all of the jobs in cells that scientists want to study. We can learn a lot about how proteins work by simply watching them down the microscope. We want to know their precise location. Light microscopy means that the cells are alive and we can watch the proteins move around. It’s a great method but it has low resolution, so seeing a protein’s precise location is not possible. We can overcome this limitation by using electron microscopy. This gives us higher resolution, but the proteins are stuck in one location. When we correlate images from one microscope to the other, we can watch proteins move and then look at them with high resolution. All we need is a way to see the proteins so that they can be seen in both types of microscope. We do this with tagging.

Tagging proteins so that we can see them by light microscopy is easy. A widely used method is to use a fluorescent protein such as GFP. We can’t see GFP in the electron microscope (EM) so we need another method. Again, there are several tags available but they all have drawbacks. They are not precise enough, or they don’t work on single proteins. So we came up with a new one and fused it with a fluorescent protein.

What is your EM tag?

We call it FerriTag. It is based on Ferritin which is a large protein shell that cells use to store iron. Because iron scatters electrons, this protein shell can be seen by EM as a particle. There was a problem though. If Ferritin is fused to a protein, we end up with a mush. So, we changed Ferritin so that it could be attached to the protein of interest by using a drug. This meant that we could put the FerriTag onto the protein we want to image in a few seconds. In the picture on the right you can see how this works to FerriTag clathrin, a component of vesicles in cells.

We can watch the tagging process happening in cells before looking by EM. The movie on the right shows green spots (clathrin-coated pits in a living cell) turning orange/yellow when we do FerriTagging. The cool thing about FerriTag is that it is genetically encoded. That means that we get the cell to make the tag itself and we don’t have to put it in from outside which would damage the cell.

What can you use FerriTag for?

Well, it can be used to tag many proteins in cells. We wanted to precisely localise a protein called HIP1R which links clathrin-coated pits to the cytoskeleton. We FerriTagged HIP1R and carried out what we call “contextual nanoscale mapping”. This is just a fancy way of saying that we could find the FerriTagged HIP1R and map where it is relative to the clathrin-coated pit. This allowed us to see that HIP1R is found at the pit and surrounding membrane. We could even see small changes in the shape of HIP1R in the different locations.

We’re using FerriTag for lots of projects. Our motivation to make FerriTag was so that we could look at proteins that are important for cell division and this is what we are doing now.

Is the work freely available?

Yes! The paper is available here under CC-BY licence. All of the code we wrote to analyse the data and run computer simulations is available here. All of the plasmids needed to do FerriTagging are available from Addgene (a non-profit company, there is a small fee) so that anyone can use them in the lab to FerriTag their favourite protein.

How long did it take to do this project?

Nick worked for four years on this project. Our first attempt at using ribosomes to tag proteins failed, but Nick then managed to get Ferritin working as a tag. This paper has broken our lab record for longest publication delay from first submission to final publication. The diagram below tells the whole saga.

The publication process was frustratingly slow. It took a few months to write the paper and then we submitted to the first journal after Christmas 2016. We got a rapid desk rejection and sent the paper to another journal and it went out for review. We had two positive referees and one negative one, but we felt we could address the comments and checked with the journal who said that they would consider a revised paper as an appeal. We did some work and resubmitted the paper. Almost six months after first submission the paper was rejected, but with the offer of a rapid (ha!) publication at Nature Communications using the peer review file from the other journal.

Hindsight is a wonderful thing but I now regret agreeing to transfer the paper to Nature Communications. It was far from rapid. They drafted in a new reviewer who came with a list of new questions, as well as being slow to respond. Sure, a huge chunk of the delay was caused by us doing revision experiments (the revisions took longer than they should because Nick defended his PhD, was working on other projects and also became a parent). However, the journal was really slow. The Editor assigned to our paper left the journal which didn’t help and the reviewer they drafted in was slow to respond each time (6 and 7 weeks, respectively). Particularly at the end, after the paper was ‘accepted in principle’ it took them three weeks to actually accept the paper (seemingly a week to figure out what a bib file is and another to ask us something about chi-squared tests). Then a further three weeks to send us the proofs, and then another three weeks until publication. You can see from the graphic that we sent back the paper in the third week of February and only incurred a 9-day delay ourselves, yet the paper was not published until July.

Did the paper improve as a result of this process? Yes and no. We actually added some things in the first revision cycle (for Journal #2) that got removed in subsequent peer review cycles! And the message in the final paper is exactly the same as the version on bioRxiv, posted 18 months previously. So in that sense, no it didn’t. It wasn’t all a total waste of time though, the extra reviewer convinced us to add some new analysis which made the paper more convincing in the end. Was this worth an 18-month delay? You can download our paper and the preprint and judge for yourself.

Were we unlucky with this slow experience? Maybe, but I know other authors who’ve had similar (and worse) experiences at this journal. As described in a previous post, the publication lag times are getting longer at Nature Communications. This suggests that our lengthy wait is not unique.

• It is open access.
• It has the Nature branding (which, like it or not, impresses many people).
• Peer review file is available
• The papers look great (in print and online).

But there are downsides too.

• The APC for each paper is £3300 ($5200). Obviously open access must cost something, but there a cheaper OA journals available (albeit without the Nature branding). • Ironically, paying a premium for this reputation is complicated since the journal covers a wide range of science and its kudos varies depending on subfield. • It’s also slow, and especially so when you consider that papers have often transferred here from somewhere else. • It’s essentially a mega journal, so your paper doesn’t get the same exposure as it would in a community-focused journal. • There’s the whole ReadCube/SpringerNature thing… Overall it was a negative publication experience with this paper. Transferring a paper along with the peer review file to another journal has worked out well for us recently and has been rapid, but not this time. Please leave a comment particularly if you’ve had a positive experience and redress the balance. The post title comes from “Ferrous” by Circle from their album Meronia. ## Pentagrammarspin: why twelve pentagons? This post has been in my drafts folder for a while. With the World Cup here, it’s time to post it! It’s a rule that a 3D assembly of hexagons must have at least twelve pentagons in order to be a closed polyhedral shape. This post takes a look at why this is true. First, some examples from nature. The stinkhorn fungus Clathrus ruber, has a largely hexagonal layout, with pentagons inserted. The core of HIV has to contain twelve pentagons (shown in red, in this image from the Briggs group) amongst many hexagonal units. My personal favourite, the clathrin cage, can assemble into many buckminsterfullerene-like shapes, but all must contain at least twelve pentagons with a variable number of hexagons. The case of clathrin is particularly interesting because clathrin triskelia can assemble into a flat hexagonal lattice on membranes. If clathrin is going to coat a vesicle, that means 12 pentagons need to be introduced. So there needs to be quite a bit of rearrangement in order to do this. You can see the same rule in everyday objects. The best example is a football, or soccer ball, if you are reading in the USA. The classic design of football has precisely twelve pentagons and twenty hexagonal panels. The roadsign for football stadia here in the UK shows a weirdly distorted hexagonal array that has no pentagons. 22,543 people signed a petition to pressurise the authorities to change it, but the Government responded that it was too costly to correct this geometrical error. So why do all of these assemblies have 12 pentagons? In the classic text “On Growth and Form” by D’Arcy Wentworth Thompson, polyhedral forms in nature are explored in some detail. In the wonderfully titled On Concretions, Specules etc. section, the author notes polyhedral forms in natural objects. One example is Dorataspis, shown left. The layout is identical to the D6 hexagonal barrel assembly of a clathrin cage shown above. There is a belt of six hexagons, one at the top, one at the bottom (eight total) and twelve pentagons between the hexagons. In the book, there is an explanation of the maths behind why there must be twelve pentagons in such assemblies, but it’s obfuscated in bizarre footnotes in latin. I’ll attempt to explain it below. To shed some light on this we need the help of Euler’s formulae. The surface of a polyhedron in 3D is composed of faces, edges and vertices. If we think back to the football the faces are the pentagons and hexgonal panels, the edges are the stitching where two panels meet and the vertices are where three edges come together. We can denote faces, edges and vertices as f, e and v, respectively. These are 2D, 1D and zero-dimensional objects, respectively. Euler’s formula which is true for all polyhedra is: $$f – e + v = 2$$ If you think about a cube, it has six faces. It has 12 edges and 8 vertices. So, 6 – 12 + 8 = 2. We can also check out a the football above. This has 32 faces (twelve pentagons, twenty hexagons), 90 edges and sixty vertices. 32 – 90 + 60 = 2. Feel free to check it with other polyhedra! Euler found a second formula which is true for polyhedra where three edges come together at a vertex. $$\sum (6-n)f_{n} = 12$$ in this formula, $$f_{n}$$ means number of n-gons. So let’s say we have dodecahedron, which is a polyhedron made of 12 pentagons. So $$n$$ = 5 and $$f_{n}$$ = 12, and you can see that $$(6-5)12 = 12$$. Let’s take a more complicated object, like the football. Now we have: $$((6-6)20) + ((6-5)12) = 12$$ You can now see why the twelve pentagons are needed. Because 6-6 = 0, we can add as many hexagons as we like, this will add nothing to the left hand side. As long as the twelve pentagons are there, we will have a polyhedron. Without them we don’t. This is the answer to why there must be twelve pentagons in a closed polyhedral assembly. So how did Euler get to the second equation? You might have spotted this yourself for the f, e, v values for the football. Did you notice that the ratio of edges to vertices is 3:2? This is because each edge has two vertices at either end (it is a 1D object) and remember we are dealing with polyhedra with three edges at each vertex. so $$v = \frac{2}{3}e$$. Also, each edge is at the boundary of two polygons. So $$e = \frac{1}{2}\sum n f_{n}$$. You can check that with the values for the cube or football above. We know that $$f = \sum f_{n}$$, this just means that the number of faces is the sum of all the faces of all n-gons. This means that: $$f – e + v = 2$$ Can be turned into $$f – (1/3)e = \sum n f_{n} – \frac{1}{6}\sum n f_{n} = 2$$ Let’s multiply by 6 to get, oh yes $$\sum (6-n)f_{n} = 12$$ There are some topics for further exploration here: • You can add 0, 2 or 10000 hexagons to 12 pentagons to make a polyhedron, but can you add just one? • What happens when you add a few heptagons into the array? Image credits (free-to-use/wiki or): Clathrus ruber – tineye search didn’t find source. HIV cores – Briggs Group Exploded football – Quora The post title comes from “Pentagrammarspin” by Steve Hillage from the 2006 remaster of his LP Fish Rising ## Rollercoaster III: yet more on Google Scholar In a previous post I made a little R script to crunch Google Scholar data for a given scientist. The graphics were done in base R and looked a bit ropey. I thought I’d give the code a spring clean – it’s available here. The script is called ggScholar.R (rather than gScholar.R). Feel free to run it and raise an issue or leave a comment if you have some ideas. I’m still learning how to get things looking how I want them using ggplot2, but this is an improvement on the base R version. As described earlier I have many Rollercoaster songs in my library. This time it’s the song and album by slowcore/dream pop outfit Red House Painters. ## Ten Years vs The Spread: Calculating publication lag times in R There have been several posts on this site about publication lag times. You can read them here. Lag times are the delays in the dissemination of scientific data introduced by the process of publishing the paper in a journal. Nowadays, your paper can be online in a few hours using a preprint server. However, this work is not peer reviewed. Journals organise a formal peer review and provide some sort of certification of the work. They typeset the work and all of this adds delays the dissemination of work in a journal. To look at publication delays, you can use PubMed data, which is incomplete but can give insight into how long these delays can be. Previous posts have involved the use of a ruby script to make a csv file from PubMed XML output and then use this in Igor to calculate the publication lag times. There is another method detailed in this excellent post by Daniel Himmelstein. I recently posted a figure for Nature Communications lag times on Twitter and was asked to generate others. I figured that I should write an R script and people can make their own! The PubMedLagR code is available here with instructions for use. A query for Nature Communications data at PubMed, such as: nat commun[ta] AND 2000 : 2018[pdat] AND journal article[pt] Retrieves all paper for this journal. The range from 2010 to 2018 is for illustration, this journal has only been in operation for these years. Filtering for journal articles rather and attempting to get rid of reviews and front matter is wise, but doesn’t always work. Again this journal doesn’t carry this material so this is for illustration. Getting your query right is very important. Save the results in XML format and then run the R script as directed. This should give a csv of the data and a png of the lag times. This is data from Nature Communications. Colleagues had two separate papers accepted at this journal and experienced long delays. I was interested to see if papers were generally taking longer to publish here. Of course we do not know why. Delays are partly the fault of the authors, the reviewers and the journal and it is not possible to say why publication lag times are increasing for this journal year-on-year. The journal has grown in terms of number of papers published, has this introduced inefficiencies? Are reviewers being slow to review? Are they being more demanding? Are Editors not marshalling the referee reports and providing clear guidance to authors? Allowing too much time and too many rounds of revision? Are authors being too slow to do further experimental work? The answer will be yes to some of these questions for some of the papers. This is not to focus on Nature Communications, it’s one of a few journals that many colleagues complain is too slow to publish their work. With this code you can have a look at the journal you are interested in submitting to and consider whether there is a more rapid venue for your work. Update: I changed the code slightly and prettified the plots just a little. Below are some plots for Nature Cell Biology, Nature Neuroscience. I also did a search for clathrin or CRISPR papers over the same time period. These keyword searches are fairly flat, whereas the journal-specific increase in publication lag time can be seen. The lag times at Nature Neuroscience look artificially low and then seem to have jumped up in 2016 to be something similar to Nature Cell Biology or Nature Communications. Edit I neglected to point out that the code truncates the y-axis in the bottom right plot to 1000 days or the maximum lag time, whichever is smaller. This is because it gets difficult to see the data points if there is an outlier, which might be due to an error in PubMed data. A reader commented on Twitter that some poor paper had a lag time almost 1000 days. Well, due to the y-axis truncation we don’t see that 9 papers in Nature Communications since 2010 have lag times (RecAcc) of > 1000 days. The record holder has a lag time of 1561 days! I checked that this was not a PubMed error by looking at the dates on the paper. Notes Date information is not available in PubMed for every paper unfortunately. This is especially true of older papers. The date information is supplied to PubMed from the journal. These dates are not necessarily accurate: 1) you can see occasional errors in the data, 2) journals sometimes “reset the clock” on papers and treat resubmissions as new submissions. The post title is taken from “10 Years vs The Spread” by Wing-Tipped Sloat from the LP Chewyfoot. Obviously the song has nothing to do with smoothed kernel density estimates of journal publication lag times, but the title was incredibly apt. ## Cloud Eleven: A cloud-based code sharing solution for IgorPro This post is something of a “how to” guide. The problem is how can you share code with a small team and keep it up-to-date? For ImageJ, the solution is simple. You can make an ImageJ update site and then push any updated code to the user when they startup ImageJ. For IgorPro, there is no equivalent. Typically I send ipf files to someone and they run the code, but I have to resend them whenever there’s an update. This can cause confusion over which is the latest version. I’ve tried a bunch of things such as versioning the code (this at least tells you if the person is running an out-of-date version). I also put the code up on GitHub and tell people to pull down the latest version, but again this doesn’t work well. The topic of how to share code comes up perennially on the Igor mailing list and on IgorExchange, so it’s clearly something that people struggle with. I’ve found the solutions offered to be a bit daunting. My solution is detailed here with some code to make it run. The details It is possible to use aliases (shortcuts on Windows) in the User’s WaveMetrics folders to point to external files. Items in the Igor Procedures directory get loaded when you start Igor. Items in User Procedures can get loaded optionally. These aliases sit in the Users Wavemetrics folder (the exact location depends on the Igor Version) and this means that the program itself can get updated without overwriting these files. So, if aliases are created here that point to a cloud-based repo of Igor Code it can be used to: 1. Optionally load code as the user needs it. Because the code sits in the cloud it can be updated and instantly used by everyone. 2. Force Igor to load a bit of code to make a little menu item so that the user can pick the code they want to load. To get this working, I made use of Ryotako’s excellent menu loader which was written for loading the “hidden” WaveMetrics procedures. I created a version like that one which makes a menu of our shared code in alphabetical order. I then made a version that allows the code to be grouped by purpose. People in my group told me they prefer this version. Code just needs to be organised in folders for it to work. The IgorDistro.ipf just needs to be placed in a folder called IP somewhere in a share that users have access to (unless people are contributing to code development, you can make the share read-only). In the same directory that IP sits in, place a folder called UP with all of your code organised into folders. Aliases need to be created that point Igor Procedures folder to IP and User Procedures to UP. That’s it! I’ve tested it on IP7 and IP8, on Windows and Mac, using a shared Dropbox as the cloud repo. Obviously, the correct IgorPro licences need to be in place to share the code with multiple users. The post title comes from the pseudonymous LP by Cloud Eleven. A great debut album. The track “Wish I” is worth the price of the record alone (assuming people still buy records). ## Rollercoaster II: more on Google Scholar citations I’ve previously written about Google Scholar. Its usefulness and its instability. I just read a post by Jon Tennant on how to harvest Google Scholar data in R and I thought I would use his code as the basis to generate some nice plots based on Google Scholar data. A script for R is below and can be found here. Graphics are base R but do the job. First of all I took it for a spin on my own data. The outputs are shown here: These were the most interesting plots that sprang to mind. First is a ranked citation plot which also shows y=x to find the Hirsch number. Second, was to look at total citations per year to all papers over time. Google Scholar shows the last few years of this plot in the profile page. Third, older papers accrue more citations, but how does this look for all papers? Finally, a prediction of what my H-index will do over time (no prizes for guessing that it will go up!). As Jon noted, the calculation comes from this paper. While that’s interesting, we need to get the data of a scholar with a huge number of papers and citations. Here is George Church. At the time of writing he has 763 papers with over 90,000 citations in total and a H-index of 147. Interestingly ~10% of his total citations come from a monster paper in PNAS with Wally Gilbert in the mid 80s on genome sequencing. Feel free to grab/fork this code and have a play yourself. If you have other ideas for plots or calculations, add a comment here or an issue at GitHub. if(!require(scholar)){ install.packages("scholar") } library(scholar) # Add Google Scholar ID of interest here ID <- "" # If you didn't add one to the script prompt user to add one if(ID == ""){ ID <- readline(prompt="Enter Scholar ID: ") } # Get the citation history citeByYear<-get_citation_history(ID) # Get profile information profile <- get_profile(ID) # Get publications and save as a csv pubs <- get_publications(ID) write.csv(pubs, file = "citations.csv") # Predict h-index hIndex <- predict_h_index(ID) # Now make some plots # Plot of total citations by year png(file = "citationsByYear.png") plot(citeByYear$year,citeByYear$cites, type="h", xlab="Year", ylab = "Total Cites") dev.off() # Plot of ranked paper by citation with h png(file = "citationsAndH.png") plot(pubs$cites, type="l",
xlab="Paper rank", ylab = "Citations per paper")
abline(0,1)
text(nrow(pubs),max(pubs$cites, na.rm = TRUE), profile$h_index)
dev.off()
# Plot of cites to paper by year
png(file = "citesByYear.png")
plot(pubs$year, pubs$cites,
xlab="Year", ylab = "Citations per paper")
dev.off()
# Plot of h-index prediction
thisYear <- as.integer(format(Sys.Date(), "%Y"))
png(file = "hPred.png")
plot(hIndex$years_ahead+thisYear,hIndex$h_index,
ylim = c(0, max(hIndex$h_index, na.rm = TRUE)), type = "h", xlab="Year", ylab = "H-index prediction") dev.off()  Note that my previous code used a python script to grab Google Scholar data. While that script worked well, the scholar package for R seems a lot more reliable. I have a surprising number of tracks in my library with Rollercoaster in the title. This time I will go with the Jesus & Mary Chain track from Honey’s Dead. ## Turn That Heartbeat Over Again: comparing wrist and chest-strap HRM As a geek, the added bonus of exercise is the fun that you can have with the data you’ve generated. A recent conversation on Twitter about the accuracy of wrist-based HRMs got me thinking… how does a wrist-based HRM compare with a traditional chest-strap HRM? Conventional wisdom says that the chest-strap is more accurate, but my own experience of chest-strap HRMs is that they are a bit unreliable. Time to put it to the test. I have a Garmin Fēnix 5 which records wrist-based HR and I have a Garmin chest-strap which uses ANT+ to transmit. I could pick up the ANT+ signal with a Garmin Edge 800 so that I could record both datasets simultaneously, on the same bike ride. Both the Fēnix and Edge can record GPS and Time (obviously) allowing accurate registration of the data. I also set both devices to receive cadence data via ANT+ from the same cadence/speed sensor so that I could control for (or at least look at) variability in recordings. I rode for a ~1 hr ~32 km to capture enough data. Obviously this is just one trial but the data gives a feel for the accuracy of the two HRMs. Biking, I figured was a fair activity since upper body and wrist movement is minimal, meaning that the contacts for both HRMs are more likely to stay in place than if I was running. I’ll get to heart rate last. First, you can see that the GPS recording is virtually identical between the two units – so that’s a good sign. Second, elevation is pretty similar too. There’s a bit of divergence at the beginning and end of the ride, since those parts are over the same stretch of road, neither device looks totally accurate. I’d be inclined to trust the Fēnix here since has a newer altimeter in it. Third, cadence looks accurate. Remember this data is coming off the same sensor and so any divergence is in how it’s being logged. Finally, heart rate. You can see that at the beginning of the ride, both wrist-based and chest-strap HRMs struggle. Obviously I have no reference here to know which trace is correct, but the chest-strap recording looks like it has an erroneous low reading for several minutes but is otherwise normal. The wrist-based HRM looks like it is reading 120ish bpm values from the start and then snaps into reading the right thing after a while. The chest-strap makes best contact when some perspiration has built up, which might explain its readings. The comparisons are shown below in grey. The correlation is OK but not great. Compared to cadence, the data diverge a lot more which rules out simple logging differences as a cause. I found a different story in Smart recording mode on the Fēnix. This is a lower frequency recording mode, which is recommended to preserve battery life for long activities. So what can we see here? Well, the data from the Fēnix are more patchy but even so, the data are pretty similar except for heart rate. The Fēnix performs badly here. Again, you can see the drop out of the chest strap HRM for a few minutes at the start, but otherwise it seems pretty reliable. The comparison graph for heart rate shows how poorly the wrist-based HRM measures heart rate, in this mode. OK, this is just two rides, for one person – not exactly conclusive but it gives some idea about the data that are captured with each HRM. Conclusions Wrist-based HRM is pretty good (at the higher sampling rate only) especially considering how the technology works, plus chest-strap HRMs can be uncomfortable to wear, so wrist-based HRM may be all you need. If you are training to heart rate zones, or want the best data, chest-strap HRM is more reliable than wrist-based HRM generally. Neither are very good for very short activities (<15 min). For nerds only Comparisons like these are quite easy to do in desktop packages like Rubitrack (which I love) or Ascent or others. They tend to mask things like missing data points, they smooth out the data and getting the plots the way you want is not straightforward. So, I took the original FIT files from each unit and used these for processing. There’s a great package for R called cycleRtools. This worked great except for the smart recording data which was sampled irregularly and it turns out and the package requires monotonic sampling. I generated a gpx file and parsed the data for this activity in R using XML. I found this snippet on the web (modified slightly). library(XML) library(plyr) filename <- "myfile.gpx" gpx.raw <- xmlTreeParse(filename, useInternalNodes = TRUE) rootNode <- xmlRoot(gpx.raw) gpx.rawlist <- xmlToList(rootNode)$trk
gpx.list <- unlist(gpx.rawlist[names(gpx.rawlist) == "trkseg"], recursive = FALSE)
gpx <- do.call(rbind.fill, lapply(gpx.list, function(x) as.data.frame(t(unlist(x)), stringsAsFactors=F)))
names(gpx) <- c("ele", "time", "temp", "hr", "cad", "lat", "lon")

Otherwise:

library(cycleRtools)
edge <- as.data.frame(read_fit(file = file.choose(), format = TRUE, CP = NULL, sRPE = NULL))
write.csv(edge, file = "edge.csv", row.names = F)

The resulting data frames could be saved out as csv and read into Igor to make the plots. I wrote a quick function in Igor to resample all datasets at 1 Hz. The plots and layout were generated by hand.

The post title comes from “Turn That Heartbeat Over Again” by Steely Dan from Can’t Buy A Thrill