<jupyter_start><jupyter_text>rock physics modelingAll rock physics models output dry-rock frame moduli:  $K_d$ (bulk modulus) and $\mu_d$ (shear modulus). These moduli represent the resistance of the rock's dry frame to normal and tangential stresses. They are used together with Gassmann's equation to calculate the saturated rock moduli ($K$ and $\mu$) which are, together with densities, the building blocks for the P-wave and S-wave velocities ($V_p$ and $V_s$):$$V_p = \sqrt{\frac{k+4/3\mu}{\rho}}$$$$V_s = \sqrt{\frac\mu{\rho}}$$The product of velocity by density is called impedance, and impedance contrasts are ultimately what generate seismic data; this is why rock physics, by linking rock and fluid properties to velocities, allows us to understand and explain seismic reflections.I will introduce here two simple but useful models, the Soft Sand and the Stiff Sand model.  Both models have the high porosity endpoint calculated via the Hertz-Mindlin theory, which is then connected to the zero porosity endpoint via respectively the lower or the upper Hashin-Shtrikman bounds. Details on Hertz-Mindlin, Hashin-Shtrikman and Gassmann's equations can be found in the referenced literature at the end of the notebook and will not be repeated here; the inputs however are worth spending a few more words on.Let's see the equation for the high porosity endpoint for both models, which is calculated via the Hertz-Mindlin's equation:$$ K_d = \frac{ P C_n^2 (1-\phi_c)^2 \mu_0^2} {18 \pi^2 (1-\sigma_0)^2}^{(1/3)} $$The input variables are therefore the effective pressure ($P$), the coordination number ($C_n$), i.e the average number of contacts that each grain has with surrounding grains, the critical porosity ($\phi_c$), i.e. the porosity of a siliciclastic sediment at initial deposition, and the mineral shear modulus $\mu_0$ and Poisson's ratio ($\sigma_0$).<!--Gassmann's equations are used to mix dry-rock and fluid moduli to output the saturated rock moduli:$$ K_s = K_d + \frac { (1-\frac{K_d}{K_0})^2} { \frac{\phi}{K_f} + \frac{1-\phi}{K_0} - \frac{K_d}{K_0^2}}$$$$\mu_s = \mu_d$$-->It is admittedly very confusing (and a bit intimidating) the distinction between dry-rock, saturated and mineral moduli, but it is however very important to make that distinction and understand the differences between them.In simple words, rocks are made of a mixture of minerals and fluids. All the mineral components have an inherent resistance to compressional and shear stresses, which we call bulk and shear mineral moduli ($K0$ and $\mu0$). The fluids offer a certain resistance to compressional stresses but not to shear stresses, and thus we only have bulk fluid moduli ($K_f$) to deal with.The dry-rock concept is a basic concept that is very often a source of confusion for those approaching the subject for the first time. It represents the overall structure of a rock, i.e., the way solid portions and empty spaces within a rock are arranged relative to each other; I think _architecture_ gives a better idea of the dry-rock frame concept.The differences between a 'soft' rock like the red friable sandstones that form the big arches in the USA's eponym national park and a 'stiff' rock like the limestones bounding the beautiful beaches with sheer cliffs along the southern Italian coast are not only due to their mineralogical components but also to their internal architecture.***I will define now the following functions:* `vrh`: to calculate average properties for mixture of 2 minerals or fluids* `hertzmindlin`: to calculate the high porosity endpoints* `softsand`: to calculate dry-rock moduli using the Soft Sand model* `stiffsand`: to calculate dry-rock moduli using the Stiff Sand model* `vels`: to calculate saturated moduli and velocities Let's set some starting parameters for minerals and fluids:* `RHO_qz`, `K_qz`, `MU_qz` are density, bulk and shear moduli for quartz* `RHO_sh`, `K_sh`, `MU_sh` are density, bulk and shear moduli for a generic shale mineral* `RHO_b`, `K_b`, `RHO_o`, `K_o`, `RHO_g`, `K_g` are density and bulk modulus for brine, oil and gasA few additional parameters required by the rock physics equations are:* `Cn` is the coordination number* `phic` is the critical porosity* `f` is the shear modulus correction factor (`f=1` for dry pack with perfect adhesion between particles and `f=0` for a dry frictionless pack)Finally, `phi` is a vector of porosity values which is the most important parameter for all these models. As a starting point, I will assume that the reservoir sands are 'clean' (i.e., entirely made of quartz) so the mineral moduli are the same as the quartz moduli; I will also calculate the velocities for both the Soft and the Stiff Sand models using brine as saturating fluid:<jupyter_code>K0, MU0, RHO0 = K_qz, MU_qz, RHO_qz

