<?xml version="1.0" encoding="UTF-8"?>
<rss  xmlns:atom="http://www.w3.org/2005/Atom" 
      xmlns:media="http://search.yahoo.com/mrss/" 
      xmlns:content="http://purl.org/rss/1.0/modules/content/" 
      xmlns:dc="http://purl.org/dc/elements/1.1/" 
      version="2.0">
<channel>
<title>Ricardo Avila</title>
<link>https://ravila.dev/blog.html</link>
<atom:link href="https://ravila.dev/blog.xml" rel="self" type="application/rss+xml"/>
<description>Ricardo Avila&#39;s website</description>
<generator>quarto-1.8.27</generator>
<lastBuildDate>Sun, 18 Jan 2026 00:00:00 GMT</lastBuildDate>
<item>
  <title>Extracting Room Boundaries from 3D Scans</title>
  <link>https://ravila.dev/posts/2026-01-18-room-shell-extraction/</link>
  <description><![CDATA[ 






<p>This week I’ve been working on extracting room boundaries from 3D mesh scans. It is a bit of an ADHD-fueled rabbit hole, but long story short, we moved to a new apartment, and I was wondering if I could use 3D virtual modeling to plan how we are going to lay out our furniture. There’s apps out there that scan rooms pretty accurately using LIDAR + ARKit on iPhones (e.g.&nbsp;Apple’s <a href="https://developer.apple.com/augmented-reality/roomplan/">RoomPlan API</a>), but I don’t have an iPhone with Lidar, and I wasn’t too happy with any of the apps.</p>
<p>The goal: take a noisy point cloud from an iPhone photogrammetry scan (I used the Polycam app with a free trial and exported an OBJ file) and produce a clean polygon representing the room’s floor plan.</p>
<section id="the-problem" class="level2">
<h2 class="anchored" data-anchor-id="the-problem">The Problem</h2>
<p>Given a 3D mesh of a room, I need to:</p>
<ol type="1">
<li>Detect the walls, floor, and ceiling</li>
<li>Extract the room’s 2D boundary polygon</li>
<li>Handle real-world messiness: furniture, alcoves, doorways, windows, mirrors, and other scanning artifacts that cause noise and holes in the mesh.</li>
</ol>
<section id="key-terms" class="level3">
<h3 class="anchored" data-anchor-id="key-terms">Key Terms</h3>
<p>Before diving in, some definitions for readers unfamiliar with computational geometry:</p>
<ul>
<li><strong>Point cloud</strong>: A set of 3D points (x, y, z) representing surfaces scanned by a sensor</li>
<li><strong>Normal vector</strong>: A unit vector perpendicular to a surface, indicating which way it “faces”</li>
<li><strong>Inliers/Outliers</strong>: Points that do/don’t fit a proposed model (e.g., points on vs.&nbsp;off a plane)</li>
<li><strong>Convex hull</strong>: The smallest convex shape containing all points - imagine stretching a rubber band around pins</li>
<li><strong>CCW (Counter-Clockwise) ordering</strong>: When creating a convex hull, the convention is that vertices are listed so that walking along edges keeps the interior on your left</li>
</ul>
<p>Here’s what the raw data looks like - a point cloud colored by height:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="images/raw_scan_topdown.png" class="lightbox" data-gallery="quarto-lightbox-gallery-1" title="Raw 3D scan top-down view"><img src="https://ravila.dev/posts/2026-01-18-room-shell-extraction/images/raw_scan_topdown.png" class="img-fluid figure-img" data-fig-cap="Raw point cloud from a photogrammetry scan of my living room. Yellow/green points are ceiling height, purple points are floor level. The room shape is visible, but extracting a clean boundary is non-trivial. Density from the incompletely scanned hallway and windows makes it more complex, and I find that it may be better to remove that density manually before running the algorithm." alt="Raw 3D scan top-down view"></a></p>
<figcaption>Raw 3D scan top-down view</figcaption>
</figure>
</div>
</section>
</section>
<section id="approach-multi-plane-ransac" class="level2">
<h2 class="anchored" data-anchor-id="approach-multi-plane-ransac">Approach: Multi-Plane RANSAC</h2>
<p>The foundational algorithm for this task is <strong>RANSAC</strong> (Random Sample Consensus) <span class="citation" data-cites="fischler1981">(Fischler and Bolles 1981)</span>. It is essentially a kind of Monte-Carlo algorithm that repeatedly samples minimal subsets of the data and keeps the model that explains the most data.</p>
<section id="standard-ransac-for-plane-detection" class="level3">
<h3 class="anchored" data-anchor-id="standard-ransac-for-plane-detection">Standard RANSAC for Plane Detection</h3>
<p>For plane detection, the algorithm works as follows:</p>
<ol type="1">
<li><strong>Sample</strong>: Pick 3 random points - the minimum needed to define a plane</li>
<li><strong>Hypothesize</strong>: Fit a plane through these 3 points using the equation <img src="https://latex.codecogs.com/png.latex?ax%20+%20by%20+%20cz%20+%20d%20=%200"></li>
<li><strong>Score</strong>: Count inliers - points within distance threshold <img src="https://latex.codecogs.com/png.latex?%5Cvarepsilon"> of the plane</li>
<li><strong>Iterate</strong>: Repeat N times, keep the plane with most inliers</li>
<li><strong>Refine</strong>: Refit the plane using all inliers (not just the 3 samples)</li>
<li><strong>Remove &amp; repeat</strong>: Delete inliers from point cloud, find next plane</li>
</ol>
<p>Here’s the core RANSAC implementation:</p>
<div id="ransac-core" class="cell" data-execution_count="1">
<details class="code-fold">
<summary>Show code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-1" style="background: #f1f3f5;"><pre class="sourceCode python code-annotation-code code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="annotated-cell-1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> dataclasses <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> dataclass</span>
<span id="annotated-cell-1-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> typing <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Optional</span>
<span id="annotated-cell-1-4"></span>
<span id="annotated-cell-1-5"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@dataclass</span></span>
<span id="annotated-cell-1-6"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> DetectedPlane:</span>
<span id="annotated-cell-1-7">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""A plane detected via RANSAC."""</span></span>
<span id="annotated-cell-1-8">    normal: np.ndarray      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Unit normal vector (3,)</span></span>
<span id="annotated-cell-1-9">    point: np.ndarray       <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Point on plane (3,)</span></span>
<span id="annotated-cell-1-10">    inlier_indices: np.ndarray</span>
<span id="annotated-cell-1-11">    inlier_count: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span></span>
<span id="annotated-cell-1-12"></span>
<span id="annotated-cell-1-13">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@property</span></span>
<span id="annotated-cell-1-14">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> d(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>:</span>
<span id="annotated-cell-1-15">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Plane equation: n·x + d = 0, so d = -n·point."""</span></span>
<span id="annotated-cell-1-16">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>np.dot(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.normal, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.point)</span>
<span id="annotated-cell-1-17"></span>
<span id="annotated-cell-1-18"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> ransac_plane(</span>
<span id="annotated-cell-1-19">    points: np.ndarray,</span>
<span id="annotated-cell-1-20">    threshold: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.02</span>,</span>
<span id="annotated-cell-1-21">    iterations: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">200</span>,</span>
<span id="annotated-cell-1-22">    min_inliers: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span></span>
<span id="annotated-cell-1-23">) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> Optional[DetectedPlane]:</span>
<span id="annotated-cell-1-24">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="annotated-cell-1-25"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Single-plane RANSAC with least-squares refinement.</span></span>
<span id="annotated-cell-1-26"></span>
<span id="annotated-cell-1-27"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Args:</span></span>
<span id="annotated-cell-1-28"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        points: (N, 3) point cloud.</span></span>
<span id="annotated-cell-1-29"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        threshold: Distance threshold for inliers (meters).</span></span>
<span id="annotated-cell-1-30"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        iterations: Number of RANSAC iterations.</span></span>
<span id="annotated-cell-1-31"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        min_inliers: Minimum inliers for a valid plane.</span></span>
<span id="annotated-cell-1-32"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="annotated-cell-1-33">    n_points <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(points)</span>
<span id="annotated-cell-1-34">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n_points <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>:</span>
<span id="annotated-cell-1-35">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span></span>
<span id="annotated-cell-1-36"></span>
<span id="annotated-cell-1-37">    best_inlier_count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="annotated-cell-1-38">    best_inlier_mask <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span></span>
<span id="annotated-cell-1-39">    best_normal <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span></span>
<span id="annotated-cell-1-40">    best_point <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span></span>
<span id="annotated-cell-1-41"></span>
<span id="annotated-cell-1-42">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(iterations):</span>
<span id="annotated-cell-1-43">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Sample 3 random points</span></span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-1" data-target-annotation="1">1</button><span id="annotated-cell-1-44" class="code-annotation-target">        idx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.random.choice(n_points, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, replace<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="annotated-cell-1-45">        p1, p2, p3 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> points[idx]</span>
<span id="annotated-cell-1-46"></span>
<span id="annotated-cell-1-47">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Compute normal via cross product</span></span>
<span id="annotated-cell-1-48">        v1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> p2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> p1</span>
<span id="annotated-cell-1-49">        v2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> p3 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> p1</span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-1" data-target-annotation="2">2</button><span id="annotated-cell-1-50" class="code-annotation-target">        normal <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.cross(v1, v2)</span>
<span id="annotated-cell-1-51">        norm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.linalg.norm(normal)</span>
<span id="annotated-cell-1-52">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> norm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-8</span>:  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Collinear points</span></span>
<span id="annotated-cell-1-53">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">continue</span></span>
<span id="annotated-cell-1-54">        normal <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/=</span> norm</span>
<span id="annotated-cell-1-55"></span>
<span id="annotated-cell-1-56">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Compute distances to plane</span></span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-1" data-target-annotation="3">3</button><span id="annotated-cell-1-57" class="code-annotation-target">        dists <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">abs</span>(np.dot(points <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> p1, normal))</span>
<span id="annotated-cell-1-58">        inlier_mask <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dists <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> threshold</span>
<span id="annotated-cell-1-59">        count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.count_nonzero(inlier_mask)</span>
<span id="annotated-cell-1-60"></span>
<span id="annotated-cell-1-61">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> best_inlier_count:</span>
<span id="annotated-cell-1-62">            best_inlier_count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> count</span>
<span id="annotated-cell-1-63">            best_inlier_mask <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> inlier_mask</span>
<span id="annotated-cell-1-64">            best_normal <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> normal</span>
<span id="annotated-cell-1-65">            best_point <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> p1</span>
<span id="annotated-cell-1-66"></span>
<span id="annotated-cell-1-67">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> best_inlier_count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> min_inliers:</span>
<span id="annotated-cell-1-68">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span></span>
<span id="annotated-cell-1-69"></span>
<span id="annotated-cell-1-70">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Refine with least-squares on inliers</span></span>
<span id="annotated-cell-1-71">    inlier_points <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> points[best_inlier_mask]</span>
<span id="annotated-cell-1-72">    centroid <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.mean(inlier_points, axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="annotated-cell-1-73">    centered <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> inlier_points <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> centroid</span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-1" data-target-annotation="4">4</button><span id="annotated-cell-1-74" class="code-annotation-target">    _, _, vh <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.linalg.svd(centered)</span>
<span id="annotated-cell-1-75">    refined_normal <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> vh[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="annotated-cell-1-76"></span>
<span id="annotated-cell-1-77">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> DetectedPlane(</span>
<span id="annotated-cell-1-78">        normal<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>refined_normal <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> np.linalg.norm(refined_normal),</span>
<span id="annotated-cell-1-79">        point<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>centroid,</span>
<span id="annotated-cell-1-80">        inlier_indices<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>np.where(best_inlier_mask)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>],</span>
<span id="annotated-cell-1-81">        inlier_count<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>best_inlier_count</span>
<span id="annotated-cell-1-82">    )</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-hidden code-annotation-container-grid">
<dt data-target-cell="annotated-cell-1" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-1" data-code-lines="44" data-code-annotation="1">The minimum number of points to define a plane in 3D</span>
</dd>
<dt data-target-cell="annotated-cell-1" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-1" data-code-lines="50" data-code-annotation="2">Cross product gives the normal perpendicular to both edge vectors</span>
</dd>
<dt data-target-cell="annotated-cell-1" data-target-annotation="3">3</dt>
<dd>
<span data-code-cell="annotated-cell-1" data-code-lines="57" data-code-annotation="3">Signed distance: <img src="https://latex.codecogs.com/png.latex?d%20=%20%7C(p%20-%20p_0)%20%5Ccdot%20%5Cmathbf%7Bn%7D%7C"></span>
</dd>
<dt data-target-cell="annotated-cell-1" data-target-annotation="4">4</dt>
<dd>
<span data-code-cell="annotated-cell-1" data-code-lines="74" data-code-annotation="4">SVD gives the best-fit plane normal as the last row of <img src="https://latex.codecogs.com/png.latex?V%5ET"></span>
</dd>
</dl>
</div>
</div>
<p>The distance formula measures the <strong>perpendicular</strong> distance from a point to the plane:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="images/tikz/point-to-plane-distance.png" class="lightbox" data-gallery="quarto-lightbox-gallery-2" title="Point-to-plane distance geometry"><img src="https://ravila.dev/posts/2026-01-18-room-shell-extraction/images/tikz/point-to-plane-distance.png" class="img-fluid figure-img" data-fig-cap="The vector $\mathbf{n} = (a, b, c)$ is the plane's unit normal. The distance from point $P$ to the plane is the projection of $(P - P_0)$ onto $\mathbf{n}$." alt="Point-to-plane distance geometry"></a></p>
<figcaption>Point-to-plane distance geometry</figcaption>
</figure>
</div>
</section>
<section id="how-many-iterations" class="level3">
<h3 class="anchored" data-anchor-id="how-many-iterations">How Many Iterations?</h3>
<p>The number of iterations N needed depends on the inlier ratio. If fraction <img src="https://latex.codecogs.com/png.latex?w"> of points are inliers, the probability of picking 3 good points is <img src="https://latex.codecogs.com/png.latex?w%5E3">. To achieve 99% confidence:</p>
<p><img src="https://latex.codecogs.com/png.latex?N%20=%20%5Cfrac%7B%5Clog(1%20-%200.99)%7D%7B%5Clog(1%20-%20w%5E3)%7D"></p>
<div id="ransac-iterations" class="cell" data-execution_count="2">
<details class="code-fold">
<summary>Show code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="cb1-2"></span>
<span id="cb1-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> ransac_iterations_needed(inlier_ratio: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>, confidence: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.99</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>:</span>
<span id="cb1-4">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Calculate iterations needed for given inlier ratio and confidence."""</span></span>
<span id="cb1-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(np.ceil(np.log(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> confidence) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> np.log(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> inlier_ratio<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)))</span>
<span id="cb1-6"></span>
<span id="cb1-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># For different inlier ratios</span></span>
<span id="cb1-8"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> w <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>]:</span>
<span id="cb1-9">    n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ransac_iterations_needed(w)</span>
<span id="cb1-10">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"w = </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>w<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.0%}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>n<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:,}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> iterations needed"</span>)</span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>w = 50%: 35 iterations needed
w = 30%: 169 iterations needed
w = 10%: 4,603 iterations needed</code></pre>
</div>
</div>
<p>The algorithm is not particularly fast, and it is not traditionally parallelizable. A simple room has six walls, but this algorithm detects one plane at a time, removes the inliers, and then repeats.</p>
</section>
<section id="the-spurious-plane-problem" class="level3">
<h3 class="anchored" data-anchor-id="the-spurious-plane-problem">The Spurious Plane Problem</h3>
<p>Another fundamental flaw is <strong>spurious planes</strong>. When your 3 random points come from <em>different</em> surfaces, you can get phantom planes that don’t correspond to any real physical surface.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="images/ransac-spurious-plane.png" class="lightbox" data-gallery="quarto-lightbox-gallery-3" title="The spurious plane problem"><img src="https://ravila.dev/posts/2026-01-18-room-shell-extraction/images/ransac-spurious-plane.png" class="img-fluid figure-img" data-fig-cap="Left: sampling 3 points from the same wall yields a valid plane. Right: sampling from wall AND floor yields a diagonal phantom plane that doesn't exist." alt="The spurious plane problem"></a></p>
<figcaption>The spurious plane problem</figcaption>
</figure>
</div>
</section>
</section>
<section id="ndt-ransac-eliminating-spurious-planes" class="level2">
<h2 class="anchored" data-anchor-id="ndt-ransac-eliminating-spurious-planes">NDT-RANSAC: Eliminating Spurious Planes</h2>
<p>I implemented NDT-RANSAC based on Li et al. <span class="citation" data-cites="li2017">(Li et al. 2017)</span>.</p>
<p><strong>NDT (Normal Distribution Transformation)</strong> fixes the spurious planes problem by pre-classifying regions of space into planar and non-planar cells. Instead of sampling 3 random points, we sample from locally planar regions.</p>
<section id="step-1-classify-cells-by-shape-using-ndt" class="level3">
<h3 class="anchored" data-anchor-id="step-1-classify-cells-by-shape-using-ndt">Step 1: Classify Cells by Shape using NDT</h3>
<p>The algorithm voxelizes space and computes statistics for each cell:</p>
<div id="ndt-cell" class="cell" data-execution_count="3">
<details class="code-fold">
<summary>Show code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-3" style="background: #f1f3f5;"><pre class="sourceCode python code-annotation-code code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-3-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@dataclass</span></span>
<span id="annotated-cell-3-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> NDTCell:</span>
<span id="annotated-cell-3-3">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="annotated-cell-3-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    A cell in the Normal Distribution Transform grid.</span></span>
<span id="annotated-cell-3-5"></span>
<span id="annotated-cell-3-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Eigenvalue shape classification (sorted λ₁ ≤ λ₂ ≤ λ₃):</span></span>
<span id="annotated-cell-3-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    - Planar: λ₁ &lt;&lt; λ₂ ≈ λ₃ (λ₁/λ₂ ≤ threshold) → flat surface</span></span>
<span id="annotated-cell-3-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    - Linear: λ₁ ≈ λ₂ &lt;&lt; λ₃ (λ₂/λ₃ ≤ threshold) → edge/line</span></span>
<span id="annotated-cell-3-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    - Spherical: λ₁ ≈ λ₂ ≈ λ₃ → noise or point feature</span></span>
<span id="annotated-cell-3-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="annotated-cell-3-11">    indices: np.ndarray       <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Point indices belonging to this cell</span></span>
<span id="annotated-cell-3-12">    centroid: np.ndarray      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Mean position (3,)</span></span>
<span id="annotated-cell-3-13">    normal: np.ndarray        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Eigenvector of smallest eigenvalue</span></span>
<span id="annotated-cell-3-14">    eigenvalues: np.ndarray   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Sorted: λ₁ ≤ λ₂ ≤ λ₃</span></span>
<span id="annotated-cell-3-15">    is_planar: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span>           <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># True if λ₁/λ₂ ≤ planarity_threshold</span></span>
<span id="annotated-cell-3-16">    is_linear: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># True if λ₂/λ₃ ≤ linearity_threshold</span></span>
<span id="annotated-cell-3-17"></span>
<span id="annotated-cell-3-18"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> compute_cell_features(points: np.ndarray) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>:</span>
<span id="annotated-cell-3-19">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Compute NDT features for a group of points."""</span></span>
<span id="annotated-cell-3-20">    centroid <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.mean(points, axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="annotated-cell-3-21">    centered <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> points <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> centroid</span>
<span id="annotated-cell-3-22"></span>
<span id="annotated-cell-3-23">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Covariance matrix</span></span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-3" data-target-annotation="1">1</button><span id="annotated-cell-3-24" class="code-annotation-target">    cov <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.dot(centered.T, centered) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(points)</span>
<span id="annotated-cell-3-25"></span>
<span id="annotated-cell-3-26">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Eigendecomposition (returns sorted ascending)</span></span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-3" data-target-annotation="2">2</button><span id="annotated-cell-3-27" class="code-annotation-target">    eigenvalues, eigenvectors <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.linalg.eigh(cov)</span>
<span id="annotated-cell-3-28">    eigenvalues <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">abs</span>(eigenvalues)</span>
<span id="annotated-cell-3-29"></span>
<span id="annotated-cell-3-30">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Normal = eigenvector of smallest eigenvalue</span></span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-3" data-target-annotation="3">3</button><span id="annotated-cell-3-31" class="code-annotation-target">    normal <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> eigenvectors[:, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="annotated-cell-3-32">    normal <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> normal <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (np.linalg.norm(normal) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-10</span>)</span>
<span id="annotated-cell-3-33"></span>
<span id="annotated-cell-3-34">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Planarity test: λ₁/λ₂ ≤ threshold</span></span>
<span id="annotated-cell-3-35">    planarity_threshold <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.04</span></span>
<span id="annotated-cell-3-36">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> eigenvalues[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-10</span>:</span>
<span id="annotated-cell-3-37">        is_planar <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span></span>
<span id="annotated-cell-3-38">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="annotated-cell-3-39">        is_planar <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (eigenvalues[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> eigenvalues[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> planarity_threshold</span>
<span id="annotated-cell-3-40"></span>
<span id="annotated-cell-3-41">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> centroid, normal, eigenvalues, is_planar</span>
<span id="annotated-cell-3-42"></span>
<span id="annotated-cell-3-43"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Demo with synthetic planar points</span></span>
<span id="annotated-cell-3-44">np.random.seed(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="annotated-cell-3-45"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Points on a plane z = 0 with small noise</span></span>
<span id="annotated-cell-3-46">planar_pts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.column_stack([</span>
<span id="annotated-cell-3-47">    np.random.uniform(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>),</span>
<span id="annotated-cell-3-48">    np.random.uniform(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>),</span>
<span id="annotated-cell-3-49">    np.random.normal(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.01</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Small z-noise</span></span>
<span id="annotated-cell-3-50">])</span>
<span id="annotated-cell-3-51"></span>
<span id="annotated-cell-3-52">centroid, normal, eigenvalues, is_planar <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> compute_cell_features(planar_pts)</span>
<span id="annotated-cell-3-53"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Eigenvalues: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>eigenvalues<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="annotated-cell-3-54"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Ratio λ₁/λ₂: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>eigenvalues[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>eigenvalues[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="annotated-cell-3-55"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Is planar: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>is_planar<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="annotated-cell-3-56"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Normal: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>normal<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> (should be ~[0, 0, 1])"</span>)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-hidden code-annotation-container-grid">
<dt data-target-cell="annotated-cell-3" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-3" data-code-lines="24" data-code-annotation="1">Covariance matrix captures the spread of points in each direction</span>
</dd>
<dt data-target-cell="annotated-cell-3" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-3" data-code-lines="27" data-code-annotation="2"><code>eigh</code> returns eigenvalues sorted ascending - important for our ratios</span>
</dd>
<dt data-target-cell="annotated-cell-3" data-target-annotation="3">3</dt>
<dd>
<span data-code-cell="annotated-cell-3" data-code-lines="31" data-code-annotation="3">The smallest eigenvalue’s eigenvector points perpendicular to the spread</span>
</dd>
</dl>
</div>
<div class="cell-output cell-output-stdout">
<pre><code>Eigenvalues: [9.45656815e-05 3.32523124e-01 3.58162504e-01]
Ratio λ₁/λ₂: 0.0003
Is planar: True
Normal: [ 0.00170904 -0.00359751  0.99999207] (should be ~[0, 0, 1])</code></pre>
</div>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="images/tikz/covariance-ellipsoids.png" class="lightbox" data-gallery="quarto-lightbox-gallery-4" title="NDT cell classification by eigenvalues"><img src="https://ravila.dev/posts/2026-01-18-room-shell-extraction/images/tikz/covariance-ellipsoids.png" class="img-fluid figure-img" data-fig-cap="The eigenvectors are the principal axes (directions), and the eigenvalues are the magnitudes. Together they describe how points spread within each cell." alt="NDT cell classification by eigenvalues"></a></p>
<figcaption>NDT cell classification by eigenvalues</figcaption>
</figure>
</div>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>If you’re familiar with basic statistics but not linear algebra: the covariance matrix is just the multi-dimensional version of variance. We are effectively fitting a 3D Gaussian distribution, hence the name <strong>Normal Distribution Transformation</strong>.</p>
</div>
</div>
</section>
<section id="the-key-insight-better-sampling-probability" class="level3">
<h3 class="anchored" data-anchor-id="the-key-insight-better-sampling-probability">The Key Insight: Better Sampling Probability</h3>
<p><strong>Because we sample from pre-classified planar cells, the probability of picking a good sample is dramatically improved</strong>:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Method</th>
<th>P(good sample)</th>
<th>w = 10%</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Standard RANSAC</td>
<td><img src="https://latex.codecogs.com/png.latex?w%5E3"></td>
<td>0.1% per iteration</td>
</tr>
<tr class="even">
<td>NDT-RANSAC</td>
<td><img src="https://latex.codecogs.com/png.latex?w"></td>
<td>10% per iteration</td>
</tr>
</tbody>
</table>
<p>That’s a 100× speedup: instead of hoping 3 random points all land on the same surface, you pick one cell that’s <em>already proven</em> to be planar.</p>
</section>
<section id="step-2-grow-the-plane" class="level3">
<h3 class="anchored" data-anchor-id="step-2-grow-the-plane">Step 2: Grow the Plane</h3>
<p>Selecting a good seed cell is only the first step. We need to find all other cells belonging to the same plane using a <strong>dual condition</strong>:</p>
<ol type="1">
<li><p><strong>Spatial Proximity</strong>: Distance from cell center to the hypothesized plane &lt; <img src="https://latex.codecogs.com/png.latex?%5CDelta_d"> <img src="https://latex.codecogs.com/png.latex?d%20=%20%7C(%5Cmathbf%7Bg%7D_%7Bcell%7D%20-%20%5Cmathbf%7Bg%7D_%7Bseed%7D)%20%5Ccdot%20%5Cmathbf%7Bn%7D_%7Bseed%7D%7C"></p></li>
<li><p><strong>Normal Consistency</strong>: Angle between cell normal and plane normal &lt; <img src="https://latex.codecogs.com/png.latex?%5CDelta_%5Ctheta"> <img src="https://latex.codecogs.com/png.latex?%5Ctheta%20=%20%5Carccos(%5Cmathbf%7Bn%7D_%7Bcell%7D%20%5Ccdot%20%5Cmathbf%7Bn%7D_%7Bseed%7D)"></p></li>
</ol>
<p>Typical thresholds from the paper: <img src="https://latex.codecogs.com/png.latex?%5CDelta_d%20=%200.08m">, <img src="https://latex.codecogs.com/png.latex?%5CDelta_%5Ctheta%20=%2015%C2%B0">.</p>
</section>
<section id="step-3-refine-with-irls" class="level3">
<h3 class="anchored" data-anchor-id="step-3-refine-with-irls">Step 3: Refine with IRLS</h3>
<p>After finding inliers, we need to fit the final plane equation. Standard least-squares minimizes <img src="https://latex.codecogs.com/png.latex?%5Csum%20r_i%5E2"> where <img src="https://latex.codecogs.com/png.latex?r_i"> is each point’s distance to the plane. The problem: <strong>outliers have outsized influence</strong>.</p>
<p><strong>IRLS (Iteratively Reweighted Least Squares)</strong> fixes this by iteratively adjusting weights:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7Bminimize%7D%20%5Csum%20w(r_i)%20%5Ccdot%20r_i%5E2"></p>
<div id="irls-fit" class="cell" data-execution_count="4">
<details class="code-fold">
<summary>Show code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-4" style="background: #f1f3f5;"><pre class="sourceCode python code-annotation-code code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-4-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> irls_fit_plane(</span>
<span id="annotated-cell-4-2">    points: np.ndarray,</span>
<span id="annotated-cell-4-3">    max_iter: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>,</span>
<span id="annotated-cell-4-4">    convergence_threshold: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-6</span></span>
<span id="annotated-cell-4-5">) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>[np.ndarray, np.ndarray]:</span>
<span id="annotated-cell-4-6">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="annotated-cell-4-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Robust plane fitting using IRLS with Welsch weight function.</span></span>
<span id="annotated-cell-4-8"></span>
<span id="annotated-cell-4-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    w(r) = exp(-r²/k²) where k = 2.985</span></span>
<span id="annotated-cell-4-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-4" data-target-annotation="1">1</button><span id="annotated-cell-4-11" class="code-annotation-target">    k_welsch <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.985</span>  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Standard tuning constant for 95% efficiency</span></span>
<span id="annotated-cell-4-12"></span>
<span id="annotated-cell-4-13">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Initial fit via SVD</span></span>
<span id="annotated-cell-4-14">    centroid <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.mean(points, axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="annotated-cell-4-15">    centered <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> points <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> centroid</span>
<span id="annotated-cell-4-16">    _, _, vh <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.linalg.svd(centered)</span>
<span id="annotated-cell-4-17">    normal <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> vh[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="annotated-cell-4-18">    normal <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> normal <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> np.linalg.norm(normal)</span>
<span id="annotated-cell-4-19"></span>
<span id="annotated-cell-4-20">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> iteration <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(max_iter):</span>
<span id="annotated-cell-4-21">        old_normal <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> normal.copy()</span>
<span id="annotated-cell-4-22"></span>
<span id="annotated-cell-4-23">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Compute residuals (distances to plane)</span></span>
<span id="annotated-cell-4-24">        residuals <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">abs</span>(np.dot(centered, normal))</span>
<span id="annotated-cell-4-25"></span>
<span id="annotated-cell-4-26">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Welsch weights: exp(-r²/k²)</span></span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-4" data-target-annotation="2">2</button><span id="annotated-cell-4-27" class="code-annotation-target">        weights <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.exp(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>(residuals <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (k_welsch <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))</span>
<span id="annotated-cell-4-28"></span>
<span id="annotated-cell-4-29">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Weighted centroid</span></span>
<span id="annotated-cell-4-30">        weighted_centroid <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.average(points, axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, weights<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>weights)</span>
<span id="annotated-cell-4-31">        centered <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> points <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> weighted_centroid</span>
<span id="annotated-cell-4-32"></span>
<span id="annotated-cell-4-33">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Weighted covariance</span></span>
<span id="annotated-cell-4-34">        weighted_cov <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.dot(centered.T <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> weights, centered) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> weights.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>()</span>
<span id="annotated-cell-4-35"></span>
<span id="annotated-cell-4-36">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># New normal from smallest eigenvalue</span></span>
<span id="annotated-cell-4-37">        eigenvalues, eigenvectors <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.linalg.eigh(weighted_cov)</span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-4" data-target-annotation="3">3</button><span id="annotated-cell-4-38" class="code-annotation-target">        normal <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> eigenvectors[:, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="annotated-cell-4-39">        normal <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> normal <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> np.linalg.norm(normal)</span>
<span id="annotated-cell-4-40"></span>
<span id="annotated-cell-4-41">        centroid <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> weighted_centroid</span>
<span id="annotated-cell-4-42"></span>
<span id="annotated-cell-4-43">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Check convergence</span></span>
<span id="annotated-cell-4-44">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> np.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(np.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">abs</span>(normal <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> old_normal)) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> convergence_threshold:</span>
<span id="annotated-cell-4-45">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">break</span></span>
<span id="annotated-cell-4-46"></span>
<span id="annotated-cell-4-47">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> normal, centroid</span>
<span id="annotated-cell-4-48"></span>
<span id="annotated-cell-4-49"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Demo: plane with outliers</span></span>
<span id="annotated-cell-4-50">np.random.seed(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="annotated-cell-4-51"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Main plane: z ≈ 0</span></span>
<span id="annotated-cell-4-52">inliers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.column_stack([</span>
<span id="annotated-cell-4-53">    np.random.uniform(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">80</span>),</span>
<span id="annotated-cell-4-54">    np.random.uniform(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">80</span>),</span>
<span id="annotated-cell-4-55">    np.random.normal(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">80</span>)</span>
<span id="annotated-cell-4-56">])</span>
<span id="annotated-cell-4-57"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Outliers: points far from plane</span></span>
<span id="annotated-cell-4-58">outliers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.column_stack([</span>
<span id="annotated-cell-4-59">    np.random.uniform(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>),</span>
<span id="annotated-cell-4-60">    np.random.uniform(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>),</span>
<span id="annotated-cell-4-61">    np.random.uniform(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Way off the plane</span></span>
<span id="annotated-cell-4-62">])</span>
<span id="annotated-cell-4-63">points_with_outliers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.vstack([inliers, outliers])</span>
<span id="annotated-cell-4-64"></span>
<span id="annotated-cell-4-65"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Compare standard vs IRLS</span></span>
<span id="annotated-cell-4-66">standard_normal, _ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.linalg.svd(points_with_outliers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> points_with_outliers.mean(axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>))[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>][<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span></span>
<span id="annotated-cell-4-67">standard_normal <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> standard_normal <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> np.linalg.norm(standard_normal)</span>
<span id="annotated-cell-4-68"></span>
<span id="annotated-cell-4-69">irls_normal, irls_centroid <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> irls_fit_plane(points_with_outliers)</span>
<span id="annotated-cell-4-70"></span>
<span id="annotated-cell-4-71"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"True normal: [0, 0, 1]"</span>)</span>
<span id="annotated-cell-4-72"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Standard LS normal: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>np<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">abs</span>(standard_normal)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="annotated-cell-4-73"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"IRLS normal: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>np<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">abs</span>(irls_normal)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-hidden code-annotation-container-grid">
<dt data-target-cell="annotated-cell-4" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-4" data-code-lines="11" data-code-annotation="1">The value <img src="https://latex.codecogs.com/png.latex?k%20=%202.985"> achieves 95% efficiency - losing only 5% precision vs standard LS when there are no outliers</span>
</dd>
<dt data-target-cell="annotated-cell-4" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-4" data-code-lines="27" data-code-annotation="2">Welsch weights fall off exponentially with distance, effectively ignoring far outliers</span>
</dd>
<dt data-target-cell="annotated-cell-4" data-target-annotation="3">3</dt>
<dd>
<span data-code-cell="annotated-cell-4" data-code-lines="38" data-code-annotation="3">After reweighting, we solve the normal eigenvalue problem again</span>
</dd>
</dl>
</div>
<div class="cell-output cell-output-stdout">
<pre><code>True normal: [0, 0, 1]
Standard LS normal: [0.154 0.073 0.985]
IRLS normal: [0.127 0.076 0.989]</code></pre>
</div>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="images/tikz/irls-comparison.png" class="lightbox" data-gallery="quarto-lightbox-gallery-5" title="Standard LS vs IRLS comparison"><img src="https://ravila.dev/posts/2026-01-18-room-shell-extraction/images/tikz/irls-comparison.png" class="img-fluid figure-img" data-fig-cap="Standard least squares (gray line) gets pulled toward the outlier. IRLS (red line) downweights distant points, producing a fit that matches the actual data distribution." alt="Standard LS vs IRLS comparison"></a></p>
<figcaption>Standard LS vs IRLS comparison</figcaption>
</figure>
</div>
<div class="callout callout-style-default callout-tip callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>If you’ve used <code>glm()</code> in R, you’ve used IRLS - it’s the algorithm that fits generalized linear models internally.</p>
</div>
</div>
</section>
<section id="step-4-handle-disconnected-components" class="level3">
<h3 class="anchored" data-anchor-id="step-4-handle-disconnected-components">Step 4: Handle Disconnected Components</h3>
<p>After fitting a plane, we need to handle an additional problem: <strong>a mathematical plane is infinite, but physical surfaces are finite</strong>.</p>
<p>RANSAC might find a single plane that contains points from two disconnected physical walls if they share the same orientation and both satisfy the distance threshold.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="images/tikz/connected-components.png" class="lightbox" data-gallery="quarto-lightbox-gallery-6" title="Connected component analysis"><img src="https://ravila.dev/posts/2026-01-18-room-shell-extraction/images/tikz/connected-components.png" class="img-fluid figure-img" data-fig-cap="The &quot;teleportation problem&quot;: A single mathematical plane (light blue, infinite) can intersect two separate physical walls. Without connected-component analysis, RANSAC would treat these as one surface." alt="Connected component analysis"></a></p>
<figcaption>Connected component analysis</figcaption>
</figure>
</div>
<p><strong>Connected-component analysis</strong> solves this by examining spatial connectivity:</p>
<div id="connected-components" class="cell" data-execution_count="5">
<details class="code-fold">
<summary>Show code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-5" style="background: #f1f3f5;"><pre class="sourceCode python code-annotation-code code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-5-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> scipy.spatial <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> KDTree</span>
<span id="annotated-cell-5-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> scipy.sparse <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> csr_matrix</span>
<span id="annotated-cell-5-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> scipy.sparse.csgraph <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> connected_components</span>
<span id="annotated-cell-5-4"></span>
<span id="annotated-cell-5-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> split_by_connectivity(</span>
<span id="annotated-cell-5-6">    inlier_points: np.ndarray,</span>
<span id="annotated-cell-5-7">    neighbor_radius: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>,</span>
<span id="annotated-cell-5-8">    min_component_points: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span></span>
<span id="annotated-cell-5-9">) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[np.ndarray]:</span>
<span id="annotated-cell-5-10">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="annotated-cell-5-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Split points into spatially connected groups.</span></span>
<span id="annotated-cell-5-12"></span>
<span id="annotated-cell-5-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Args:</span></span>
<span id="annotated-cell-5-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        inlier_points: (N, 3) points on a detected plane</span></span>
<span id="annotated-cell-5-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        neighbor_radius: Max distance for connectivity (2-3× RANSAC threshold)</span></span>
<span id="annotated-cell-5-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        min_component_points: Filter small components as noise</span></span>
<span id="annotated-cell-5-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="annotated-cell-5-18">    n_points <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(inlier_points)</span>
<span id="annotated-cell-5-19">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> n_points <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> min_component_points:</span>
<span id="annotated-cell-5-20">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> [np.arange(n_points)]</span>
<span id="annotated-cell-5-21"></span>
<span id="annotated-cell-5-22">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Build KD-tree for neighbor queries</span></span>
<span id="annotated-cell-5-23">    tree <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> KDTree(inlier_points)</span>
<span id="annotated-cell-5-24"></span>
<span id="annotated-cell-5-25">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Find all neighbor pairs within radius</span></span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-5" data-target-annotation="1">1</button><span id="annotated-cell-5-26" class="code-annotation-target">    pairs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tree.query_pairs(r<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>neighbor_radius, output_type<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'ndarray'</span>)</span>
<span id="annotated-cell-5-27"></span>
<span id="annotated-cell-5-28">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(pairs) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="annotated-cell-5-29">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> [np.arange(n_points)]  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># No connections</span></span>
<span id="annotated-cell-5-30"></span>
<span id="annotated-cell-5-31">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Build sparse adjacency matrix</span></span>
<span id="annotated-cell-5-32">    row_indices <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.concatenate([pairs[:, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], pairs[:, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]])</span>
<span id="annotated-cell-5-33">    col_indices <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.concatenate([pairs[:, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], pairs[:, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]])</span>
<span id="annotated-cell-5-34">    data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.ones(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(row_indices), dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>np.int8)</span>
<span id="annotated-cell-5-35"></span>
<span id="annotated-cell-5-36">    adjacency <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> csr_matrix(</span>
<span id="annotated-cell-5-37">        (data, (row_indices, col_indices)),</span>
<span id="annotated-cell-5-38">        shape<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(n_points, n_points)</span>
<span id="annotated-cell-5-39">    )</span>
<span id="annotated-cell-5-40"></span>
<span id="annotated-cell-5-41">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Find connected components</span></span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-5" data-target-annotation="2">2</button><span id="annotated-cell-5-42" class="code-annotation-target">    n_components, labels <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> connected_components(</span>
<span id="annotated-cell-5-43">        adjacency, directed<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, return_labels<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span></span>
<span id="annotated-cell-5-44">    )</span>
<span id="annotated-cell-5-45"></span>
<span id="annotated-cell-5-46">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Split into groups</span></span>
<span id="annotated-cell-5-47">    groups <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="annotated-cell-5-48">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> comp_id <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(n_components):</span>
<span id="annotated-cell-5-49">        mask <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> labels <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> comp_id</span>
<span id="annotated-cell-5-50">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> mask.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> min_component_points:</span>
<span id="annotated-cell-5-51">            groups.append(np.where(mask)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>])</span>
<span id="annotated-cell-5-52"></span>
<span id="annotated-cell-5-53">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> groups <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> groups <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> [np.arange(n_points)]</span>
<span id="annotated-cell-5-54"></span>
<span id="annotated-cell-5-55"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Demo: two separate clusters</span></span>
<span id="annotated-cell-5-56">np.random.seed(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span>
<span id="annotated-cell-5-57">cluster1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.random.randn(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="annotated-cell-5-58">cluster2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.random.randn(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 5m away</span></span>
<span id="annotated-cell-5-59">combined <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.vstack([cluster1, cluster2])</span>
<span id="annotated-cell-5-60"></span>
<span id="annotated-cell-5-61">groups <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> split_by_connectivity(combined, neighbor_radius<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, min_component_points<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>)</span>
<span id="annotated-cell-5-62"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Found </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(groups)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> connected components"</span>)</span>
<span id="annotated-cell-5-63"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, g <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(groups):</span>
<span id="annotated-cell-5-64">    center <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> combined[g].mean(axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="annotated-cell-5-65">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"  Component </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(g)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> points, center at </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>center<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</details>
<div class="cell-annotation">
<dl class="code-annotation-container-hidden code-annotation-container-grid">
<dt data-target-cell="annotated-cell-5" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-5" data-code-lines="26" data-code-annotation="1"><code>query_pairs</code> efficiently finds all point pairs within radius using the KD-tree</span>
</dd>
<dt data-target-cell="annotated-cell-5" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-5" data-code-lines="42" data-code-annotation="2"><code>connected_components</code> is the same algorithm used in image processing to identify blobs</span>
</dd>
</dl>
</div>
<div class="cell-output cell-output-stdout">
<pre><code>Found 2 connected components
  Component 1: 100 points, center at [ 0.01 -0.02  0.01]
  Component 2: 100 points, center at [ 5.   -0.01  0.  ]</code></pre>
</div>
</div>
</section>
</section>
<section id="the-real-challenge-boundary-extraction" class="level2">
<h2 class="anchored" data-anchor-id="the-real-challenge-boundary-extraction">The Real Challenge: Boundary Extraction</h2>
<p>Detecting planes was the easy part. The difficult part was turning detected wall planes into a clean boundary polygon.</p>
<section id="ceiling-height-filtering" class="level3">
<h3 class="anchored" data-anchor-id="ceiling-height-filtering">Ceiling-Height Filtering</h3>
<p>First problem: <strong>we’re detecting too many wall segments</strong>. Many “wall” segments are actually furniture - bookcases, cabinets, and other vertical surfaces that happen to be planar.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="images/wall_classification_problem.png" class="lightbox" data-gallery="quarto-lightbox-gallery-7" title="Wall classification problem"><img src="https://ravila.dev/posts/2026-01-18-room-shell-extraction/images/wall_classification_problem.png" class="img-fluid figure-img" data-fig-cap="The problem: All red segments are classified as &quot;walls&quot; by RANSAC. But look at the side view (right) - many segments stop well below the ceiling line. These are furniture, not walls." alt="Wall classification problem"></a></p>
<figcaption>Wall classification problem</figcaption>
</figure>
</div>
<p><strong>Filtering by height</strong>: Keep only segments where <code>y_max &gt;= 2.0m</code>. This simple threshold eliminates most furniture while keeping all true walls.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="images/segment_heights_example.png" class="lightbox" data-gallery="quarto-lightbox-gallery-8" title="Segment height analysis"><img src="https://ravila.dev/posts/2026-01-18-room-shell-extraction/images/segment_heights_example.png" class="img-fluid figure-img" data-fig-cap="Left: Side view showing wall segments (green) reaching ceiling vs furniture (red) stopping mid-height. Middle: Top-down view confirms walls form the perimeter while furniture is interior. Right: Bar chart showing the clear 2.0m threshold separating walls from furniture." alt="Segment height analysis"></a></p>
<figcaption>Segment height analysis</figcaption>
</figure>
</div>
</section>
<section id="enclosure-filtering-handling-doorways" class="level3">
<h3 class="anchored" data-anchor-id="enclosure-filtering-handling-doorways">Enclosure Filtering: Handling Doorways</h3>
<p>Height filtering removes furniture, but there’s another problem: <strong>doorways</strong>. The scanner captured points through open doors into hallways and adjacent rooms. These points pass the height filter (hallway walls also reach the ceiling), but they’re not part of the room we’re trying to extract.</p>
<p>The solution is <strong>enclosure scoring</strong> - a ray-casting algorithm that identifies which regions are “inside” vs “outside” the room:</p>
<div id="enclosure-filtering" class="cell" data-execution_count="6">
<details class="code-fold">
<summary>Show enclosure scoring algorithm</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> compute_enclosure_score(</span>
<span id="cb6-2">    x: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>, z: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>,</span>
<span id="cb6-3">    wall_segments: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>],</span>
<span id="cb6-4">    ray_directions: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>), (<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>), (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)]</span>
<span id="cb6-5">) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>:</span>
<span id="cb6-6">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb6-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Count how many ray directions hit a wall.</span></span>
<span id="cb6-8"></span>
<span id="cb6-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    A point is "enclosed" if rays in multiple directions hit walls.</span></span>
<span id="cb6-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb6-11">    hits <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb6-12">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> dx, dz <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> ray_directions:</span>
<span id="cb6-13">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Cast ray and check for wall intersections</span></span>
<span id="cb6-14">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (simplified - real implementation checks segment bounds)</span></span>
<span id="cb6-15">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> seg_start, seg_end <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> wall_segments:</span>
<span id="cb6-16">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> ray_intersects_segment(x, z, dx, dz, seg_start, seg_end):</span>
<span id="cb6-17">                hits <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb6-18">                <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">break</span>  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># One hit per direction is enough</span></span>
<span id="cb6-19">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> hits</span>
<span id="cb6-20"></span>
<span id="cb6-21"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> ray_intersects_segment(x, z, dx, dz, start, end):</span>
<span id="cb6-22">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Check if ray from (x,z) in direction (dx,dz) hits segment."""</span></span>
<span id="cb6-23">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Parametric ray-segment intersection</span></span>
<span id="cb6-24">    x1, z1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> start</span>
<span id="cb6-25">    x2, z2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> end</span>
<span id="cb6-26"></span>
<span id="cb6-27">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Ray: (x,z) + t*(dx,dz), t &gt;= 0</span></span>
<span id="cb6-28">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Segment: (x1,z1) + s*(x2-x1,z2-z1), 0 &lt;= s &lt;= 1</span></span>
<span id="cb6-29"></span>
<span id="cb6-30">    denom <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (z2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> z1) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> dz <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (x2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> x1)</span>
<span id="cb6-31">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">abs</span>(denom) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-10</span>:</span>
<span id="cb6-32">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Parallel</span></span>
<span id="cb6-33"></span>
<span id="cb6-34">    t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ((x1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> x) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (z2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> z1) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> (z1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> z) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (x2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> x1)) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> denom</span>
<span id="cb6-35">    s <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ((x1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> x) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> dz <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> (z1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> z) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> dx) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> denom</span>
<span id="cb6-36"></span>
<span id="cb6-37">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">and</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> s <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span></code></pre></div></div>
</details>
</div>
<p>The algorithm:</p>
<ol type="1">
<li><strong>Create a 2D grid</strong> over the XZ projection (0.3m cells)</li>
<li><strong>For each cell</strong>, cast rays in 4 cardinal directions (N, S, E, W)</li>
<li><strong>Count wall hits</strong>: How many rays intersect a detected wall segment?</li>
<li><strong>Score the cell</strong>: Cells with walls on multiple sides (score ≥ 2) are “enclosed”</li>
<li><strong>Find largest region</strong>: Use connected-component analysis to identify the main room</li>
</ol>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="images/1_11_2026_aligned_enclosure_filter.png" class="lightbox" data-gallery="quarto-lightbox-gallery-9" title="Enclosure filtering visualization"><img src="https://ravila.dev/posts/2026-01-18-room-shell-extraction/images/1_11_2026_aligned_enclosure_filter.png" class="img-fluid figure-img" data-fig-cap="Enclosure filtering in action. Green points are &quot;inside&quot; - enclosed by walls on multiple sides. Red points are &quot;outside&quot; - the hallway through the doorway (right), an adjacent room (top), and areas where walls weren't detected (bottom)." alt="Enclosure filtering visualization"></a></p>
<figcaption>Enclosure filtering visualization</figcaption>
</figure>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="images/1_11_2026_aligned_enclosure_v2.png" class="lightbox" data-gallery="quarto-lightbox-gallery-10" title="Enclosure filtering visualization (aligned, v2)"><img src="https://ravila.dev/posts/2026-01-18-room-shell-extraction/images/1_11_2026_aligned_enclosure_v2.png" class="img-fluid figure-img" data-fig-cap="Enclosure filtering visualization after alignment (version 2)." alt="Enclosure filtering visualization (aligned, v2)"></a></p>
<figcaption>Enclosure filtering visualization (aligned, v2)</figcaption>
</figure>
</div>
</section>
</section>
<section id="edge-detection-beyond-planes" class="level2">
<h2 class="anchored" data-anchor-id="edge-detection-beyond-planes">Edge Detection: Beyond Planes</h2>
<p>The same eigenvalue analysis that identifies planar cells can identify <strong>linear</strong> cells (edges). For linear cells, <img src="https://latex.codecogs.com/png.latex?%5Clambda_2/%5Clambda_3%20%5Cleq%200.2"> - points spread along one dominant direction while the perpendicular spreads are similarly small.</p>
<p>Edges provide information planes cannot: <strong>room corners</strong> (vertical edges where walls meet) and <strong>missing wall inference</strong> (edge exists but no plane detected → unscanned wall).</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><a href="images/1_11_2026_corners_no_filter.png" class="lightbox" data-gallery="quarto-lightbox-gallery-11" title="Corner detection from vertical edges"><img src="https://ravila.dev/posts/2026-01-18-room-shell-extraction/images/1_11_2026_corners_no_filter.png" class="img-fluid figure-img" data-fig-cap="Vertical edge cells (red dots) classified as &quot;linear&quot; with vertical direction. Clustering by XZ position reveals 22 corner candidates (black stars). Many align with obvious room corners; some mark furniture edges." alt="Corner detection from vertical edges"></a></p>
<figcaption>Corner detection from vertical edges</figcaption>
</figure>
</div>
</section>
<section id="tuning-the-cell-size" class="level2">
<h2 class="anchored" data-anchor-id="tuning-the-cell-size">Tuning the Cell Size</h2>
<p>The theoretical constraint from Li et al. <span class="citation" data-cites="li2017">(Li et al. 2017)</span>:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Cleft(%5Cfrac%7B%5Cvarepsilon%7D%7Bs%7D%5Cright)%5E2%20%3C%20t_e%20%3C%200.04"></p>
<p>Where <img src="https://latex.codecogs.com/png.latex?%5Cvarepsilon"> = sensor noise, <img src="https://latex.codecogs.com/png.latex?s"> = cell size, <img src="https://latex.codecogs.com/png.latex?t_e"> = planarity threshold.</p>
<p>The cell must be large enough that noise doesn’t dominate eigenvalue spread. Too small: noise overwhelms geometry, everything looks “spherical”. Too large: misses detail, merges distinct surfaces.</p>
<section id="mesh-density-varies-wildly" class="level3">
<h3 class="anchored" data-anchor-id="mesh-density-varies-wildly">Mesh Density Varies Wildly</h3>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Mesh</th>
<th>Density (pts/m²)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>1_11_2026_aligned.obj</td>
<td><strong>291</strong></td>
</tr>
<tr class="even">
<td>Untitled_Scan.obj</td>
<td><strong>835</strong></td>
</tr>
<tr class="odd">
<td>1_11_2026_4.obj</td>
<td><strong>1,298</strong></td>
</tr>
</tbody>
</table>
<p>A 4× density difference between scans of the same apartment.</p>
<p><strong>Practical rule</strong>: sparse phone photogrammetry needs 25-50cm cells; dense TLS can use 10-25cm.</p>
</section>
</section>
<section id="next-steps" class="level2">
<h2 class="anchored" data-anchor-id="next-steps">Next Steps</h2>
<p>The CCW ordering failure points to a fundamental issue: we’re trying to construct a complex polygon from unordered corners. With the ceiling-height filter reducing noise, several alternative approaches to explore:</p>
<ol type="1">
<li><p><strong>Convex hull + selective inward refinement</strong>: Start with the simplest valid boundary (convex hull of wall points), then selectively “push in” edges only where strong evidence of indentation exists.</p></li>
<li><p><strong>Grid-based occupancy</strong>: Discretize the floor into a 2D grid, mark cells containing wall points, then trace the boundary using marching squares.</p></li>
<li><p><strong>Constrained concave hull</strong>: Use a concave hull algorithm (alpha shapes) but constrain edges to align with detected Manhattan directions.</p></li>
<li><p><strong>Boundary tracing</strong>: Instead of finding all corners then ordering them, start at one segment and “walk” the perimeter - always turning to the next adjacent segment.</p></li>
</ol>
<p>The perfect room boundary extractor remains elusive, but each iteration reveals more about the problem structure. The key insight: <strong>start simple, add complexity only where data supports it</strong>.</p>
</section>
<section id="lessons-learned" class="level2">
<h2 class="anchored" data-anchor-id="lessons-learned">Lessons Learned</h2>
<ol type="1">
<li><p><strong>Real-world data is messy.</strong> Furniture occludes walls, scanning artifacts create phantom planes, doorways create gaps that may or may not be intentional room boundaries.</p></li>
<li><p><strong>NDT pre-classification is powerful.</strong> By reasoning about local geometry before sampling, we eliminate entire classes of errors.</p></li>
<li><p><strong>Connected components matter.</strong> A mathematical plane can span disconnected physical surfaces - always check spatial connectivity.</p></li>
</ol>
<hr>
</section>
<section id="references" class="level2">



<!-- -->


</section>

<div id="quarto-appendix" class="default"><section class="quarto-appendix-contents" id="quarto-bibliography"><h2 class="anchored quarto-appendix-heading">References</h2><div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="0">
<div id="ref-fischler1981" class="csl-entry">
Fischler, Martin A., and Robert C. Bolles. 1981. <span>“Random Sample Consensus: A Paradigm for Model Fitting with Applications to Image Analysis and Automated Cartography.”</span> <em>Communications of the ACM</em> 24 (6): 381–95. <a href="https://doi.org/10.1145/358669.358692">https://doi.org/10.1145/358669.358692</a>.
</div>
<div id="ref-li2017" class="csl-entry">
Li, Lin, Fan Yang, Haihong Zhu, Deren Li, Yuan Li, and Liang Tang. 2017. <span>“An Improved <span>RANSAC</span> for <span>3D</span> Point Cloud Plane Segmentation Based on Normal Distribution Transformation Cells.”</span> <em>Remote Sensing</em> 9 (5): 433. <a href="https://doi.org/10.3390/rs9050433">https://doi.org/10.3390/rs9050433</a>.
</div>
</div></section></div> ]]></description>
  <category>Python</category>
  <category>computational-geometry</category>
  <category>3D-reconstruction</category>
  <guid>https://ravila.dev/posts/2026-01-18-room-shell-extraction/</guid>
  <pubDate>Sun, 18 Jan 2026 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Making My Own Engagement Ring</title>
  <link>https://ravila.dev/posts/2025-01-20-making-my-own-engagement-ring/</link>
  <description><![CDATA[ 






<p>I always knew I wanted to make my own engagement ring – even before I was sure that it was possible. It wasn’t just about the challenge (although I do have a habit of choosing the most difficult way of doing things). I knew I wanted something that truly reflected my journey with my partner. And I realized that even if I couldn’t make something perfect, I could still create something that truly belonged to us.</p>
<p>With this in mind, I began the work of turning my idea into something tangible. Given that I have never worked with metal jewelry before, it involved a lot of research - I found information in blogs, youtube videos, and books, which I’ll be linking in this post. Hopefully this will inspire or guide anyone else who’s curious about taking on a similar project.</p>
<section id="part-1-the-design" class="level2">
<h2 class="anchored" data-anchor-id="part-1-the-design">Part 1: The Design</h2>
<p>The process of designing and crafting a ring is slow and deliberate, which to me was the perfect chance to reflect on what this ring should symbolize.</p>
<p>My partner and I are avid gardeners and nature lovers, so I knew I wanted to incorporate some nature themes.I decided to go with a concept of two intertwined trees, which I felt was a fitting symbol for the way people and relationships grow.</p>
<p>It all started with a few rough sketches to visualize the concept, but I found it easier to flesh out the details in a computer. The modeling software I used was <a href="https://www.blender.org/">Blender</a>, which I also learned on the go with this project. It is probably too much to dive into the details of designing a ring in Blender, but it is not as difficult as it may seem, and there are plenty of great tutorials.</p>
<p>My initial worries about the ring were around the durability of the ring - the main guideline I found was to keep the thickness of the ring at at minimum 1mm thickness throughout<sup>1</sup></p>
<p>Finding the right dimension is also essential. You can get the right dimension from <a href="https://www.diamondscreener.com/education/round-diamond-carat-size-chart/">this chart</a>.</p>
<hr>
<section id="what-is-lost-wax-casting" class="level3">
<h3 class="anchored" data-anchor-id="what-is-lost-wax-casting">What is Lost Wax Casting?</h3>
<p>There are several building methods one could use to make a ring - probably the most common are machining and lost wax casting. In my case, I knew that my design would be pretty intricate, so I opted for the later.</p>
<p>Lost wax casting is an ancient technique that can be used for creating detailed jewelry and sculptures. The idea is simple: start by carving a model out of wax (beeswax works well). Then, encase the wax in a plaster mold. Once the plaster hardens, the wax is melted away in a process called the burnout, leaving a hollow cavity to pour molten metal into.</p>
<div id="fig-lost-wax-casting" class="quarto-float quarto-figure quarto-figure-center anchored" data-fig-align="center">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-lost-wax-casting-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://ravila.dev/posts/2025-01-20-making-my-own-engagement-ring/images/lost-wax-casting.jpg" class="img-fluid quarto-figure quarto-figure-center figure-img" width="250">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-lost-wax-casting-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1: The lost wax casting process
</figcaption>
</figure>
</div>
<p>Modern twists on this technique include using 3D printing to create the model out of resin or PLA. This allows for more intricate designs and faster production.</p>
<hr>
</section>
</section>
<section id="casting-the-ring" class="level2">
<h2 class="anchored" data-anchor-id="casting-the-ring">Casting the Ring</h2>
</section>
<section id="closing-thoughts" class="level2">
<h2 class="anchored" data-anchor-id="closing-thoughts">Closing Thoughts</h2>
<p>Just like in love, there were challenges and set-backs, but with each misstep, I found a reminder of the patience and steady effort that a lasting relationship demands.</p>


</section>


<div id="quarto-appendix" class="default"><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>

<ol>
<li id="fn1"><p>https://cms.hooverandstrong.com/uploads/Casting_Brochure1_29_24_b906631a5a.pdf↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>jewelry-making</category>
  <category>DIY</category>
  <guid>https://ravila.dev/posts/2025-01-20-making-my-own-engagement-ring/</guid>
  <pubDate>Fri, 14 Feb 2025 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Automate Your Linux Desktop: Switching GTK Themes Based on Time of Day</title>
  <link>https://ravila.dev/posts/2020-04-24-switching-themes-on-time-of-day/</link>
  <description><![CDATA[ 






<p>The ability to toggle between light and dark modes is now a standard feature across modern operating systems, from Windows and macOS to iOS and Android. This trend extends to web design, where the <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme">prefers-color-scheme</a> CSS media query can be used to adapt websites to users’ theme preferences. Automated transitions between light and dark modes—such as switching to dark mode at sunset—are particularly convenient for improving usability and reducing eye strain.</p>
<p>While Linux desktops, including GNOME, offer extensive theme customization, many lack built-in automation for these transitions. Instead, users often rely on third-party tools or scripts to bridge the gap. <sup>1</sup></p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Today, GNOME users can easily achieve this with the <a href="https://extensions.gnome.org/extension/2236/night-theme-switcher/">Night Theme Switcher</a> extension.</p>
</div>
</div>
<p>In this post, I will show you a simple way to implement theme switching using systemd timers. Beyond theme switching, systemd timers are useful for a wide range of automation tasks in Linux.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ravila.dev/posts/2020-04-24-switching-themes-on-time-of-day/images/gtk-night-day.png" class="img-fluid figure-img"></p>
<figcaption>Dark and light GTK themes in Nautilus</figcaption>
</figure>
</div>
<section id="cron-jobs-vs-systemd-timers-a-quick-overview" class="level2">
<h2 class="anchored" data-anchor-id="cron-jobs-vs-systemd-timers-a-quick-overview">Cron Jobs vs Systemd Timers: A Quick Overview</h2>
<p>Old time UNIX users will be familiar with cron jobs. Cron is a utility designed to <strong>automate</strong> tasks by running commands at scheduled times. These commands are typically defined in a file stored under <code>/etc/cronbtab</code>.</p>
<section id="an-example-crontab-job" class="level3">
<h3 class="anchored" data-anchor-id="an-example-crontab-job">An example crontab job</h3>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">SHELL</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>/bin/bash</span>
<span id="cb1-2"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">PATH</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>/sbin:/bin:/usr/sbin:/usr/bin</span>
<span id="cb1-3"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">MAILTO</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>root</span>
<span id="cb1-4"></span>
<span id="cb1-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Example of job definition:</span></span>
<span id="cb1-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># .---------------- minute (0 - 59)</span></span>
<span id="cb1-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># |  .------------- hour (0 - 23)</span></span>
<span id="cb1-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># |  |  .---------- day of month (1 - 31)</span></span>
<span id="cb1-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...</span></span>
<span id="cb1-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat</span></span>
<span id="cb1-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># |  |  |  |  |</span></span>
<span id="cb1-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># *  *  *  *  * user-name  command to be executed</span></span></code></pre></div></div>
<p>One of the unique features of cron is its ability to send an email when a job completes (or fails). By default, this email is sent to the MAILTO address specified in the crontab. However, many users forget to configure this setting or check their email notifications.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ravila.dev/posts/2020-04-24-switching-themes-on-time-of-day/images/cron_mail.png" class="img-fluid figure-img"></p>
<figcaption>Relevant xkcd</figcaption>
</figure>
</div>
<blockquote class="blockquote">
<p>“Take THAT, piece of 1980s-era infrastructure I’ve inexplicably maintained on my systems for 15 years despite never really learning how it works.”</p>
</blockquote>
</section>
<section id="what-is-systemd" class="level3">
<h3 class="anchored" data-anchor-id="what-is-systemd">What is Systemd?</h3>
<p>Systemd on the other hand, is a manager for system processes and services. It has replaced much of the functionality that was previously handled by the UNIX <code>init</code> daemon, and has several nice features that the cron utility lacks.</p>
<p>The big benefit for our purpose, is that with cron, if the computer is powered off, a scheduled cron job does not run. Systemd, on the other hand, can run the tasks that it missed the next time that it powers on.</p>
<p>Other advantages of systemd timers:</p>
<ul>
<li>CPU and memory limits</li>
<li>Randomized scheduling</li>
<li>Jobs can be easily started independently of their timers</li>
<li>Jobs are logged in systemd journal, which makes for easier debugging</li>
</ul>
</section>
</section>
<section id="step-1-creating-systemd-services" class="level2">
<h2 class="anchored" data-anchor-id="step-1-creating-systemd-services">Step 1: Creating Systemd Services</h2>
<p>Systemd services have the extension <code>.service</code>. All user-created systemd scripts will be stored in <code>~/.config/systemd/user/</code>. Here are the contents of our systemd service for switching to the Adwaita-dark GTK theme:</p>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>dark-theme.service</strong></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" data-filename="dark-theme.service" style="background: #f1f3f5;"><pre class="sourceCode ini code-with-copy"><code class="sourceCode ini"><span id="cb2-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[Unit]</span></span>
<span id="cb2-2"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Description</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Change the GTK theme to dark mode.</span></span>
<span id="cb2-3"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">After</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">graphical.target</span></span>
<span id="cb2-4"></span>
<span id="cb2-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[Service]</span></span>
<span id="cb2-6"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Type</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">oneshot</span></span>
<span id="cb2-7"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">ExecStart</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">/bin/sh -c 'gsettings set org.gnome.desktop.interface gtk-theme Adwaita-dark'</span></span>
<span id="cb2-8"></span>
<span id="cb2-9"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[Install]</span></span>
<span id="cb2-10"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">WantedBy</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">default.target</span></span></code></pre></div></div>
</div>
<p>We will need to create a separate systemd service file to switch to a light GTK theme:</p>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>light-theme.service</strong></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" data-filename="light-theme.service" style="background: #f1f3f5;"><pre class="sourceCode ini code-with-copy"><code class="sourceCode ini"><span id="cb3-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[Unit]</span></span>
<span id="cb3-2"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Description</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Switch to light GTK theme</span></span>
<span id="cb3-3"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">After</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">graphical.target</span></span>
<span id="cb3-4"></span>
<span id="cb3-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[Service]</span></span>
<span id="cb3-6"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Type</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">oneshot</span></span>
<span id="cb3-7"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">ExecStart</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">/bin/sh -c 'gsettings set org.gnome.desktop.interface gtk-theme Adwaita'</span></span>
<span id="cb3-8"></span>
<span id="cb3-9"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[Install]</span></span>
<span id="cb3-10"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">WantedBy</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">default.target</span></span></code></pre></div></div>
</div>
</section>
<section id="step-2-creating-systemd-timers" class="level2">
<h2 class="anchored" data-anchor-id="step-2-creating-systemd-timers">Step 2: Creating Systemd Timers</h2>
<p>Now, to create a timer, we make another set of files in the same directory with the same rootname plus the extension <code>.timer</code>. Here are the two files we need to create:</p>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>dark-theme.timer</strong></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" data-filename="dark-theme.timer" style="background: #f1f3f5;"><pre class="sourceCode ini code-with-copy"><code class="sourceCode ini"><span id="cb4-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[Unit]</span></span>
<span id="cb4-2"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Description</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Change the GTK theme daily at a given time.</span></span>
<span id="cb4-3"></span>
<span id="cb4-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[Timer]</span></span>
<span id="cb4-5"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">OnCalendar</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">*-*-* 16:00:00</span></span>
<span id="cb4-6"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Persistent</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">true</span></span>
<span id="cb4-7"></span>
<span id="cb4-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[Install]</span></span>
<span id="cb4-9"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">WantedBy</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">timers.target</span></span></code></pre></div></div>
</div>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>light-theme.timer</strong></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" data-filename="light-theme.timer" style="background: #f1f3f5;"><pre class="sourceCode ini code-with-copy"><code class="sourceCode ini"><span id="cb5-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[Unit]</span></span>
<span id="cb5-2"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Description</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Switch to light theme at 07:00</span></span>
<span id="cb5-3"></span>
<span id="cb5-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[Timer]</span></span>
<span id="cb5-5"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">OnCalendar</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">*-*-* 07:00:00</span></span>
<span id="cb5-6"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Persistent</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">true</span></span>
<span id="cb5-7"></span>
<span id="cb5-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[Install]</span></span>
<span id="cb5-9"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">WantedBy</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">timers.target</span></span></code></pre></div></div>
</div>
<p>The <code>OnCalendar</code> setting specifies that this particular timer should run every day at 16:00 hrs. You can also create timers that run every other day, or on specific days of the week. For more on this, you can check out the <a href="https://wiki.archlinux.org/index.php/Systemd/Timers">ArchLinux Wiki</a>.</p>
</section>
<section id="step-3-enabling-and-starting-the-services" class="level2">
<h2 class="anchored" data-anchor-id="step-3-enabling-and-starting-the-services">Step 3: Enabling and Starting the Services</h2>
<p>When we are done creating the four configuration files, we need to enable the services. It is recommended that we enable them at the user level (since requiring sudo access would be a hazzle and potential security risk).</p>
<p>Enabling the services:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">systemctl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--user</span> enable dark-theme.service</span>
<span id="cb6-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">systemctl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--user</span> enable light-theme.service</span>
<span id="cb6-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">systemctl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--user</span> enable dark-theme.timer</span>
<span id="cb6-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">systemctl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--user</span> enable light-theme.timer</span></code></pre></div></div>
<p>Now the operating system will automatically change the GTK theme at the specified times. Furthermore, if we wish to manually change the theme, or test that the service works, we may do so using:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb7-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">systemctl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--user</span> start light-theme.service</span></code></pre></div></div>
<p>or:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb8-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">systemctl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--user</span> start dark-theme.service</span></code></pre></div></div>
<p>If we have any issues, we can check the logs using:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb9-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">journalctl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--user</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-u</span> dark-theme.service</span></code></pre></div></div>
</section>
<section id="so-what-else-can-we-use-this-for" class="level2">
<h2 class="anchored" data-anchor-id="so-what-else-can-we-use-this-for">So, what else can we use this for?</h2>
<p>A couple other applications come to mind:</p>
<ul>
<li>Daily data backups</li>
<li>Daily data ingestion (web-scraping?)</li>
<li>Time-based notifications (e.g.&nbsp;set reminders to take breaks, drink water, etc.)</li>
<li>Scheduled system maintenance tasks</li>
</ul>
<p>Have you implemented a similar setup or used systemd timers for something creative? Let me know if you have other interesting applications!</p>


</section>


<div id="quarto-appendix" class="default"><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>

<ol>
<li id="fn1"><p><a href="https://wiki.archlinux.org/title/Dark_mode_switching">Arch wiki: Dark mode switching</a>↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>Linux</category>
  <guid>https://ravila.dev/posts/2020-04-24-switching-themes-on-time-of-day/</guid>
  <pubDate>Fri, 24 Apr 2020 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Getting Book Prices from AbeBooks.com</title>
  <link>https://ravila.dev/posts/2020-04-10-reverse-engineering-abebooks-api/</link>
  <description><![CDATA[ 






<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>I wrote this blog post about five years ago, and it remains one of my most viewed posts. If this topic is of interest to you, there was a recent blog posted on Hacker News which details even more cool ways to find undocumented REST APIs: <a href="https://jero.zone/posts/reverse-engineering-apis">All the data can be yours</a></p>
</div>
</div>
<section id="motivation" class="level2">
<h2 class="anchored" data-anchor-id="motivation">Motivation</h2>
<p>I have a large collection of electronic books, which I manage using <a href="https://calibre-ebook.com">Calibre</a>. Using Calibre’s “Extract ISBN” plugin, I am able to parse the ISBN identifier from most of my files, which then makes fetching the rest of the metadata very easy. (Below is an example of my library’s metadata.)</p>
<p>Thus, I have access to a very convenient and ever-growing virtual library of books, which I like to use on the go, and for exploratory research. Nevertheless, whenever I find a particularly good book, the thing that I want most, is to own a physical copy.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ravila.dev/posts/2020-04-10-reverse-engineering-abebooks-api/images/calibre.png" class="img-fluid figure-img"></p>
<figcaption>A screenshot of my calibre e-book library</figcaption>
</figure>
</div>
<p>Enter here <a href="https://www.abebooks.com/">AbeBooks.com</a>. Next to Amazon, and occasionally Ebay, it is my go-to site for buying cheap used textbooks. Given that I have stored the ISBN data for most of my electronic books, I would like to be able to automatically fetch pricing information for any book in my virtual library, perhaps even keeping track of changes in price over time.</p>
<p>However, until now, the main problem stopping me from writing a script to do this was that AbeBooks does not have a publicly available API… or at the very least, none that is explicitly documented.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ravila.dev/posts/2020-04-10-reverse-engineering-abebooks-api/images/abebooks.png" class="img-fluid figure-img"></p>
<figcaption>AbeBooks search results page</figcaption>
</figure>
</div>
</section>
<section id="rest-apis" class="level2">
<h2 class="anchored" data-anchor-id="rest-apis">REST APIs</h2>
<p>REST, or Representational State Transfer, is a method used by the HTTP protocol to provide interoperability between servers. It is based on a request/response system, where a request is a “payload”, normally formatted as HTML, XML, or JSON, and the response can be a link to a resource, a data payload in any of the aforementioned formats, or a confirmation that some data was modified in the server.</p>
<p>Several common REST methods exist: GET, HEAD, POST, PUT, PATCH, DELETE, CONNECT, OPTIONS and TRACE. Among these, the two most common are GET and POST:</p>
<p><strong>GET</strong></p>
<ul>
<li>Used to request data from a server.</li>
<li>Parameter data is stored in the URL of the query as string parameters</li>
<li>Number of parameters is limited to the length that can fit in the URL</li>
<li>Not secure for sensitive information. (Passwords can be easily seen)</li>
</ul>
<p><strong>POST</strong></p>
<ul>
<li>Used to submit data to a server, and can modify server contents.</li>
<li>Parameters are passed in the message body, rather than the URL.</li>
<li>It has no restrictions on the number of parameters.</li>
<li>Is more secure for sending sensitive information.</li>
</ul>
</section>
<section id="exploring-network-packets" class="level2">
<h2 class="anchored" data-anchor-id="exploring-network-packets">Exploring Network Packets</h2>
<p>I found that inspecting the network packets for an AbeBooks search results page is simple, and yields promising results. If we open Firefox’s developer tools, under the Network tab, we can see a list of all the packets that are loaded. In particular we are interested in those that have a JSON response, highlighted in red below:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ravila.dev/posts/2020-04-10-reverse-engineering-abebooks-api/images/packets.png" class="img-fluid figure-img"></p>
<figcaption>Network packet inspection in Firefox</figcaption>
</figure>
</div>
<p>We can see that there are four POST requests, to a service called “pricingservice”, and one GET request to a “RecomendationsApi”.</p>
<p>If we look more closely at one of the POST requests, we can see which parameters it takes in:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ravila.dev/posts/2020-04-10-reverse-engineering-abebooks-api/images/params.png" class="img-fluid figure-img"></p>
<figcaption>POST request parameters</figcaption>
</figure>
</div>
<p>ISBN! Just what we needed! Furthermore, looking at the response tab, we can see that this request returns the prices for new and used books, among other things:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ravila.dev/posts/2020-04-10-reverse-engineering-abebooks-api/images/response.png" class="img-fluid figure-img"></p>
<figcaption>Example POST response</figcaption>
</figure>
</div>
</section>
<section id="wrapping-the-api-in-python" class="level2">
<h2 class="anchored" data-anchor-id="wrapping-the-api-in-python">Wrapping the API in Python</h2>
<p>Now that we know a bit more about how AbeBooks works under the hood, we can start implementing our API wrapper in Python. We will need the requests module:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> requests</span></code></pre></div></div>
<section id="sending-post-requests" class="level3">
<h3 class="anchored" data-anchor-id="sending-post-requests">Sending POST requests</h3>
<p>The first REST method that we will implement is the POST method that fetches prices for a given book. From inspecting the page elements, we know that the URL for this service is:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1">url <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://www.abebooks.com/servlet/DWRestService/pricingservice"</span></span></code></pre></div></div>
<p>There seem to be three main parameter groups, and we can infer their purpose. (Parameters shown in bold below are to be replaced by user values)</p>
<div class="table-responsive">
<table class="table-bordered table-striped caption-top table">
<caption>Searching prices by ISBN</caption>
<thead>
<tr class="header">
<th style="text-align: left;">Parameter</th>
<th style="text-align: left;">Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">action</td>
<td style="text-align: left;">getPricingDataByISBN</td>
</tr>
<tr class="even">
<td style="text-align: left;">isbn</td>
<td style="text-align: left;"><strong>isbn</strong></td>
</tr>
<tr class="odd">
<td style="text-align: left;">container</td>
<td style="text-align: left;">pricingService-<strong>isbn</strong></td>
</tr>
</tbody>
</table>
</div>
<div class="table-responsive">
<table class="table-bordered table-striped caption-top table">
<caption>Searching prices by title and author</caption>
<thead>
<tr class="header">
<th style="text-align: left;">Parameter</th>
<th style="text-align: left;">Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">action</td>
<td style="text-align: left;">getPricingDataForAuthorTitleStandardAddToBasket</td>
</tr>
<tr class="even">
<td style="text-align: left;">an</td>
<td style="text-align: left;"><strong>author</strong></td>
</tr>
<tr class="odd">
<td style="text-align: left;">tn</td>
<td style="text-align: left;"><strong>title</strong></td>
</tr>
<tr class="even">
<td style="text-align: left;">container</td>
<td style="text-align: left;">oe-search-all</td>
</tr>
</tbody>
</table>
</div>
<div class="table-responsive">
<table class="table-bordered table-striped caption-top table">
<caption>Searching prices by title, author, and hardcover/softcover binding</caption>
<thead>
<tr class="header">
<th style="text-align: left;">Parameter</th>
<th style="text-align: left;">Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">action</td>
<td style="text-align: left;">getPricingDataForAuthorTitleBindingRefinements</td>
</tr>
<tr class="even">
<td style="text-align: left;">isbn</td>
<td style="text-align: left;">9781250297662</td>
</tr>
<tr class="odd">
<td style="text-align: left;">an</td>
<td style="text-align: left;"><strong>author</strong></td>
</tr>
<tr class="even">
<td style="text-align: left;">tn</td>
<td style="text-align: left;"><strong>title</strong></td>
</tr>
<tr class="odd">
<td style="text-align: left;">container</td>
<td style="text-align: left;"><strong>priced-from-soft</strong> OR <strong>priced-from-hard</strong></td>
</tr>
</tbody>
</table>
</div>
<hr>
<p>The parameters can be stored as keys in a dictionary, and sent to the request’s post method. For example:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Search prices by ISBN</span></span>
<span id="cb3-2">payload1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'action'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'getPricingDataByISBN'</span>,</span>
<span id="cb3-3">           <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'isbn'</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9781250297662</span>,</span>
<span id="cb3-4">           <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'container'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'pricingService-9781250297662'</span>}</span>
<span id="cb3-5"></span>
<span id="cb3-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Search prices by author and title</span></span>
<span id="cb3-7">payload2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'action'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'getPricingDataForAuthorTitleStandardAddToBasket'</span>,</span>
<span id="cb3-8">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'an'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'liu ken'</span>,</span>
<span id="cb3-9">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tn'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'broken stars'</span>,</span>
<span id="cb3-10">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'container'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'oe-search-all'</span>}</span>
<span id="cb3-11"></span>
<span id="cb3-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Sending a request</span></span>
<span id="cb3-13">resp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> requests.post(url, data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>payload1)</span>
<span id="cb3-14"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(resp.status_code, resp.reason)</span>
<span id="cb3-15">resp.json()</span></code></pre></div></div>
<p>The response is:</p>
<pre><code>200 OK</code></pre>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode json code-with-copy"><code class="sourceCode json"><span id="cb5-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'errorTexts'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">[</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">]</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-2"> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'errorCodes'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">[</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">]</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-3"> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'success'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">True</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-4"> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'newExists'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">True</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-5"> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'usedExists'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">True</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-6"> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'pricingInfoForBestNew'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'bestListingid'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">32081713842</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-7">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'totalResults'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-8">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'bestPriceInPurchaseCurrencyWithCurrencySymbol'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'US$</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">28.07</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-9">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'bestPriceInSurferCurrencyWithCurrencySymbol'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'US$</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">28.07</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-10">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'shippingToDestinationPriceInPurchaseCurrencyWithCurrencySymbol'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'US$</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.00</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-11">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'shippingToDestinationPriceInSurferCurrencyWithCurrencySymbol'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'US$</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.00</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-12">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'shippingDestinationNameInSurferLanguage'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'U.S.A.'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-13">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'vendorCountryNameInSurferLanguage'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'U.S.A.'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-14">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'vendorId'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8304062</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-15">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'bestPriceInPurchaseCurrencyValueOnly'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">28.07</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-16">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'bestShippingToDestinationPriceInPurchaseCurrencyValueOnly'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.00</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-17">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'purchaseCurrencySymbol'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'US$'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-18">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'refinementList'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-19">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'internationalEdition'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">False</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-20">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'bookCondition'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'New'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-21">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'bookDescription'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'LOCUS</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">AWARD</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">FINALIST</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">FOR</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">BEST</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">ANTHOLOGYSixteen...'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-22">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'freeShipping'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">True</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">},</span></span>
<span id="cb5-23"> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'pricingInfoForBestUsed'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'bestListingid'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">31422279270</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-24">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'totalResults'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-25">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'bestPriceInPurchaseCurrencyWithCurrencySymbol'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'US$</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">8.05</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-26">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'bestPriceInSurferCurrencyWithCurrencySymbol'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'US$</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">8.05</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-27">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'shippingToDestinationPriceInPurchaseCurrencyWithCurrencySymbol'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'US$</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.00</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-28">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'shippingToDestinationPriceInSurferCurrencyWithCurrencySymbol'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'US$</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.00</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-29">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'shippingDestinationNameInSurferLanguage'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'U.S.A.'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-30">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'vendorCountryNameInSurferLanguage'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'U.S.A.'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-31">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'vendorId'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">51315977</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-32">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'bestPriceInPurchaseCurrencyValueOnly'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">8.05</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-33">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'bestShippingToDestinationPriceInPurchaseCurrencyValueOnly'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.00</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-34">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'purchaseCurrencySymbol'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'US$'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-35">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'refinementList'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-36">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'internationalEdition'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">False</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-37">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'bookCondition'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'Good'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-38">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'bookDescription'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'Former</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">library</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">book;</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">may</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">include...'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-39">  <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'freeShipping'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">True</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">},</span></span>
<span id="cb5-40"> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'pricingInfoForBestAllConditions'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-41"> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'isbn'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9781250297662</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-42"> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'totalResults'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">18</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-43"> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'containerId'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'pricingService</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">-9781250297662</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-44"> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'refinementList'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">[</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'name'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'collectibleSigned'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-45">   <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'label'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'Signed'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-46">   <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'count'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-47">   <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'url'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'attrs=sgnd&amp;ds=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">&amp;isbn=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9781250297662</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">&amp;sgnd=on&amp;sortby=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">17</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-48">   <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'soutaRequest'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'debug'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-49">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'rollup'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-50">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'deep'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-51">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'facets'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">True</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-52">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'bsaExpandedFacets'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-53">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'strict'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-54">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'shippingDestination'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'USA'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-55">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'shippingMode'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-56">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'currency'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'USD'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-57">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'clientId'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-58">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'sort'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'TOTAL_PRICE_ASC'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-59">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'pageSize'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-60">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'pageDescriptor'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-61">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'featureFlags'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-62">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'query'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'domain'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'COM'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-63">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'booleanQuery'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-64">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'isbns'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">[</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'isbn13'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">True</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'isbn10'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">False</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">]</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-65">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'contributor'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-66">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'title'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-67">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'publisher'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-68">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'keyword'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-69">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'minYearPublished'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-70">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'maxYearPublished'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-71">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'minPrice'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-72">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'maxPrice'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-73">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'createdWithin'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-74">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'minCreatedTimestamp'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-75">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'maxCreatedTimestamp'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-76">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'includedLanguages'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-77">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'includedProductTypes'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-78">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'requiredAttributes'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">[</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'SIGNED'</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">]</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-79">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'includedConditions'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-80">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'requiredBsaCodes'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-81">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'requiredFreeShippingCountries'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-82">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'minSellerRating'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-83">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'sellerProvState'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-84">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'sellerCountry'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-85">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'includedSellerRegions'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-86">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'sellerCatalog'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-87">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'requiredSellerGroups'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-88">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'includedSellers'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-89">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'excludedSellers'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-90">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'includedListingIds'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-91">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'excludeSellerPictures'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}}}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-92">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'name'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'collectibleJacket'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-93">   <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'label'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'Dust</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Jacket'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-94">   <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'count'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-95">   <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'url'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'attrs=dj&amp;dj=on&amp;ds=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">&amp;isbn=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9781250297662</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">&amp;sortby=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">17</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-96">   <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'soutaRequest'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'debug'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-97">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'rollup'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-98">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'deep'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-99">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'facets'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">True</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-100">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'bsaExpandedFacets'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-101">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'strict'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-102">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'shippingDestination'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'USA'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-103">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'shippingMode'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-104">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'currency'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'USD'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-105">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'clientId'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-106">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'sort'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'TOTAL_PRICE_ASC'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-107">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'pageSize'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-108">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'pageDescriptor'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-109">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'featureFlags'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-110">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'query'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'domain'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'COM'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-111">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'booleanQuery'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-112">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'isbns'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">[</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'isbn13'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">True</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'isbn10'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">False</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">]</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-113">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'contributor'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-114">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'title'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-115">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'publisher'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-116">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'keyword'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-117">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'minYearPublished'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-118">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'maxYearPublished'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-119">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'minPrice'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-120">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'maxPrice'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-121">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'createdWithin'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-122">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'minCreatedTimestamp'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-123">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'maxCreatedTimestamp'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-124">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'includedLanguages'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-125">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'includedProductTypes'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-126">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'requiredAttributes'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">[</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'JACKET'</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">]</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-127">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'includedConditions'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-128">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'requiredBsaCodes'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-129">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'requiredFreeShippingCountries'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-130">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'minSellerRating'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-131">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'sellerProvState'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-132">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'sellerCountry'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-133">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'includedSellerRegions'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-134">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'sellerCatalog'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-135">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'requiredSellerGroups'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-136">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'includedSellers'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-137">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'excludedSellers'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-138">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'includedListingIds'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-139">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'excludeSellerPictures'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}}}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-140">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'name'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'bindingHard'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-141">   <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'label'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'Hardcover'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-142">   <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'count'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">18</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-143">   <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'url'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'attrs=hc&amp;bi=h&amp;ds=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">&amp;isbn=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9781250297662</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">&amp;sortby=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">17</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-144">   <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'soutaRequest'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'debug'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-145">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'rollup'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-146">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'deep'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-147">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'facets'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">True</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-148">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'bsaExpandedFacets'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-149">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'strict'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-150">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'shippingDestination'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'USA'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-151">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'shippingMode'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-152">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'currency'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'USD'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-153">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'clientId'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-154">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'sort'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'TOTAL_PRICE_ASC'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-155">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'pageSize'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-156">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'pageDescriptor'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-157">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'featureFlags'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-158">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'query'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'domain'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'COM'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-159">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'booleanQuery'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-160">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'isbns'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">[</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'isbn13'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">True</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'isbn10'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">False</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">]</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-161">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'contributor'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-162">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'title'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-163">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'publisher'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-164">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'keyword'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-165">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'minYearPublished'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-166">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'maxYearPublished'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-167">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'minPrice'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-168">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'maxPrice'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-169">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'createdWithin'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-170">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'minCreatedTimestamp'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-171">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'maxCreatedTimestamp'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-172">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'includedLanguages'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-173">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'includedProductTypes'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-174">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'requiredAttributes'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">[</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'HARDCOVER'</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">]</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-175">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'includedConditions'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-176">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'requiredBsaCodes'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-177">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'requiredFreeShippingCountries'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-178">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'minSellerRating'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-179">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'sellerProvState'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-180">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'sellerCountry'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-181">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'includedSellerRegions'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-182">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'sellerCatalog'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-183">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'requiredSellerGroups'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-184">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'includedSellers'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-185">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'excludedSellers'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-186">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'includedListingIds'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-187">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'excludeSellerPictures'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}}}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-188">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'name'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'collectibleFirstEdition'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-189">   <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'label'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'First</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Edition'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-190">   <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'count'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-191">   <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'url'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'attrs=fe&amp;ds=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">&amp;fe=on&amp;isbn=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9781250297662</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">&amp;sortby=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">17</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-192">   <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'soutaRequest'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'debug'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-193">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'rollup'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-194">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'deep'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-195">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'facets'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">True</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-196">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'bsaExpandedFacets'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-197">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'strict'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-198">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'shippingDestination'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'USA'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-199">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'shippingMode'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-200">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'currency'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'USD'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-201">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'clientId'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-202">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'sort'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'TOTAL_PRICE_ASC'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-203">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'pageSize'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-204">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'pageDescriptor'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-205">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'featureFlags'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-206">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'query'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'domain'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'COM'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-207">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'booleanQuery'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-208">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'isbns'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">[</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'isbn13'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">True</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'isbn10'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">False</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">]</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-209">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'contributor'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-210">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'title'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-211">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'publisher'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-212">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'keyword'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-213">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'minYearPublished'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-214">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'maxYearPublished'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-215">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'minPrice'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-216">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'maxPrice'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-217">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'createdWithin'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-218">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'minCreatedTimestamp'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-219">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'maxCreatedTimestamp'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-220">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'includedLanguages'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-221">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'includedProductTypes'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-222">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'requiredAttributes'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">[</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'FIRST_EDITION'</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">]</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-223">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'includedConditions'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-224">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'requiredBsaCodes'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-225">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'requiredFreeShippingCountries'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-226">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'minSellerRating'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-227">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'sellerProvState'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-228">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'sellerCountry'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-229">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'includedSellerRegions'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-230">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'sellerCatalog'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-231">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'requiredSellerGroups'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-232">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'includedSellers'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-233">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'excludedSellers'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-234">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'includedListingIds'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-235">     <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'excludeSellerPictures'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}}}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">]</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-236"> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'bibliographicDetail'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div></div>
<p>In our example, we have 6 results and the best price for a new book <code>bestPriceInPurchaseCurrencyWithCurrencySymbol</code> is $28.07, and the best price for a used book is $8.05.</p>
</section>
<section id="sending-a-get-request" class="level3">
<h3 class="anchored" data-anchor-id="sending-a-get-request">Sending a GET request</h3>
<p>The API also has a GET method for obtaining book recommendations given an ISBN. The url and parameter names are different, but the way we send the request is very similar:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1">url <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://www.abebooks.com/servlet/RecommendationsApi"</span></span></code></pre></div></div>
<div class="table-responsive">
<table class="table-bordered table-striped caption-top table">
<caption>Get recommended books from an ISBN</caption>
<thead>
<tr class="header">
<th style="text-align: left;">Parameter</th>
<th style="text-align: left;">Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">pageId</td>
<td style="text-align: left;">plp</td>
</tr>
<tr class="even">
<td style="text-align: left;">itemIsbn13</td>
<td style="text-align: left;"><strong>isbn</strong></td>
</tr>
</tbody>
</table>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Get book recommendations by ISBN</span></span>
<span id="cb7-2">payload <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'pageId'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'plp'</span>,</span>
<span id="cb7-3">           <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'itemIsbn13'</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9781250297662</span>}</span>
<span id="cb7-4"></span>
<span id="cb7-5">resp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> requests.get(url, params<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>payload)</span>
<span id="cb7-6"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(resp.status_code, resp.reason)</span>
<span id="cb7-7">resp.json()</span></code></pre></div></div>
<p>Response:</p>
<pre><code>200 OK</code></pre>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode json code-with-copy"><code class="sourceCode json"><span id="cb9-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'widgetResponses'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">[</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'slotName'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'detail</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">-1</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-2">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'title'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'Customers</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">who</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">bought</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">this</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">item</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">also</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">bought'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-3">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'algoName'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'abeBooksBlendedPurchaseSims'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-4">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'ref'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'pd_b_p_</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-5">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'recommendationItems'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">[</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'attributes'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">[]</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-6">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'thumbNailImgUrl'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'https://pictures.abebooks.com/isbn/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9780765384201</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">-us</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">-300</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">.jpg'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-7">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'itemLink'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'/products/isbn/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9780765384201</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">?cm_sp=rec-_-pd_b_p_</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">-_-plp&amp;reftag=pd_b_p_</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-8">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'subTitle'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-9">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'isbn13'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9780765384201</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-10">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'title'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'Invisible</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Planets:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Contemporary</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Chinese</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Science</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Fiction...'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-11">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'author'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'Liu</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ken'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-12">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'attributes'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">[]</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-13">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'thumbNailImgUrl'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'https://pictures.abebooks.com/isbn/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9781250306029</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">-us</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">-300</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">.jpg'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-14">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'itemLink'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'/products/isbn/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9781250306029</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">?cm_sp=rec-_-pd_b_p_</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">-_-plp&amp;reftag=pd_b_p_</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-15">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'subTitle'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-16">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'isbn13'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9781250306029</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-17">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'title'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'The</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Redemption</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">of</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Time:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">A</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Three-Body</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Problem</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Novel...'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-18">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'author'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'Baoshu'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-19">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'attributes'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">[]</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-20">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'thumbNailImgUrl'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'https://pictures.abebooks.com/isbn/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9780765389312</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">-us</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">-300</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">.jpg'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-21">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'itemLink'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'/products/isbn/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9780765389312</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">?cm_sp=rec-_-pd_b_p_</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">-_-plp&amp;reftag=pd_b_p_</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-22">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'subTitle'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-23">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'isbn13'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9780765389312</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-24">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'title'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'Waste</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Tide'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-25">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'author'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'Qiufan</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Chen'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-26">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'attributes'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">[]</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-27">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'thumbNailImgUrl'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'https://pictures.abebooks.com/isbn/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9780765384195</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">-us</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">-300</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">.jpg'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-28">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'itemLink'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'/products/isbn/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9780765384195</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">?cm_sp=rec-_-pd_b_p_</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">-_-plp&amp;reftag=pd_b_p_</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-29">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'subTitle'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-30">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'isbn13'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9780765384195</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-31">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'title'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'Invisible</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Planets:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Contemporary</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Chinese</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Science</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Fiction...'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-32">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'author'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'Liu</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ken'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-33">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'attributes'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">[]</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-34">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'thumbNailImgUrl'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'https://pictures.abebooks.com/isbn/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9781784978518</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">-us</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">-300</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">.jpg'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-35">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'itemLink'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'/products/isbn/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9781784978518</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">?cm_sp=rec-_-pd_b_p_</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">-_-plp&amp;reftag=pd_b_p_</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-36">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'subTitle'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-37">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'isbn13'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9781784978518</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-38">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'title'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'The</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Wandering</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Earth'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-39">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'author'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'Liu</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Cixin'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">]</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-40">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'slotName'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'ext-search-detail</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">-1</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-41">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'title'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">None</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-42">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'algoName'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'heroWidgetIsbnSims'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-43">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'ref'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'pd_hw_i_</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-44">    <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'recommendationItems'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">[</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'attributes'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">[]</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-45">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'thumbNailImgUrl'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'https://pictures.abebooks.com/isbn/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9780804172448</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">-us</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">-300</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">.jpg'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-46">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'itemLink'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'/products/isbn/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9780804172448</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">?cm_sp=rec-_-pd_hw_i_</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">-_-plp&amp;reftag=pd_hw_i_</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-47">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'subTitle'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'Best</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Selling'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-48">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'isbn13'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9780804172448</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-49">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'title'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'Station</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Eleven'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-50">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'author'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'Mandel</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Emily</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">St.</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">John'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-51">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'attributes'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">[]</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-52">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'thumbNailImgUrl'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'https://pictures.abebooks.com/isbn/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9781786073495</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">-us</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">-300</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">.jpg'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-53">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'itemLink'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'/products/isbn/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9781786073495</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">?cm_sp=rec-_-pd_hw_i_</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">-_-plp&amp;reftag=pd_hw_i_</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-54">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'subTitle'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'Top</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Rated'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-55">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'isbn13'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9781786073495</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-56">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'title'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'Zuleikha'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-57">        <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'author'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">'Yakhina</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">Guzel'</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">]</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">]</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div></div>
</section>
</section>
<section id="an-object-oriented-module" class="level2">
<h2 class="anchored" data-anchor-id="an-object-oriented-module">An Object-Oriented Module</h2>
<p>I created a small Python module <a href="https://github.com/ravila4/abebooks">abebooks.py</a> to encapsulate the requests. The full code is below:</p>
<div id="fd15dd8f" class="cell" data-execution_count="1">
<details class="code-fold">
<summary>Show the code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> requests</span>
<span id="cb10-2"></span>
<span id="cb10-3"></span>
<span id="cb10-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> AbeBooks:</span>
<span id="cb10-5"></span>
<span id="cb10-6">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> __get_price(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, payload):</span>
<span id="cb10-7">        url <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://www.abebooks.com/servlet/DWRestService/pricingservice"</span></span>
<span id="cb10-8">        resp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> requests.post(url, data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>payload)</span>
<span id="cb10-9">        resp.raise_for_status()</span>
<span id="cb10-10">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> resp.json()</span>
<span id="cb10-11"></span>
<span id="cb10-12">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> __get_recomendations(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, payload):</span>
<span id="cb10-13">        url <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://www.abebooks.com/servlet/RecommendationsApi"</span></span>
<span id="cb10-14">        resp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> requests.get(url, params<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>payload)</span>
<span id="cb10-15">        resp.raise_for_status()</span>
<span id="cb10-16">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> resp.json()</span>
<span id="cb10-17"></span>
<span id="cb10-18">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> getPriceByISBN(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, isbn):</span>
<span id="cb10-19">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb10-20"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        Parameters</span></span>
<span id="cb10-21"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        ----------</span></span>
<span id="cb10-22"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        isbn (int) - a book's ISBN code</span></span>
<span id="cb10-23"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        """</span></span>
<span id="cb10-24">        payload <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'action'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'getPricingDataByISBN'</span>,</span>
<span id="cb10-25">                   <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'isbn'</span>: isbn,</span>
<span id="cb10-26">                   <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'container'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'pricingService-</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">format</span>(isbn)}</span>
<span id="cb10-27">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.__get_price(payload)</span>
<span id="cb10-28"></span>
<span id="cb10-29">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> getPriceByAuthorTitle(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, author, title):</span>
<span id="cb10-30">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb10-31"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        Parameters</span></span>
<span id="cb10-32"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        ----------</span></span>
<span id="cb10-33"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        author (str) - book author</span></span>
<span id="cb10-34"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        title (str) - book title</span></span>
<span id="cb10-35"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        """</span></span>
<span id="cb10-36">        payload <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'action'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'getPricingDataForAuthorTitleStandardAddToBasket'</span>,</span>
<span id="cb10-37">                   <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'an'</span>: author,</span>
<span id="cb10-38">                   <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tn'</span>: title,</span>
<span id="cb10-39">                   <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'container'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'oe-search-all'</span>}</span>
<span id="cb10-40">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.__get_price(payload)</span>
<span id="cb10-41"></span>
<span id="cb10-42">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> getPriceByAuthorTitleBinding(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, author, title, binding):</span>
<span id="cb10-43">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb10-44"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        Parameters</span></span>
<span id="cb10-45"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        ----------</span></span>
<span id="cb10-46"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        author (str) - book author</span></span>
<span id="cb10-47"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        title (str) - book title</span></span>
<span id="cb10-48"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        binding(str) - one of 'hard', or 'soft'</span></span>
<span id="cb10-49"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        """</span></span>
<span id="cb10-50">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> binding <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"hard"</span>:</span>
<span id="cb10-51">            container <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"priced-from-hard"</span></span>
<span id="cb10-52">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elif</span> binding <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"soft"</span>:</span>
<span id="cb10-53">            container <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"priced-from-soft"</span></span>
<span id="cb10-54">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb10-55">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ValueError</span>(</span>
<span id="cb10-56">                    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Invalid parameter. Binding must be "hard" or "soft"'</span>)</span>
<span id="cb10-57">        payload <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'action'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'getPricingDataForAuthorTitleBindingRefinements'</span>,</span>
<span id="cb10-58">                   <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'an'</span>: author,</span>
<span id="cb10-59">                   <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tn'</span>: title,</span>
<span id="cb10-60">                   <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'container'</span>: container}</span>
<span id="cb10-61">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.__get_price(payload)</span>
<span id="cb10-62"></span>
<span id="cb10-63">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> getRecommendationsByISBN(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, isbn):</span>
<span id="cb10-64">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb10-65"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        Parameters</span></span>
<span id="cb10-66"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        ----------</span></span>
<span id="cb10-67"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        isbn (int) - a book's ISBN code</span></span>
<span id="cb10-68"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        """</span></span>
<span id="cb10-69">        payload <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'pageId'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'plp'</span>,</span>
<span id="cb10-70">                   <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'itemIsbn13'</span>: isbn}</span>
<span id="cb10-71">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.__get_recomendations(payload)</span></code></pre></div></div>
</details>
</div>
<section id="using-the-abebooks-module" class="level3">
<h3 class="anchored" data-anchor-id="using-the-abebooks-module">Using the AbeBooks Module</h3>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> abebooks <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> AbeBooks</span>
<span id="cb11-2"></span>
<span id="cb11-3">ab <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> AbeBooks()</span>
<span id="cb11-4">results <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ab.getPriceByISBN(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9780062941503</span>)</span>
<span id="cb11-5"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> results[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'success'</span>]:</span>
<span id="cb11-6">    best_new <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> results[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'pricingInfoForBestNew'</span>]</span>
<span id="cb11-7">    best_used <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> results[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'pricingInfoForBestUsed'</span>]</span></code></pre></div></div>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Best New Price</span></span>
<span id="cb12-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(best_new[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bestPriceInPurchaseCurrencyWithCurrencySymbol'</span>])</span></code></pre></div></div>
<pre><code>US$ 21.49</code></pre>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Best Used Price</span></span>
<span id="cb14-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(best_used[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bestPriceInPurchaseCurrencyWithCurrencySymbol'</span>])</span></code></pre></div></div>
<pre><code>US$ 24.42</code></pre>


</section>
</section>

 ]]></description>
  <category>Python</category>
  <category>API</category>
  <category>books</category>
  <guid>https://ravila.dev/posts/2020-04-10-reverse-engineering-abebooks-api/</guid>
  <pubDate>Fri, 10 Apr 2020 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Interweaving R and Python with Reticulate and Apache Arrow</title>
  <link>https://ravila.dev/posts/2019-05-04-interweaving-r-and-python/</link>
  <description><![CDATA[ 






<p>Python is fantastic for general data manipulation, but I find that R excells at data visualization, and its large array of specialized statistical libraries. Since both of these ecosystems have their strengths, I often find myself wanting to combine features of both in a single workflow. Nevertheless, I want to avoid the task of having to write duplicate data munging operations in both languages.</p>
<p>Below, I’ll demonstrate how to use:</p>
<ul>
<li>Reticulate to call Python code from R (and pass objects between them)</li>
<li>Apache Arrow for fast, language-agnostic data sharing between the two languages</li>
</ul>
<p>I’m using the mtcars dataset for some examples because it’s small, but at the end, we’ll discuss how Arrow helps when data sets are large, where copying everything in memory repeatedly is no longer practical.</p>
<section id="reticulate" class="level2">
<h2 class="anchored" data-anchor-id="reticulate">Reticulate</h2>
<section id="what-is-reticulate" class="level3">
<h3 class="anchored" data-anchor-id="what-is-reticulate">What is Reticulate?</h3>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://rstudio.github.io/reticulate/reference/figures/reticulated_python.png" class="img-fluid quarto-figure quarto-figure-center figure-img" width="300"></p>
</figure>
</div>
<p>Reticulate is an R package that provides a Python interface for R. It allows R users to share objects between R and Python sessions.</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Reticulate is especially powerful in <a href="https://quarto.org/docs/get-started/">Quarto</a>, which supports both R and Python chunks natively in the same document, and works with any text editor. <sup>1</sup> This is the setup I am using to write this blog.</p>
</div>
</div>
<p>Installing the reticulate package in R:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">install.packages</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"reticulate"</span>)</span></code></pre></div></div>
<p>Loading the reticulate library:</p>
<div class="cell">
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>R Code</strong></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(reticulate)</span></code></pre></div></div>
</div>
</div>
</section>
<section id="a-quick-pythonr-integration-example" class="level3">
<h3 class="anchored" data-anchor-id="a-quick-pythonr-integration-example">A Quick Python–R Integration Example</h3>
<p>Let’s create some simple Python arrays and plot them:</p>
<div class="cell">
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>Python Code</strong></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="cb3-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb3-3"></span>
<span id="cb3-4">x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.array([<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>])</span>
<span id="cb3-5">y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.exp2(x)</span>
<span id="cb3-6"></span>
<span id="cb3-7">plt.plot(x, y)</span>
<span id="cb3-8">plt.show()</span></code></pre></div></div>
</div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ravila.dev/posts/2019-05-04-interweaving-r-and-python/index_files/figure-html/array-from-python-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<p>Because I am using Quarto, we can call Python code directly in the same notebook as R code. However in a traditional R script we would call Python code like this:</p>
<div class="cell">
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>R Code</strong></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">np <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">import</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"numpy"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"np"</span>)</span>
<span id="cb4-2">x <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> np<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">array</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>))</span>
<span id="cb4-3">y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> np<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp2</span>(x)</span></code></pre></div></div>
</div>
</div>
<p>Or alternatively,</p>
<div class="cell">
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>R Code</strong></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">py_run_string</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb5-2"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">import numpy as np</span></span>
<span id="cb5-3"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">x = np.array([1,2,3,4,5])</span></span>
<span id="cb5-4"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">y = np.exp2(x)</span></span>
<span id="cb5-5"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
</div>
</div>
<p>Or, if we want to run an entire Python script:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">py_run_file</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"python_script.py"</span>)</span></code></pre></div></div>
<p>Finally, we can access these same Python objects from inside an R code cell:</p>
<div class="cell">
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>R Code</strong></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plotting the same arrays in R! So simple!</span></span>
<span id="cb7-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(py<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>x, py<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>y)</span></code></pre></div></div>
</div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ravila.dev/posts/2019-05-04-interweaving-r-and-python/index_files/figure-html/array-from-r-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<p>In this example, we created Python arrays and visualized them with both Python’s Matplotlib and R’s plotting system. The <code>py$</code> syntax accesses Python objects from within R, allowing for seamless interoperation.</p>
</section>
<section id="accessing-r-objects-from-python" class="level3">
<h3 class="anchored" data-anchor-id="accessing-r-objects-from-python">Accessing R objects from Python</h3>
<p>For accessing R objects from Python, we can use the <code>r.</code> prefix. Here we load the mtcars dataset in R and access it from Python’s Pandas library, where we use SciKit Learn to apply a data transformation:</p>
<div class="cell">
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>R Code</strong></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data</span>(mtcars)</span></code></pre></div></div>
</div>
</div>
<div class="cell">
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>Python Code</strong></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-9" style="background: #f1f3f5;"><pre class="sourceCode python code-annotation-code code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-9-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Python Code</span></span>
<span id="annotated-cell-9-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pandas <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> pd</span>
<span id="annotated-cell-9-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="annotated-cell-9-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.preprocessing <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> StandardScaler</span>
<span id="annotated-cell-9-5"></span>
<span id="annotated-cell-9-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Access mtcars from R and do some Python-specific analysis</span></span>
<span id="annotated-cell-9-7">mtcars_py <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> r.mtcars</span>
<span id="annotated-cell-9-8"></span>
<span id="annotated-cell-9-9">numeric_cols <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mpg'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'disp'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'hp'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'drat'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'wt'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'qsec'</span>]</span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-9" data-target-annotation="1">1</button><span id="annotated-cell-9-10" class="code-annotation-target">scaler <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> StandardScaler()</span>
<span id="annotated-cell-9-11">mtcars_py[numeric_cols] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> scaler.fit_transform(mtcars_py[numeric_cols])</span>
<span id="annotated-cell-9-12">mtcars_py.head()</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</div>
<div class="cell-annotation">
<dl class="code-annotation-container-hidden code-annotation-container-grid">
<dt data-target-cell="annotated-cell-9" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-9" data-code-lines="10,11" data-code-annotation="1">Standarizing numeric columns with scikit-learns’s <code>StandardScaler</code></span>
</dd>
</dl>
</div>
<div class="cell-output cell-output-stdout">
<pre><code>                        mpg  cyl      disp        hp  ...   vs   am  gear  carb
Mazda RX4          0.153299  6.0 -0.579750 -0.543655  ...  0.0  1.0   4.0   4.0
Mazda RX4 Wag      0.153299  6.0 -0.579750 -0.543655  ...  0.0  1.0   4.0   4.0
Datsun 710         0.456737  4.0 -1.006026 -0.795570  ...  1.0  1.0   4.0   1.0
Hornet 4 Drive     0.220730  6.0  0.223615 -0.543655  ...  1.0  0.0   3.0   1.0
Hornet Sportabout -0.234427  8.0  1.059772  0.419550  ...  0.0  0.0   3.0   2.0

[5 rows x 11 columns]</code></pre>
</div>
</div>
<div class="callout callout-style-default callout-warning callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Warning
</div>
</div>
<div class="callout-body-container callout-body">
<p>A downside of this approach is that it is slow for large datasets, as we are creating a copy of the object in memory when we pass it from R to Python, or vice-versa.</p>
<p>Another caveat is that some Python objects do not map directly to R objects, so we may need to convert them. For example, a Pandas DataFrame in Python is not directly convertible to an R data frame. However, we can convert it to a dictionary and then to an R data frame.</p>
</div>
</div>
<p>Accessing our transformed mtcars DataFrame from R:</p>
<div class="cell">
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>Python Code</strong></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Convert the Pandas dataframe to a dictionary</span></span>
<span id="cb10-2">mtcars_dict <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> mtcars_py.to_dict(orient<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'list'</span>)</span></code></pre></div></div>
</div>
</div>
<div class="cell">
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>R Code</strong></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb11-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb11-2"></span>
<span id="cb11-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Convert the dictionary to an R data frame</span></span>
<span id="cb11-4">standardized_data <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(py<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>mtcars_dict)</span>
<span id="cb11-5"></span>
<span id="cb11-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(standardized_data, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> wt, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> mpg, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>(cyl))) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_minimal</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb11-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Standardized Weight vs MPG by Cylinders"</span>,</span>
<span id="cb11-10">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Standardized Weight"</span>,</span>
<span id="cb11-11">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Standardized MPG"</span>,</span>
<span id="cb11-12">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Cylinders"</span>)</span></code></pre></div></div>
</div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ravila.dev/posts/2019-05-04-interweaving-r-and-python/index_files/figure-html/mtcars-ggplot-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<p>A more efficient way to share data between R and Python is to use Apache Arrow which we will discuss next.</p>
</section>
</section>
<section id="using-apache-arrow-for-large-data-interchange" class="level2">
<h2 class="anchored" data-anchor-id="using-apache-arrow-for-large-data-interchange">Using Apache Arrow for Large Data Interchange</h2>
<p>For sharing large datasets, you might want to consider <a href="https://arrow.apache.org/">Apache Arrow</a>. Arrow provides a language-agnostic columnar memory format, enabling fast data exchange between R, Python, and other systems.</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>In Python, we can install the pyarrow package with <code>pip install pyarrow</code>, and in R, we can install the arrow package with <code>install.packages("arrow")</code>.</p>
</div>
</div>
<section id="in-memory-data-sharing-with-arrow" class="level3">
<h3 class="anchored" data-anchor-id="in-memory-data-sharing-with-arrow">In-memory data sharing with Arrow</h3>
<p>We can always use Arrow to write out a Parquet file and read it in in another language, but in cases where we want to avoid IO, we can combine Arrow with reticulate (or rpy2!) to share data between R and Python directly in memory. For example, we can read the mtcars dataset into an Arrow table in R and then read it from Python:</p>
<div class="cell">
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>R Code</strong></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-12" style="background: #f1f3f5;"><pre class="sourceCode r code-annotation-code code-with-copy code-annotated"><code class="sourceCode r"><button class="code-annotation-anchor" data-target-cell="annotated-cell-12" data-target-annotation="1">1</button><span id="annotated-cell-12-1" class="code-annotation-target"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">suppressPackageStartupMessages</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(arrow))</span>
<span id="annotated-cell-12-2"></span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-12" data-target-annotation="2">2</button><span id="annotated-cell-12-3" class="code-annotation-target">mtcars_arrow <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">arrow_table</span>(mtcars)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</div>
<div class="cell-annotation">
<dl class="code-annotation-container-hidden code-annotation-container-grid">
<dt data-target-cell="annotated-cell-12" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-12" data-code-lines="1" data-code-annotation="1">Silencing some package startup messages when loading the arrow library</span>
</dd>
<dt data-target-cell="annotated-cell-12" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-12" data-code-lines="3" data-code-annotation="2">Converting the mtcars dataset to an Arrow table</span>
</dd>
</dl>
</div>
</div>
<p>Accessing the mtcars Arrow dataset from Python:</p>
<div class="cell">
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>Python Code</strong></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pyarrow <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> pa</span>
<span id="cb12-2"></span>
<span id="cb12-3">mtcars_py <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> r.mtcars_arrow</span>
<span id="cb12-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># An aggregation example in pyarrow</span></span>
<span id="cb12-5">mtcars_py.group_by(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'cyl'</span>).aggregate([(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mpg'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mean'</span>)]).to_pandas()</span></code></pre></div></div>
</div>
<div class="cell-output cell-output-stdout">
<pre><code>   cyl   mpg_mean
0  6.0  19.742857
1  4.0  26.663636
2  8.0  15.100000</code></pre>
</div>
</div>
<p>Conversely, if we have a Pandas DataFrame in Python, we can convert it to an Arrow table and access it from R:</p>
<div class="cell">
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>Python Code</strong></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Convert a Pandas DataFrame to an Arrow table</span></span>
<span id="cb14-2">df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'a'</span>: [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'b'</span>: [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>]})</span>
<span id="cb14-3">table <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pa.Table.from_pandas(df)</span></code></pre></div></div>
</div>
</div>
<div class="cell">
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>R Code</strong></pre>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-15" style="background: #f1f3f5;"><pre class="sourceCode r code-annotation-code code-with-copy code-annotated"><code class="sourceCode r"><span id="annotated-cell-15-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Access the arrow table from R</span></span>
<span id="annotated-cell-15-2">df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> py<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>table</span>
<button class="code-annotation-anchor" data-target-cell="annotated-cell-15" data-target-annotation="1">1</button><span id="annotated-cell-15-3" class="code-annotation-target"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.data.frame</span>(df)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
</div>
<div class="cell-annotation">
<dl class="code-annotation-container-hidden code-annotation-container-grid">
<dt data-target-cell="annotated-cell-15" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-15" data-code-lines="3" data-code-annotation="1">Not always necessary, but we can convert the Arrow table to an R data frame</span>
</dd>
</dl>
</div>
<div class="cell-output cell-output-stdout">
<pre><code>  a b
1 1 4
2 2 5
3 3 6</code></pre>
</div>
</div>
<p>The advantage of using Arrow is that the object representation remains the same between R and Python (and other languages that implement the format), so we avoid the overhead of copying the data. We are simply passing a reference to the same object in memory and updating the metadata.</p>
</section>
</section>
<section id="wrapping-up" class="level2">
<h2 class="anchored" data-anchor-id="wrapping-up">Wrapping up</h2>
<p>Reticulate makes interfacing Python and R code nearly seamless, especially when working in a Quarto notebook, and with the addition of Apache Arrow, we can efficiently share large datasets between the two languages.</p>
<p>However, while Reticulate works great if you are working in an R-based environment, it is also common to start out in a Python environment and have need of an R library (e.g., a Bioconductor package or plotting function). In such cases, we can use <a href="https://rpy2.github.io/">rpy2</a>, a Python package that provides an interface to call R code from Python. Additionally, <a href="https://rpy2.github.io/rpy2-arrow/version/main/html/index.html">rpy2-arrow</a> provides an extension for using Apache Arrow with rpy2. It would probably make this blog post too long to cover rpy2 in detail, but this blog did an excellent job of explaining how to use it: <a href="https://blog.djnavarro.net/posts/2022-09-16_arrow-and-rpy2/">Data transfer between Python and R with rpy2 and Apache Arrow</a>.</p>
<p>I am excited to try out these workflows more extensively, and leverage some of the strengths of both languages via some Franken-pipelines! What are your favorite use cases for combining Python and R?</p>
</section>
<section id="references-and-further-reading" class="level2">
<h2 class="anchored" data-anchor-id="references-and-further-reading">References and Further Reading</h2>
<ul>
<li><a href="https://arrow.apache.org/cookbook/r/creating-arrow-objects.html">Apache Arrow R Cookbook</a></li>
<li><a href="https://blog.djnavarro.net/posts/2022-09-16_arrow-and-rpy2/">Data transfer between Python and R with rpy2 and Apache Arrow</a>.</li>
<li><a href="https://rviews.rstudio.com/2022/05/25/calling-r-from-python-with-rpy2/">Calling R from Python with rpy2</a></li>
</ul>


<!-- -->

</section>


<div id="quarto-appendix" class="default"><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>

<ol>
<li id="fn1"><p>Nowadays, I do most of my coding in VS Code for both R and Python.↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>Python</category>
  <category>Rstats</category>
  <category>dataviz</category>
  <guid>https://ravila.dev/posts/2019-05-04-interweaving-r-and-python/</guid>
  <pubDate>Sat, 04 May 2019 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Mapping Pharos Targets with Structures</title>
  <link>https://ravila.dev/posts/2019-02-14-mapping-pharos-to-pdb/</link>
  <description><![CDATA[ 






<p>A common goal in early drug discovery is to prioritize targets that not only have known active compounds but also have experimentally determined protein structures in the Protein Data Bank (PDB). This sets the stage for more in-depth analyses such as structure-based drug design (SBDD) and structure-activity relationship (SAR).</p>
<p>Here, we combine two key data sources:</p>
<ol type="1">
<li><a href="https://pharos.nih.gov/">Pharos/TCRD (Target Central Resource Database)</a> – an NIH-funded knowledgebase containing data for human targets, their associated ligands/compounds, and many annotations such as gene families and drug development levels (Tclin, Tchem, etc.).</li>
<li><a href="https://www.ebi.ac.uk/pdbe/docs/sifts/">SIFTS (Structure Integration with Function, Taxonomy and Sequence)</a> – the EBI’s resource mapping UniProt accessions to PDB structures, as well as other databases such as GO, InterPro, Pfam, CATH, SCOP, and PubMed.</li>
</ol>
<p>By merging these data, we can quickly identify human protein targets that (A) meet a minimum threshold of known active compounds (≥15 in this example), and (B) have PDB structures available for structure-based work.</p>
<p>Below is a brief, self-contained workflow that:</p>
<ul>
<li>Connects to Pharos via MySQL to retrieve targets in the <a href="http://juniper.health.unm.edu/tcrd/">Tclin/Tchem</a> development levels.</li>
<li>Collects compound-activity counts.</li>
<li>Retrieves UniProt-PDB mappings from SIFTS.</li>
<li>Joins the data, flags targets that have ≥15 active compounds and at least one PDB structure.</li>
<li>Explores target families and visualizes the final set.</li>
</ul>
<p>You can adapt this workflow to explore deeper aspects of SAR, binding modes, or structure-based design.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ravila.dev/posts/2019-02-14-mapping-pharos-to-pdb/images/sift.png" class="img-fluid figure-img" style="width:80.0%"></p>
<figcaption>SIFTS provides residue-level mappings between PDBe, UniProt, and several other annotation resources</figcaption>
</figure>
</div>
<section id="getting-target-data-from-pharos" class="level2">
<h2 class="anchored" data-anchor-id="getting-target-data-from-pharos">Getting Target Data from Pharos</h2>
<p>First, we connect to the Pharos database with the help of SQLAlchemy and read the necessary tables into Pandas DataFrames.</p>
<div id="42d42b1e" class="cell" data-execution_count="1">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pandas <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> pd</span>
<span id="cb1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sqlalchemy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> create_engine</span>
<span id="cb1-3"></span>
<span id="cb1-4">connection_string <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mysql+mysqlconnector://tcrd@tcrd.kmc.io/tcrd540"</span></span>
<span id="cb1-5">engine <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> create_engine(connection_string)</span>
<span id="cb1-6"></span>
<span id="cb1-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Get targets in Tclin and Tchem</span></span>
<span id="cb1-8">query_target <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb1-9"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">  SELECT id, name, tdl, fam, famext</span></span>
<span id="cb1-10"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">  FROM target</span></span>
<span id="cb1-11"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">  WHERE tdl IN ('Tclin','Tchem')</span></span>
<span id="cb1-12"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb1-13">target <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.read_sql(query_target, con<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>engine)</span>
<span id="cb1-14"></span>
<span id="cb1-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Get Uniprot ids</span></span>
<span id="cb1-16">query_protein <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SELECT id, uniprot, family FROM protein"</span></span>
<span id="cb1-17">protein <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.read_sql(query_protein, con<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>engine)</span>
<span id="cb1-18"></span>
<span id="cb1-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Get compound activities</span></span>
<span id="cb1-20">query_cmpd_activity <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb1-21"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">  SELECT id, target_id, act_value</span></span>
<span id="cb1-22"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">  FROM cmpd_activity</span></span>
<span id="cb1-23"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb1-24"></span>
<span id="cb1-25">cmpd_activity <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.read_sql(query_cmpd_activity, con<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>engine)</span></code></pre></div></div>
</div>
<p>Here are the datasets that we obtained:</p>
<div class="cell" data-execution_count="2">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1">target.head()</span></code></pre></div></div>
<div id="tbl-target" class="cell quarto-float quarto-figure quarto-figure-center anchored" data-execution_count="2">
<figure class="quarto-float quarto-float-tbl figure">
<figcaption class="quarto-float-caption-top quarto-float-caption quarto-float-tbl" id="tbl-target-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Table&nbsp;1: Targets
</figcaption>
<div aria-describedby="tbl-target-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<div class="cell-output cell-output-display" data-execution_count="2">
<div>


<table class="dataframe do-not-create-environment cell caption-top table table-sm table-striped small" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">id</th>
<th data-quarto-table-cell-role="th">name</th>
<th data-quarto-table-cell-role="th">tdl</th>
<th data-quarto-table-cell-role="th">fam</th>
<th data-quarto-table-cell-role="th">famext</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th">0</th>
<td>2</td>
<td>14-3-3 protein eta</td>
<td>Tchem</td>
<td>None</td>
<td>None</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th">1</th>
<td>3</td>
<td>14-3-3 protein theta</td>
<td>Tchem</td>
<td>None</td>
<td>None</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th">2</th>
<td>23</td>
<td>3 beta-hydroxysteroid dehydrogenase/Delta 5--&gt;...</td>
<td>Tchem</td>
<td>Enzyme</td>
<td>3-beta-HSD</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th">3</th>
<td>26</td>
<td>5-hydroxytryptamine receptor 2B</td>
<td>Tclin</td>
<td>GPCR</td>
<td>GPCR</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th">4</th>
<td>27</td>
<td>5-hydroxytryptamine receptor 2C</td>
<td>Tclin</td>
<td>GPCR</td>
<td>GPCR</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
</figure>
</div>
</div>
<div class="cell" data-execution_count="3">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1">protein.head()</span></code></pre></div></div>
<div id="tbl-protein" class="cell quarto-float quarto-figure quarto-figure-center anchored" data-execution_count="3">
<figure class="quarto-float quarto-float-tbl figure">
<figcaption class="quarto-float-caption-top quarto-float-caption quarto-float-tbl" id="tbl-protein-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Table&nbsp;2: Proteins
</figcaption>
<div aria-describedby="tbl-protein-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<div class="cell-output cell-output-display" data-execution_count="3">
<div>


<table class="dataframe do-not-create-environment cell caption-top table table-sm table-striped small" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">id</th>
<th data-quarto-table-cell-role="th">uniprot</th>
<th data-quarto-table-cell-role="th">family</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th">0</th>
<td>1</td>
<td>P62258</td>
<td>Belongs to the 14-3-3 family.</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th">1</th>
<td>2</td>
<td>Q04917</td>
<td>Belongs to the 14-3-3 family.</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th">2</th>
<td>3</td>
<td>P27348</td>
<td>Belongs to the 14-3-3 family.</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th">3</th>
<td>4</td>
<td>P30443</td>
<td>Belongs to the MHC class I family.</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th">4</th>
<td>5</td>
<td>P04439</td>
<td>Belongs to the MHC class I family.</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
</figure>
</div>
</div>
<div class="cell" data-execution_count="4">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1">cmpd_activity.head()</span></code></pre></div></div>
<div id="tbl-cmpd-activity" class="cell quarto-float quarto-figure quarto-figure-center anchored" data-execution_count="4">
<figure class="quarto-float quarto-float-tbl figure">
<figcaption class="quarto-float-caption-top quarto-float-caption quarto-float-tbl" id="tbl-cmpd-activity-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Table&nbsp;3: Compound Activities
</figcaption>
<div aria-describedby="tbl-cmpd-activity-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<div class="cell-output cell-output-display" data-execution_count="4">
<div>


<table class="dataframe do-not-create-environment cell caption-top table table-sm table-striped small" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">id</th>
<th data-quarto-table-cell-role="th">target_id</th>
<th data-quarto-table-cell-role="th">act_value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th">0</th>
<td>1</td>
<td>3006</td>
<td>7.60</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th">1</th>
<td>2</td>
<td>3006</td>
<td>7.68</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th">2</th>
<td>3</td>
<td>3006</td>
<td>7.77</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th">3</th>
<td>4</td>
<td>3006</td>
<td>7.80</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th">4</th>
<td>5</td>
<td>3006</td>
<td>7.89</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
</figure>
</div>
</div>
</section>
<section id="filtering-targets-with-more-than-15-active-compounds" class="level2">
<h2 class="anchored" data-anchor-id="filtering-targets-with-more-than-15-active-compounds">Filtering targets with more than 15 active compounds</h2>
<div id="a1cd88c4" class="cell" data-execution_count="5">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1">actives_count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb5-2">    cmpd_activity</span>
<span id="cb5-3">    .groupby(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'target_id'</span>, as_index<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="cb5-4">    .agg(num_actives<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'id'</span>,<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'count'</span>))</span>
<span id="cb5-5">)</span>
<span id="cb5-6"></span>
<span id="cb5-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Merge with the target table</span></span>
<span id="cb5-8">target <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> target.merge(actives_count,</span>
<span id="cb5-9">                      left_on<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'id'</span>,</span>
<span id="cb5-10">                      right_on<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'target_id'</span>,</span>
<span id="cb5-11">                      how<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'left'</span>)</span>
<span id="cb5-12"></span>
<span id="cb5-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Keep only targets with &gt;= 15 active compounds</span></span>
<span id="cb5-14">target <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> target[target[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'num_actives'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>]</span></code></pre></div></div>
</div>
<p>At this point, we have a table of Tclin/Tchem targets that each have at least 15 active compounds recorded in Pharos.</p>
</section>
<section id="read-sifts-mappings" class="level2">
<h2 class="anchored" data-anchor-id="read-sifts-mappings">Read SIFTS Mappings</h2>
<p>The SIFTS PDB chain to UniProt mappings were downloaded from <a href="https://ftp.ebi.ac.uk/pub/databases/msd/sifts/flatfiles/csv">their ftp site</a>.</p>
<div class="cell" data-execution_count="6">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> requests</span>
<span id="cb6-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> tempfile</span>
<span id="cb6-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> typing <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Dict, List</span>
<span id="cb6-4"></span>
<span id="cb6-5">sifts_url <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://ftp.ebi.ac.uk/pub/databases/msd/sifts/flatfiles/csv/pdb_chain_uniprot.csv.gz"</span></span>
<span id="cb6-6"></span>
<span id="cb6-7">dtypes: Dict[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb6-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'PDB'</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>,</span>
<span id="cb6-9">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'CHAIN'</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>,</span>
<span id="cb6-10">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'SP_PRIMARY'</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>,</span>
<span id="cb6-11">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'RES_BEG'</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>,</span>
<span id="cb6-12">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'RES_END'</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>,</span>
<span id="cb6-13">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'PDB_BEG'</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>,  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Keep as string since it may contain insertion codes</span></span>
<span id="cb6-14">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'PDB_END'</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>,  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Keep as string since it may contain insertion codes</span></span>
<span id="cb6-15">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'SP_BEG'</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>,</span>
<span id="cb6-16">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'SP_END'</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span></span>
<span id="cb6-17">}</span>
<span id="cb6-18"></span>
<span id="cb6-19"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> tempfile.TemporaryDirectory() <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> tmpdirname:</span>
<span id="cb6-20">    response <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> requests.get(sifts_url)</span>
<span id="cb6-21">    gz_file_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>tmpdirname<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">/pdb_chain_uniprot.csv.gz"</span></span>
<span id="cb6-22">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">open</span>(gz_file_path, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"wb"</span>) <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> gz_file:</span>
<span id="cb6-23">        gz_file.write(response.content)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Raw compressed bytes</span></span>
<span id="cb6-24">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Read the gzipped CSV with pandas</span></span>
<span id="cb6-25">    sifts_data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.read_csv(</span>
<span id="cb6-26">        gz_file_path,</span>
<span id="cb6-27">        compression<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"gzip"</span>,</span>
<span id="cb6-28">        comment<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#"</span>,</span>
<span id="cb6-29">        dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>dtypes</span>
<span id="cb6-30">    )</span>
<span id="cb6-31"></span>
<span id="cb6-32"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Rename the columns</span></span>
<span id="cb6-33">sifts_data.rename(</span>
<span id="cb6-34">    columns<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>{</span>
<span id="cb6-35">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PDB"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pdb"</span>,</span>
<span id="cb6-36">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CHAIN"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"chain_id"</span>,</span>
<span id="cb6-37">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SP_PRIMARY"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"uniprot"</span>,</span>
<span id="cb6-38">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"RES_BEG"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"res_beg"</span>,</span>
<span id="cb6-39">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"RES_END"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"res_end"</span>,</span>
<span id="cb6-40">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PDB_BEG"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pdb_res_beg"</span>,</span>
<span id="cb6-41">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PDB_END"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pdb_res_end"</span>,</span>
<span id="cb6-42">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SP_BEG"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"uniprot_res_beg"</span>,</span>
<span id="cb6-43">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SP_END"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"uniprot_res_end"</span>,</span>
<span id="cb6-44">    },</span>
<span id="cb6-45">    inplace<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span></span>
<span id="cb6-46">)</span>
<span id="cb6-47"></span>
<span id="cb6-48">sifts_data.head(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span></code></pre></div></div>
<div id="tbl-sifts" class="cell quarto-float quarto-figure quarto-figure-center anchored" data-execution_count="6">
<figure class="quarto-float quarto-float-tbl figure">
<figcaption class="quarto-float-caption-top quarto-float-caption quarto-float-tbl" id="tbl-sifts-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Table&nbsp;4: SIFTS Data
</figcaption>
<div aria-describedby="tbl-sifts-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<div class="cell-output cell-output-display" data-execution_count="6">
<div>


<table class="dataframe do-not-create-environment cell caption-top table table-sm table-striped small" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">pdb</th>
<th data-quarto-table-cell-role="th">chain_id</th>
<th data-quarto-table-cell-role="th">uniprot</th>
<th data-quarto-table-cell-role="th">res_beg</th>
<th data-quarto-table-cell-role="th">res_end</th>
<th data-quarto-table-cell-role="th">pdb_res_beg</th>
<th data-quarto-table-cell-role="th">pdb_res_end</th>
<th data-quarto-table-cell-role="th">uniprot_res_beg</th>
<th data-quarto-table-cell-role="th">uniprot_res_end</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th">0</th>
<td>101m</td>
<td>A</td>
<td>P02185</td>
<td>1</td>
<td>154</td>
<td>0</td>
<td>153</td>
<td>1</td>
<td>154</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th">1</th>
<td>102l</td>
<td>A</td>
<td>P00720</td>
<td>1</td>
<td>40</td>
<td>1</td>
<td>40</td>
<td>1</td>
<td>40</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th">2</th>
<td>102l</td>
<td>A</td>
<td>P00720</td>
<td>42</td>
<td>165</td>
<td>41</td>
<td>NaN</td>
<td>41</td>
<td>164</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th">3</th>
<td>102m</td>
<td>A</td>
<td>P02185</td>
<td>1</td>
<td>154</td>
<td>0</td>
<td>153</td>
<td>1</td>
<td>154</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th">4</th>
<td>103l</td>
<td>A</td>
<td>P00720</td>
<td>1</td>
<td>40</td>
<td>1</td>
<td>NaN</td>
<td>1</td>
<td>40</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
</figure>
</div>
</div>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>The SIFTS <code>pdb_chain_uniprot.csv</code> file provides mappings between UniProt accessions and PDB structure chains.</p>
<p>It comes with three sets of residue ranges:</p>
<ul>
<li><code>RES_BEG</code>/<code>RES_END</code>: Residue numbers as listed in the SEQRES records of the PDB file.
<ul>
<li>They represent sequential numbering from 1 to n, of the full structure sequence as intended by the author, including unresolved residues.</li>
</ul></li>
<li><code>PDB_BEG</code> / <code>PDB_END</code>: Residue numbers as they appear in the ATOM records of the PDB file.
<ul>
<li>May include insertion codes (e.g., 25A, 25B).</li>
<li>Can have non-sequential jumps due to missing residues or unresolved regions.</li>
<li>Reflect only the resolved residues with atomic coordinates.</li>
</ul></li>
<li><code>SP_BEG</code> and <code>SP_END</code>: Residue numbers in the canonical UniProt sequence.</li>
</ul>
</div>
</div>
<p>For this simple analysis, we only care whether a target has at least one PDB structure, so we can use the <code>pdb</code> (PDB) and <code>uniprot</code> (SP_PRIMARY) columns, but if we wanted to do a structure-based analysis and download the associated PDBs, we could use the residue-level mappings to identify the exact ranges of our PDB that we need to extract, as well as identify any missing residues that may need to be filled.</p>
<p>Now, we can group the SIFTS data by UniProt ID and get a list of unique PDB IDs for each target:</p>
<div class="cell" data-execution_count="7">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Group by uniprot_id and get unique PDB IDs</span></span>
<span id="cb7-2">uniprot_to_pdb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb7-3">    sifts_data</span>
<span id="cb7-4">    .groupby(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"uniprot"</span>, as_index<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="cb7-5">    .agg(pdb_ids<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pdb"</span>, <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> x: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">';'</span>.join(x.unique())))</span>
<span id="cb7-6">)</span>
<span id="cb7-7">uniprot_to_pdb.head(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span></code></pre></div></div>
<div id="tbl-sifts-grouped" class="cell quarto-float quarto-figure quarto-figure-center anchored" data-execution_count="7">
<figure class="quarto-float quarto-float-tbl figure">
<figcaption class="quarto-float-caption-top quarto-float-caption quarto-float-tbl" id="tbl-sifts-grouped-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Table&nbsp;5: PDB ids grouped by UniProt ID
</figcaption>
<div aria-describedby="tbl-sifts-grouped-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<div class="cell-output cell-output-display" data-execution_count="7">
<div>


<table class="dataframe do-not-create-environment cell caption-top table table-sm table-striped small" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">uniprot</th>
<th data-quarto-table-cell-role="th">pdb_ids</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th">0</th>
<td>A0A003</td>
<td>6kv9;6kvc</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th">1</th>
<td>A0A009I821</td>
<td>7m4w;7m4x;7m4y;7m4z;7ryf;7ryg;7ryh;7uvv;7uvw;7...</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th">2</th>
<td>A0A009IHW8</td>
<td>7uwg;7uxu;8g83</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th">3</th>
<td>A0A009PZ93</td>
<td>9kbq</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th">4</th>
<td>A0A009QSN8</td>
<td>6v39;6v3a;6v3b;6v3d</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
</figure>
</div>
</div>
</section>
<section id="merging-target-data-with-sifts" class="level2">
<h2 class="anchored" data-anchor-id="merging-target-data-with-sifts">Merging Target Data with SIFTS</h2>
<p>Since our target table has a corresponding protein table (linked by protein.id == target.id in TCRD) and each protein row has a UniProt ID, we can merge the two, and then merge with SIFTS on the UniProt accession:</p>
<div class="cell" data-execution_count="8">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Filter the protein table to only those in our target set</span></span>
<span id="cb8-2">protein_subset <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> protein[protein.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span>.isin(target.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span>)]</span>
<span id="cb8-3"></span>
<span id="cb8-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Merge target and protein by TCRD 'id'</span></span>
<span id="cb8-5">merged_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> target.merge(protein_subset, left_on<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'id'</span>, right_on<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'id'</span>, how<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'left'</span>)</span>
<span id="cb8-6"></span>
<span id="cb8-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Merge SIFTS data</span></span>
<span id="cb8-8">merged_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> merged_df.merge(uniprot_to_pdb, left_on<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'uniprot'</span>, right_on<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'uniprot'</span>, how<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'left'</span>)</span>
<span id="cb8-9"></span>
<span id="cb8-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Rename columns for clarity</span></span>
<span id="cb8-11">merged_df.rename(columns<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>{<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'fam'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'target_family'</span>,</span>
<span id="cb8-12">                   <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tdl'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'target_dev_level'</span>}, inplace<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb8-13"></span>
<span id="cb8-14">merged_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'target_family'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> merged_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'target_family'</span>].fillna(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'None'</span>, inplace<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="cb8-15"></span>
<span id="cb8-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Mark whether a target has at least one known PDB structure</span></span>
<span id="cb8-17">merged_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'has_pdb'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>merged_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'pdb_ids'</span>].isna()</span>
<span id="cb8-18"></span>
<span id="cb8-19">merged_df.head()</span></code></pre></div></div>
<div id="tbl-merged" class="cell quarto-float quarto-figure quarto-figure-center anchored" data-execution_count="8">
<figure class="quarto-float quarto-float-tbl figure">
<figcaption class="quarto-float-caption-top quarto-float-caption quarto-float-tbl" id="tbl-merged-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Table&nbsp;6: Targets with &gt;15 active compounds and PDB mappings
</figcaption>
<div aria-describedby="tbl-merged-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<div class="cell-output cell-output-display" data-execution_count="8">
<div>


<table class="dataframe do-not-create-environment cell caption-top table table-sm table-striped small" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">id</th>
<th data-quarto-table-cell-role="th">name</th>
<th data-quarto-table-cell-role="th">target_dev_level</th>
<th data-quarto-table-cell-role="th">target_family</th>
<th data-quarto-table-cell-role="th">famext</th>
<th data-quarto-table-cell-role="th">target_id</th>
<th data-quarto-table-cell-role="th">num_actives</th>
<th data-quarto-table-cell-role="th">uniprot</th>
<th data-quarto-table-cell-role="th">family</th>
<th data-quarto-table-cell-role="th">pdb_ids</th>
<th data-quarto-table-cell-role="th">has_pdb</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<th data-quarto-table-cell-role="th">0</th>
<td>26</td>
<td>5-hydroxytryptamine receptor 2B</td>
<td>Tclin</td>
<td>GPCR</td>
<td>GPCR</td>
<td>26.0</td>
<td>777.0</td>
<td>P41595</td>
<td>Belongs to the G-protein coupled receptor 1 fa...</td>
<td>4ib4;4nc3;5tud;5tvn;6drx;6dry;6drz;6ds0;7srq;7...</td>
<td>True</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th">1</th>
<td>27</td>
<td>5-hydroxytryptamine receptor 2C</td>
<td>Tclin</td>
<td>GPCR</td>
<td>GPCR</td>
<td>27.0</td>
<td>1612.0</td>
<td>P28335</td>
<td>Belongs to the G-protein coupled receptor 1 fa...</td>
<td>6bqg;6bqh;8dpf;8dpg;8dph;8dpi;8zmf</td>
<td>True</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th">2</th>
<td>30</td>
<td>5'-nucleotidase</td>
<td>Tchem</td>
<td>Enzyme</td>
<td>None</td>
<td>30.0</td>
<td>23.0</td>
<td>P21589</td>
<td>Belongs to the 5'-nucleotidase family.</td>
<td>4h1s;4h1y;4h2b;4h2f;4h2g;4h2i;6hxw;6s7f;6s7h;6...</td>
<td>True</td>
</tr>
<tr class="even">
<th data-quarto-table-cell-role="th">3</th>
<td>36</td>
<td>Amyloid-beta A4 protein</td>
<td>Tchem</td>
<td>None</td>
<td>None</td>
<td>36.0</td>
<td>440.0</td>
<td>P05067</td>
<td>Belongs to the APP family.</td>
<td>1aap;1amb;1amc;1aml;1ba4;1ba6;1bjb;1bjc;1brc;1...</td>
<td>True</td>
</tr>
<tr class="odd">
<th data-quarto-table-cell-role="th">4</th>
<td>37</td>
<td>Adenosine receptor A1</td>
<td>Tclin</td>
<td>GPCR</td>
<td>GPCR</td>
<td>37.0</td>
<td>1550.0</td>
<td>P30542</td>
<td>Belongs to the G-protein coupled receptor 1 fa...</td>
<td>5n2s;5uen;6d9h;7ld3;7ld4</td>
<td>True</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
</figure>
</div>
</div>
</section>
<section id="visualizing-the-data" class="level2">
<h2 class="anchored" data-anchor-id="visualizing-the-data">Visualizing the Data</h2>
<p>Here, we visualize the count of targets with and without PDB structures, as well as the counts by target family.</p>
<div id="058c198a" class="cell" data-execution_count="9">
<details class="code-fold">
<summary>Plotting code</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb9-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb9-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> seaborn <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> sns</span>
<span id="cb9-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="cb9-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> typing <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Tuple</span>
<span id="cb9-5"></span>
<span id="cb9-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Set global style</span></span>
<span id="cb9-7"></span>
<span id="cb9-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> plot_overall_pdb_counts(df: pd.DataFrame) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> Tuple[plt.Figure, plt.Axes]:</span>
<span id="cb9-9">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb9-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Plot the number of targets with and without PDB structures.</span></span>
<span id="cb9-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb9-12">    total <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(df)</span>
<span id="cb9-13">    counts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'has_pdb'</span>].value_counts()</span>
<span id="cb9-14">    percentages <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (counts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> total <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb9-15"></span>
<span id="cb9-16">    fig, ax <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>))</span>
<span id="cb9-17">    width <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span></span>
<span id="cb9-18">    x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.arange(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb9-19">    colors <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'#66c2a5'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'#fc8d62'</span>]</span>
<span id="cb9-20">    bars <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ax.bar(x, counts.values, width, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>colors, zorder<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb9-21"></span>
<span id="cb9-22">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> bar <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> bars:</span>
<span id="cb9-23">        height <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> bar.get_height()</span>
<span id="cb9-24">        pct <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (height<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>total <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb9-25">        ax.text(bar.get_x() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> bar.get_width()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, height, <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(height)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">(</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>pct<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">%)'</span>, ha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'center'</span>, va<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bottom'</span>, size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>)</span>
<span id="cb9-26"></span>
<span id="cb9-27">    ax.set_xticks(x)</span>
<span id="cb9-28">    ax.set_xticklabels([<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Has structure'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'No structure'</span>])</span>
<span id="cb9-29">    ax.set_ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Number of targets'</span>)</span>
<span id="cb9-30">    ax.yaxis.grid(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, linestyle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'-'</span>, alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>, zorder<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb9-31">    ax.xaxis.grid(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="cb9-32">    ax.spines[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'top'</span>].set_visible(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="cb9-33">    ax.spines[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'right'</span>].set_visible(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="cb9-34">    plt.tight_layout()</span>
<span id="cb9-35"></span>
<span id="cb9-36">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> fig, ax</span>
<span id="cb9-37"></span>
<span id="cb9-38"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> plot_pdb_counts_by_family(df: pd.DataFrame) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> Tuple[plt.Figure, plt.Axes]:</span>
<span id="cb9-39">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb9-40"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Plot the number of targets with and without PDB structures, grouped by target family.</span></span>
<span id="cb9-41"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb9-42">    family_counts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.groupby([<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'target_family'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'has_pdb'</span>]).size().unstack(fill_value<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb9-43">    family_totals <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> family_counts.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb9-44">    family_percentages <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (family_counts.div(family_totals, axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb9-45">    family_counts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> family_counts.loc[family_counts.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).sort_values(ascending<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>).index]</span>
<span id="cb9-46"></span>
<span id="cb9-47">    fig, ax <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>))</span>
<span id="cb9-48">    width <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.35</span></span>
<span id="cb9-49"></span>
<span id="cb9-50">    x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.arange(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(family_counts.index))</span>
<span id="cb9-51">    bars1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ax.bar(x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> width<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, family_counts[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>], width, label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Has structure'</span>, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'#66c2a5'</span>, zorder<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb9-52">    bars2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ax.bar(x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> width<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, family_counts[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>], width, label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'No structure'</span>, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'#fc8d62'</span>, zorder<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb9-53"></span>
<span id="cb9-54">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> add_value_labels(bars):</span>
<span id="cb9-55">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> bar <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> bars:</span>
<span id="cb9-56">            height <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> bar.get_height()</span>
<span id="cb9-57">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> height <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb9-58">                    ax.text(bar.get_x() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> bar.get_width()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, height, <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(height)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>, ha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'center'</span>, va<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bottom'</span>, fontsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>)</span>
<span id="cb9-59"></span>
<span id="cb9-60">    add_value_labels(bars1)</span>
<span id="cb9-61">    add_value_labels(bars2)</span>
<span id="cb9-62"></span>
<span id="cb9-63">    ax.set_xticks(x)</span>
<span id="cb9-64">    ax.set_xticklabels(family_counts.index, rotation<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">45</span>, ha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'right'</span>)</span>
<span id="cb9-65">    ax.set_ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Number of targets'</span>)</span>
<span id="cb9-66">    ax.yaxis.grid(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, linestyle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'-'</span>, alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>, zorder<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb9-67">    ax.xaxis.grid(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="cb9-68">    ax.spines[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'top'</span>].set_visible(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="cb9-69">    ax.spines[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'right'</span>].set_visible(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="cb9-70">    ax.legend(loc<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'upper right'</span>, frameon<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, facecolor<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'white'</span>, framealpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.9</span>, edgecolor<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'none'</span>)</span>
<span id="cb9-71">    plt.tight_layout()</span>
<span id="cb9-72"></span>
<span id="cb9-73">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> fig, ax</span></code></pre></div></div>
</details>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1">fig, ax <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plot_overall_pdb_counts(merged_df)</span>
<span id="cb10-2">plt.show()</span>
<span id="cb10-3"></span>
<span id="cb10-4">fix, ax <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plot_pdb_counts_by_family(merged_df)</span>
<span id="cb10-5">plt.show()</span></code></pre></div></div>
<div id="cell-fig-plots" class="cell quarto-layout-panel" data-execution_count="10" data-layout-ncol="1">
<div class="quarto-layout-row">
<div class="cell-output cell-output-display quarto-layout-cell" style="flex-basis: 100.0%;justify-content: flex-start;">
<div id="fig-plots" class="quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-plots-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://ravila.dev/posts/2019-02-14-mapping-pharos-to-pdb/index_files/figure-html/fig-plots-output-1.png" width="566" height="371" class="figure-img">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-plots-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1: Structure availability for targets with &gt;= 15 active compounds.
</figcaption>
</figure>
</div>
</div>
</div>
<div class="quarto-layout-row">
<div class="cell-output cell-output-display quarto-layout-cell" style="flex-basis: 100.0%;justify-content: flex-start;">
<div id="fig-plots" class="quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-plots-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://ravila.dev/posts/2019-02-14-mapping-pharos-to-pdb/index_files/figure-html/fig-plots-output-2.png" width="758" height="374" class="figure-img">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-plots-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;2: Structure availability for targets with &gt;= 15 active compounds, grouped by target family.
</figcaption>
</figure>
</div>
</div>
</div>
</div>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>This is a basic example of how we can combine data from Pharos and SIFTS to identify targets with known active compounds and available PDB structures. There are many additional filters and considerations we could apply depending on our specific research questions and goals.</p>
<p>For example, bringing in additional data from the PDB to filter the structures based on resolution, completeness, or other structural features could help refine our target selection further.</p>


</section>

 ]]></description>
  <category>Python</category>
  <category>cheminformatics</category>
  <category>dataviz</category>
  <guid>https://ravila.dev/posts/2019-02-14-mapping-pharos-to-pdb/</guid>
  <pubDate>Thu, 14 Feb 2019 00:00:00 GMT</pubDate>
</item>
</channel>
</rss>
