无法呈现使用d3.js库的Flask检索到的csv文件

2024-06-16 14:23:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我制作了一个flask应用程序,它可以正确地从API检索数据,然后将这些数据保存为csv文件。然后,我尝试在包含JavaScript和D3.js的HTML模板上使用这个csv文件,用这个csv制作热图。当从远程服务器检索csv文件时,HTML/JS文件工作得很好,但当csv文件与应用程序位于同一目录时,则工作得不好。应用程序如下所示:

from flask import Flask, render_template
from chembl_webresource_client.new_client import new_client
import csv

targets =["CHEMBL325", "CHEMBL1937", "CHEMBL1829", "CHEMBL3524", "CHEMBL2563", "CHEMBL1865", "CHEMBL2716", "CHEMBL3192", "CHEMBL4145", "CHEMBL5103", "CHEMBL3310"]

molecules = ["CHEMBL98", "CHEMBL99", "CHEMBL27759", "CHEMBL2018302", "CHEMBL483254", "CHEMBL1213490", "CHEMBL356769", "CHEMBL272980", "CHEMBL430060", "CHEMBL1173445", "CHEMBL356066", "CHEMBL1914702"]

app = Flask(__name__)

@app.route("/")
def index():

  with open('./templates/data.csv', 'w', newline='') as csvfile:
    writer = csv.writer(csvfile)
    writer.writerow(['group','variable','value'])
    for target in targets:
      total_entries = 0
      avg_pchembl_value = 0
      pchembl_value_sum = 0
      for molecule in molecules:
        filtered_acts = new_client.activity.filter(molecule_chembl_id=molecule, target_chembl_id=target, pchembl_value__isnull=False)
        for act in filtered_acts:
          total_entries += 1
          pchembl_value_sum += float(act['pchembl_value'])
        avg_pchembl_value = round(pchembl_value_sum / total_entries, 2)
        writer.writerow([target, molecule, str(avg_pchembl_value)])

  return render_template("index.html")

if __name__ == "__main__":
  app.run()

其中index.html模板如下所示:

<!-- Code from d3-graph-gallery.com -->
<!DOCTYPE html>
<meta charset="utf-8">

<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>

<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>

<!-- Load color palettes -->
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>

<script>
  // set the dimensions and margins of the graph
  var margin = {top: 80, right: 25, bottom: 30, left: 40},
    width = 450 - margin.left - margin.right,
    height = 450 - margin.top - margin.bottom;

  // append the svg object to the body of the page
  var svg = d3.select("#my_dataviz")
  .append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform",
          "translate(" + margin.left + "," + margin.top + ")");

  //Read the data
  d3.csv("data.csv", function(data) {

    // Labels of row and columns -> unique identifier of the column called 'group' and 'variable'
    var myGroups = d3.map(data, function(d){return d.group;}).keys()
    var myVars = d3.map(data, function(d){return d.variable;}).keys()

    // Build X scales and axis:
    var x = d3.scaleBand()
      .range([ 0, width ])
      .domain(myGroups)
      .padding(0.05);
    svg.append("g")
      .style("font-size", 15)
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x).tickSize(0))
      .select(".domain").remove()

    // Build Y scales and axis:
    var y = d3.scaleBand()
      .range([ height, 0 ])
      .domain(myVars)
      .padding(0.05);
    svg.append("g")
      .style("font-size", 15)
      .call(d3.axisLeft(y).tickSize(0))
      .select(".domain").remove()

    // Build color scale
    var myColor = d3.scaleSequential()
      .interpolator(d3.interpolateInferno)
      .domain([1,100])

    // create a tooltip
    var tooltip = d3.select("#my_dataviz")
      .append("div")
      .style("opacity", 0)
      .attr("class", "tooltip")
      .style("background-color", "white")
      .style("border", "solid")
      .style("border-width", "2px")
      .style("border-radius", "5px")
      .style("padding", "5px")

    // Three function that change the tooltip when user hover / move / leave a cell
    var mouseover = function(d) {
      tooltip
        .style("opacity", 1)
      d3.select(this)
        .style("stroke", "black")
        .style("opacity", 1)
    }
    var mousemove = function(d) {
      tooltip
        .html("pchEMBL<br>value: " + d.value)
        .style("left", (d3.mouse(this)[0]+70) + "px")
        .style("top", (d3.mouse(this)[1]) + "px")
    }
    var mouseleave = function(d) {
      tooltip
        .style("opacity", 0)
      d3.select(this)
        .style("stroke", "none")
        .style("opacity", 0.8)
    }

    // add the squares
    svg.selectAll()
      .data(data, function(d) {return d.group+':'+d.variable;})
      .enter()
      .append("rect")
        .attr("x", function(d) { return x(d.group) })
        .attr("y", function(d) { return y(d.variable) })
        .attr("rx", 4)
        .attr("ry", 4)
        .attr("width", x.bandwidth() )
        .attr("height", y.bandwidth() )
        .style("fill", function(d) { return myColor(d.value)} )
        .style("stroke-width", 4)
        .style("stroke", "none")
        .style("opacity", 0.8)
      .on("mouseover", mouseover)
      .on("mousemove", mousemove)
      .on("mouseleave", mouseleave)
  })

  // Add title to graph
  svg.append("text")
          .attr("x", 0)
          .attr("y", -50)
          .attr("text-anchor", "left")
          .style("font-size", "22px")
          .text("A d3.js heatmap");

  // Add subtitle to graph
  svg.append("text")
          .attr("x", 0)
          .attr("y", -20)
          .attr("text-anchor", "left")
          .style("font-size", "14px")
          .style("fill", "grey")
          .style("max-width", 400)
          .text("A short description of the take-away message of this chart.");
</script>

Tags: csvthesvgmargindatareturnvaluestyle