Kdry, MUdry = softsand(K0, MU0, phi, phic, Cn, P=45)
vp_ssm, vs_ssm, rho_ssm, _ = vels(Kdry, MUdry, K0, RHO0, K_b, RHO_b, phi)

Kdry, MUdry = stiffsand(K0, MU0, phi, phic, Cn, P=45)
vp_sti, vs_sti, rho_sti, _ = vels(Kdry, MUdry, K0, RHO0, K_b, RHO_b, phi)<jupyter_output><empty_output><jupyter_text>I will plot the same data as before (i.e., the reservoir sand from 2150m to 2200m) in the PHI-VP crossplot, superimposing the Soft Sand (continuous black line) and the Stiff Sand (dotted line) model lines:<jupyter_code>z1, z2, cutoff_sand, cutoff_shale = 2100, 2250, 0.3, 0.5

ss = (L.index >= z1) & (L.index <= z2) & (L.VSH <= cutoff_sand)
sh = (L.index >= z1) & (L.index <= z2) & (L.VSH >= cutoff_shale)

f, ax = plt.subplots(figsize=(5, 5))
ax.plot(L.PHIE[ss], L.VP[ss], **sty1)
ax.plot(phi, vp_ssm, '-k')
ax.plot(phi, vp_sti, ':k')
ax.set_xlim(0,0.4),  ax.set_ylim(2e3,4e3)
ax.set_xlabel('porosity PHIE')
ax.set_ylabel('velocity VP [m/s]')
ax.set_title('Soft Sand and Stiff Sand models')

#plt.savefig('/Users/matt/Dropbox/Agile/SEG/Tutorials/delMonte_Apr2017/Figure_2_part1.png', dpi=300)
plt.show()<jupyter_output><empty_output><jupyter_text>At a first sight, both models may offer a good starting point to investigate these sands. The sands in this section are not hydrocarbon-bearing so I can dismiss fluid effects and start leveraging the rock physics model by displaying how mineralogy affects the velocities. To do that, I will simplify the problem assuming variations in Net:Gross. When N:G is 1, then the mineral moduli will be equal to those of quartz, when N:G is lower than 1 than I will use composite mineral moduli given by the Voigt-Reuss-Hill average of quartz and a generic shale:$$K_{Voigt} = (V_{qz} \cdot K_{qz}) + (V_{sh} \cdot K_{sh}) $$$$K_{Reuss} = \frac{1} { (V_{qz} / K_{qz}) + (V_{sh} / K_{sh}) } $$$$K_{Hill} = \frac{K_{Voigt} + K_{Reuss} } {2}  $$In other words, if N:G=0.8 and the quartz and shale mineral moduli are respectively $K_{qz}=37$, $K_{sh}=15$ and $\mu_{qz}=44$ and $\mu_{sh}=5$:<jupyter_code>K_Voigt = 0.8*K_qz + 0.2*K_sh
K_Reuss = 1/ ( 0.8/K_qz + 0.2/K_sh )
K_Hill = (K_Voigt + K_Reuss) / 2

MU_Voigt = 0.8*MU_qz + 0.2*MU_sh
MU_Reuss = 1/ ( 0.8/MU_qz + 0.2/MU_sh )
MU_Hill = (MU_Voigt + MU_Reuss) / 2

print('K_VRH = {:.2f}, mu_VRH = {:.2f}'.format(K_Hill, MU_Hill))<jupyter_output>K_VRH = 30.60, mu_VRH = 26.69<jupyter_text>Density of the composite mineral are easier to calculate:$$ \rho = V_{qz} \cdot \rho_{qz} + V_{sh} \cdot \rho_{sh} $$therefore:<jupyter_code>rho = 0.8*RHO_qz + 0.2*RHO_sh

print('RHO = {:.2f}'.format(rho))<jupyter_output>RHO = 2.64<jupyter_text>Now let's put it all together and create show how the models change for different mineralogies:<jupyter_code>NG=np.linspace(0.6, 1.0, 5)

