admin管理员组

文章数量:1122846

I'm trying to make a graph with Observable plot in Node.js, but on the graph it shows only some of the data and not all the dots that should.

async function CultureChart(data, t= 7,  skew= 0) {
  try {
    // Import required libraries
    const jsdom = require("jsdom");
    const { JSDOM } = jsdom;
    const Plot = await import('@observablehq/plot');

    // Set up a virtual DOM
    const { document } = new JSDOM(`<!DOCTYPE html><body></body>`).window;

    // Map emotions to colors
    const emotionColor = {
      positive: "green",
      negative: "red",
    };

    // Create the plot without the threshold
    const plot = await Plot.plot({
      document,
      inset: 10,
      color: { legend: true, type: "categorical" },
      marks: [
        Plot.density(data.filter((d) => d.emotion), {
          weight: (d) => d.emotion === "positive" ? 1 - skew : 1 + skew,
          x: "Culture",
          y: "Innovation",
          stroke: (d) => emotionColor[d.emotion],
          strokeOpacity: 0.5,
          clip: true,
          thresholds: t,          
        }),
    
        Plot.dot(data.filter((d) => d.emotion), {
          x: "Culture",
          y: "Innovation",
          stroke: (d) => emotionColor[d.emotion],
          fill: (d) => emotionColor[d.emotion],
          // Adjust opacity based on skew: if skew is high, reduce opacity (make dot invisible)
          strokeOpacity: (d) => {
            const opacity = d.emotion === "positive" ? 1 - skew : 1 + skew;
            return Math.max(0, Math.min(1, opacity));  // Ensure opacity stays between 0 and 1
          },
          fillOpacity: (d) => {
            const opacity = d.emotion === "positive" ? 1 - skew : 1 + skew;
            return Math.max(0, Math.min(1, opacity));  // Ensure opacity stays between 0 and 1
          },
        }),
    
        Plot.frame(),
      ],
    });

    // Append the plot to the DOM
    document.body.appendChild(plot);

    // Return the SVG
    return document.body.innerHTML;

  } catch (error) {
    console.error('Error generating chart:', error);
    return `<p>Error generating chart: ${error.message}</p>`;
  }
}
exports.Culturechart = async (req, res) => {
  const filter = req.body.filter;
  const thresholds = req.body.thresholds;

  // Query to get Culture (x), Innovation (y), and their IDs
  const query = `
    SELECT 
      ppid, 
      CAST(x AS double precision) AS x, 
      CAST(y AS double precision) AS y 
    FROM 
      pointposition 
    WHERE 
      type = false`;

  // Query to get emotion values by ppid
  const emotionQuery = `
    SELECT 
      ppid, 
      emotional 
    FROM 
      value`;

  try {
    // Execute both queries
    const pointResult = await pool.query(query);
    const emotionResult = await pool.query(emotionQuery);

    // Check for empty results
    if (pointResult.rows.length <= 0 || emotionResult.rows.length <= 0) {
      return res.status(204).send('No data in the database');
    }

    // Create a mapping of emotions by pointposition ID
    const emotionMap = emotionResult.rows.reduce((map, row) => {
      const emotionValue = parseInt(row.emotional, 10); // Ensure emotional is treated as an integer

      // Categorize emotion based on the value
      let emotionCategory;
      if (emotionValue < 50) {
        emotionCategory = 'negative';
      } else  {
        emotionCategory = 'positive';
      }

      // Map ppid to categorized emotion
      map[row.ppid] = emotionCategory;
      return map;
    }, {});

    // Map the result to include Culture, Innovation, and Emotion
    const data = pointResult.rows
      .map(row => {
        const cultureValue = row.x || null; // x is the Culture value
        const innovationValue = row.y || null; // y is the Innovation value
        const emotionValue = emotionMap[row.ppid] || 'neutral'; // Default to neutral if not found

        return {
          ppid: row.ppid, // Ensure each row has its unique ID
          Culture: cultureValue,
          Innovation: innovationValue,
          emotion: emotionValue
        };
      })
      .filter(item => item.Culture !== null && item.Innovation !== null); // Remove missing values

    // Generate the chart with the updated data
    const chartSvg = await CultureChart(data,thresholds);

    // Wrap the SVG chart into an HTML response
    const htmlResponse = `
      <!DOCTYPE html>
      <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>SVG Chart</title>
      </head>
      <body>
        <div>${chartSvg}</div>
      </body>
      </html>
    `;

    // Send the HTML response with the chart SVG
    res.set('Content-Type', 'text/html');
    res.send(htmlResponse);

  } catch (error) {
    console.error('Error generating chart:', error);
    res.status(500).send('Error generating chart');
  }
};

in array "data" there is 100 line of data, I have tried to search and to modify some parameters but nothing works. I added how I call the function It's loaded with a plotController.js and plotRoutes.js index.js call routes and frame the browser I go "http://localhost:3000/plot/Culturechart"

本文标签: nodejsObservable PlotStack Overflow