f, ax = plt.subplots(nrows=1, ncols=2, figsize=(12,5))

for i in NG:
    _,_,K0 = vrh(i,K_qz,K_sh)
    _,_,MU0 = vrh(i,MU_qz,MU_sh)    
    RHO0 = i*RHO_qz+(1-i)*RHO_sh
    Kdry, MUdry = softsand(K0, MU0, phi, phic=.5, Cn=12, P=45)
    vp_ssm,vs_ssm,rho_ssm,_= vels(Kdry,MUdry,K0,RHO0,K_b,RHO_b,phi)
    Kdry, MUdry = stiffsand(K0, MU0, phi, phic=.4, Cn=8, P=45)
    vp_sti,vs_sti,rho_sti,_= vels(Kdry,MUdry,K0,RHO0,K_b,RHO_b,phi)
    ax[0].plot(phi, vp_ssm, '-k', label='N:G={:.2f}'.format(i),alpha=i-.4)
    ax[1].plot(phi, vp_sti, '-k', label='N:G={:.2f}'.format(i),alpha=i-.4)

for aa in ax:
    aa.plot(L.PHIE[ss], L.VP[ss], **sty1, label='')
    aa.set_xlim(0, 0.4), aa.set_ylim(2e3, 4e3)
    aa.legend(loc='best')

ax[0].set_title('Soft Sand model')
ax[0].set_xlabel('porosity PHIE')

ax[1].set_title('Stiff Sand model')
ax[1].set_xlabel('porosity PHIE')

# plt.savefig('/Users/matt/Dropbox/Agile/SEG/Tutorials/delMonte_Apr2017/Figure_2_part2.png', dpi=300)
plt.show()<jupyter_output><empty_output><jupyter_text>To have the models spread out to cover the entire range of the well data, I had to code them with different parameters. In the code cell above, these are the lines that call the two models:    Kdry, MUdry = softsand(K0, MU0, phi, phic=.5, Cn=12, P=45)    Kdry, MUdry = stiffsand(K0, MU0, phi, phic=.4, Cn=8, P=45)The Soft Sand model uses higher critical porosity and coordination number than the Stiff Sand model, which means that the reservoir sands can be described by either a stiffer 'soft' sand or a 'softer' stiff sand (the coordination number `Cn` suggests a closer packing of the individual grains that make up our sand, which in turn means a more compact and harder material).If a more accurate petrophysical analysis was available, it would make sense to color-code the well data to the various mineralogical volumes and try also to deduce the mineral assemblage. In this case however the shale volume was created from the gamma ray log and within the reservoir sand it would give us very little insight into the actual mineralogy of the sand. Therefore it is up to the interpreter to decide if the spread of the rock physics models could help in determining the reason behind the scatter of the data, since as already pointed out it is not due to fluid variations.So far then, both models fit the datapoints. It is up to the interpreter to decide which model is more appropriate; this is an essential question and it has probably more to do with the expectations we have than other hard data. The behaviour of the model lines with decreasing varying porosity is particularly important; do we expect to have very abrupt increases in velocity for a single porosity unit increase like in the Stiff Sand model? Does this fit with the knowledge we have from nearby wells or formation analogues?<jupyter_code>phi_test = np.array([0.2,0.3])

Kdry, MUdry = softsand(K0, MU0, phi_test, phic=.5, Cn=12, P=45)
vp_ssm,_,_,_= vels(Kdry,MUdry,K0,RHO0,K_b,RHO_b,phi_test)

Kdry, MUdry = stiffsand(K0, MU0, phi_test, phic=.4, Cn=8, P=45)
vp_sti,_,_,_ = vels(Kdry,MUdry,K0,RHO0,K_b,RHO_b,phi_test)

print('Soft Sand RPM: phi={:.2f} --> Vp={:.0f} m/s'.format(phi_test[0],vp_ssm[0]))
print('Soft Sand RPM: phi={:.2f} --> Vp={:.0f} m/s'.format(phi_test[1],vp_ssm[1]))
print('Soft Sand RPM: increase in Vp after 10% porosity decrease={:.0%}'.format((vp_ssm[0]-vp_ssm[1])/vp_ssm[1]))

print('Stiff Sand RPM: phi={:.2f} --> Vp={:.0f} m/s'.format(phi_test[0],vp_sti[0]))
print('Stiff Sand RPM: phi={:.2f} --> Vp={:.0f} m/s'.format(phi_test[1],vp_sti[1]))
print('Stiff Sand RPM: increase in Vp after 10% porosity decrease={:.0%}'.format((vp_sti[0]-vp_sti[1])/vp_sti[1]))<jupyter_output>Soft Sand RPM: phi=0.20 --> Vp=3733 m/s
Soft Sand RPM: phi=0.30 --> Vp=3245 m/s
Soft Sand RPM: increase in Vp after 10% porosity decrease=15%
Stiff Sand RPM: phi=0.20 --> Vp=4320 m/s
Stiff Sand RPM: phi=0.30 --> Vp=3477 m/s
Stiff Sand RPM: increase in Vp after 10% porosity decrease=24%<jupyter_text>Is it reasonable to assume that velocities would increase so much (from 3477 to 4320 m/s) when the reservoir goes from good to only slighty less than good porosities? In the absence of a good geological background, an investigation on other wells that have penetrated similar lithologies would probably point us in the right direction.  rock physics templatesThe set of models for varying degrees of N:G shown above are a basic example of rock physics templates (RPTs). It is fairly easy to build from that and have a function to create RPTs which show not only variations in porosity and mineralogy but also fluid content.Avseth first introduced the concept of _rock physics templates_ (RPT) to display a reference framework of all the possible variations of a particular rock and use such templates to understand actual well log data (or seismic-derived elastic properties).In the code cell below, I have simply assembled the functions to compute $K_{dry}$ and $\mu_{dry}$ for the two models (Soft and Stiff Sand), the velocities using Gassmann's equation therefore giving the user to select which kind of fluid variations to analyse (from brine to oil or brine to gas), and return arrays of IP and VP/VS that we can overlay on top of well data. In addition to that, the function will also plot the actual RPTs with all the labels to make sense of it. Let's try the function `rpt` to show the templates for both Soft and Stiff Sand models in the IP/VPVS domain. The parameters passed to the function are those that I have previously selected in my initial assessment (but once we go from the PHI/VP to IP/VPVS domain it is likely that these parameters will be fine-tuned).<jupyter_code>ip_rpt1, vpvs_rpt1 = rpt(model='stiff',vsh=0.6,fluid='oil',phic=0.4,Cn=8,P=45,f=.3)
ip_rpt0, vpvs_rpt0 = rpt(model='soft',vsh=0.6,fluid='oil',phic=0.5,Cn=12,P=45,f=.3)<jupyter_output><empty_output><jupyter_text>Now let's plot them together with the well data:<jupyter_code># f, ax = plt.subplots(nrows=1, ncols=2, figsize=(12,5))
# ax[0].plot(ip_rpt0, vpvs_rpt0, 'sk', mew=0, alpha=0.5)
# ax[1].plot(ip_rpt1, vpvs_rpt1, 'sk', mew=0, alpha=0.5)
# for aa in ax:
#     aa.plot(L.VP[ss]*L.RHO[ss], L.VP[ss]/L.VS[ss], **sty1)
#     aa.set_xlim(2e3,10e3), aa.set_ylim(1.6,2.8)
# ax[0].set_title('Soft Sand RPM')
# ax[1].set_title('Stiff Sand RPM')

# ax[0].set_xlabel('IP')
# ax[0].set_ylabel('VP/VS')

# plt.savefig('/Users/matt/Dropbox/Agile/SEG/Tutorials/delMonte_Apr2017/Figure_3_part2.png', dpi=300)
# plt.show()
f, ax = plt.subplots(nrows=1, ncols=1, figsize=(7,7))
ax.plot(ip_rpt0, vpvs_rpt0, 'sk', mew=0, alpha=0.5)
ax.plot(L.VP[ss]*L.RHOB[ss], L.VP[ss]/L.VS[ss], **sty1)
ax.set_xlim(2e3,11e3)
ax.set_ylim(1.6,2.8)

ax.set_xlabel('IP')
ax.set_ylabel('VP/VS')

# plt.savefig('/Users/matt/Dropbox/Agile/SEG/Tutorials/delMonte_Apr2017/Figure_3_part2.png', dpi=300)
plt.show()<jupyter_output><empty_output><jupyter_text>By choosing a full elastic domain to display the data, the Soft Sand RPM starts to make more sense, as it shows more gradual variations when porosity or fluid changes, in tune with the experimental data.An additional parameter that I had to set to fit the well data is the shear modulus correction factor `f` which most of the times becomes a pure fitting parameter, as it has very little correlation with any other piece of information that is usually available in exploration geophysics.***This game can be played forever, for example one can check the validity of the elastic moduli assigned to the second mineral (the one I have referred to as "shale") by computing and displaying different RPTs (in the plot below, the RPT for a 'clean' sand is in black, and red is the RPT for a shaly sand):<jupyter_code># Original parameters.
RHO_sh=2.8;   K_sh=15;  MU_sh=5

ip_rpt0a, vpvs_rpt0a = rpt(model='soft',vsh=0.0,fluid='oil',phic=0.5,Cn=12,P=45,f=.3,display=False)
ip_rpt0b, vpvs_rpt0b = rpt(model='soft',vsh=0.6,fluid='oil',phic=0.5,Cn=12,P=45,f=.3,display=False)

f, ax = plt.subplots(figsize=(7,7))
ax.plot(ip_rpt0a, vpvs_rpt0a, 'sk', mew=0, alpha=0.5)
ax.plot(ip_rpt0b, vpvs_rpt0b, 'sr', mew=0, alpha=0.5)
ax.plot(L.VP[ss]*L.RHOB[ss], L.VP[ss]/L.VS[ss], **sty1)
ax.set_xlim(2e3,11e3)
ax.set_ylim(1.6,2.8)

# plt.savefig('/Users/matt/Dropbox/Agile/SEG/Tutorials/delMonte_Apr2017/Figure_3_part2.png', dpi=300)
# plt.show()<jupyter_output><empty_output><jupyter_text>If I change the "shale" elastic moduli to something different, the RPTs will change too. Once again if the fit is better, and in the absence of other information, that is a perfectly reasonable and valuable knowledge to add to the 'exploration' puzzle.<jupyter_code># New parameters.
RHO_sh=2.8;   K_sh=21;  MU_sh=3

ip_rpt0a, vpvs_rpt0a = rpt(model='soft',vsh=0.0,fluid='oil',phic=0.5,Cn=12,P=45,f=.3,display=False)
ip_rpt0b, vpvs_rpt0b = rpt(model='soft',vsh=0.6,fluid='oil',phic=0.5,Cn=12,P=45,f=.3,display=False)

f, ax = plt.subplots(figsize=(7,7))
#ax.plot(ip_rpt0a, vpvs_rpt0a, 'sk', mew=0, alpha=0.5)
ax.plot(ip_rpt0b, vpvs_rpt0b, 'sb', mew=0, alpha=0.5)
ax.plot(L.VP[ss]*L.RHOB[ss], L.VP[ss]/L.VS[ss], **sty1)
ax.set_xlim(2e3,11e3), ax.set_ylim(1.6,2.8)

ax.set_xlabel('IP')
ax.set_ylabel('VP/VS')

# plt.savefig('/Users/matt/Dropbox/Agile/SEG/Tutorials/delMonte_Apr2017/Figure_3_part3.png', dpi=300)
plt.show()<jupyter_output><empty_output><jupyter_text>seismic modelingOnce I have a good grasp of the RPM, its adaptability to the situation under analysis, the way it reacts to different input parameters, I can start using it also to explore seismic data.It is very easy to use the velocities and densities output by the function `vels` introduced earlier to build simple two-layer models and analyse seismic and AVO signatures of the modeled top reservoir. Let's start from the base scenario, i.e. the one observed on the real well. Average elastic properties from two fairly regular intervals above and below top reservoir can be extracted in this way:<jupyter_code>top=3375
z0=top-40
z1=top
z2=top+40
z=L.index
ss = (z>=z1) & (z<=z2)
sh = (z>=z0) & (z<=z1)

vp0, vs0, rho0 = L[['VP','VS','RHOB']][sh].mean().values
vp1, vs1, rho1 = L[['VP','VS','RHOB']][ss].mean().values
samples_sh=np.isfinite(L.index[sh]).size
samples_ss=np.isfinite(L.index[ss]).size

print('({:>4.0f}-{:<4.0f}m,{:3d} samples) Vp={:.0f}, Vs={:.0f}, rho={:.2f}, Ip={:.0f}, Vp/Vs={:.2f} '.format(z0,z1,samples_sh,vp0,vs0,rho0,vp0*rho0,vp0/vs0))
print('({:>4.0f}-{:<4.0f}m,{:3d} samples) Vp={:.0f}, Vs={:.0f}, rho={:.2f}, Ip={:.0f}, Vp/Vs={:.2f} '.format(z1,z2,samples_ss,vp1,vs1,rho1,vp1*rho1,vp1/vs1))<jupyter_output>(3335-3375m, 41 samples) Vp=3729, Vs=1982, rho=2.62, Ip=9765, Vp/Vs=1.88 
(3375-3415m, 41 samples) Vp=3914, Vs=2042, rho=2.67, Ip=10438, Vp/Vs=1.92<jupyter_text>Then I will use `twolayer` to display seismic signatures at Near and Far offset traces and AVO curve:<jupyter_code>twolayer(vp0, vs0, rho0, vp1, vs1, rho1)<jupyter_output>C:\Users\tkngu\Dropbox\Work\RockPhysics\QSI\Quantitative_Seismic_Interpretation\bruges\filters\wavelets.py:204: FutureWarning: In future releases, return_t will be True by default.
  warnings.warn("In future releases, return_t will be True by default.", FutureWarning)<jupyter_text>Using the RPM calibrated at the well, I can investigate different scenarios, e.g. by choosing a different fluid type:<jupyter_code>RHO_qz=2.65;   K_qz=37;  MU_qz=15
RHO_sh=2.8;   K_sh=15;  MU_sh=5

phi,nn=.15,.9
_,_,K0 = vrh(nn,K_qz,K_sh)
_,_,MU0 = vrh(nn,MU_qz,MU_sh)    
RHO0 = nn*RHO_qz+(1-nn)*RHO_sh

Kdry, MUdry = softsand(K0, MU0, phi, phic=.5, Cn=12, P=45,f=.3)
vp_rpm,vs_rpm,rho_rpm,_= vels(Kdry,MUdry,K0,RHO0,K_g,RHO_g,phi)

twolayer(vp0, vs0, rho0, vp_rpm, vs_rpm, rho_rpm)
#plt.title('GAS case, phi=0.15')

# plt.savefig('/Users/matt/Dropbox/Agile/SEG/Tutorials/delMonte_Apr2017/Figure_4.png', dpi=300)
plt.show()<jupyter_output>C:\Users\tkngu\Dropbox\Work\RockPhysics\QSI\Quantitative_Seismic_Interpretation\bruges\filters\wavelets.py:204: FutureWarning: In future releases, return_t will be True by default.
  warnings.warn("In future releases, return_t will be True by default.", FutureWarning)<jupyter_text>Or increase the porosity:<jupyter_code>phi,nn=.25,.9
_,_,K0 = vrh(nn,K_qz,K_sh)
_,_,MU0 = vrh(nn,MU_qz,MU_sh)    
RHO0 = nn*RHO_qz+(1-nn)*RHO_sh

Kdry, MUdry = softsand(K0, MU0, phi, phic=.5, Cn=12, P=45,f=.3)
vp_rpm,vs_rpm,rho_rpm,_= vels(Kdry,MUdry,K0,RHO0,K_g,RHO_g,phi)

twolayer(vp0,vs0,rho0,vp_rpm,vs_rpm,rho_rpm)
plt.title('GAS case, phi=0.25')<jupyter_output>C:\Users\tkngu\Dropbox\Work\RockPhysics\QSI\Quantitative_Seismic_Interpretation\bruges\filters\wavelets.py:204: FutureWarning: In future releases, return_t will be True by default.
  warnings.warn("In future releases, return_t will be True by default.", FutureWarning)
{'fraction_non_alphanumeric': 0.12630593337275775, 'fraction_numerical': 0.03479203627045141, 'mean_word_length': 5.302173913043478, 'pattern_counts': {'":': 0, '<': 58, '<?xml version=': 0, '>': 66, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '14', 'dir': 'jupyter-structured-clean-dedup', 'id': '308972', 'license': 'MIT', 'n_tokens_mistral': 8058, 'n_tokens_neox': 7433, 'n_words': 2419, 'path': '03_Seismic_Rock_Physics.ipynb', 'repo_name': 'ABDunbar/Quantitative_Seismic_Interpretation', 'size': '20292'}