Skip to content

Brennaser/Virtual-FTIR-Spectrometer

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1,251 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Virtual-FTIR-Spectrometer

The Raston Lab's Fourier Transform InfraRed - Scientific Instrument Simulator (FTIR-SIS) was designed to emulate a student's classroom experience with an FTIR spectrometer. The web application focuses on both spectra generation and a simplified top-down view of the components that make up the spectrometer.

This project uses React for the frontend and Flask for the backend. The backend is located in a separate repository.

Installation

NOTE: The following setup steps are for the frontend, not the backend API.

  1. Clone the repository

  2. Move into the cloned repository's directory

    cd Virtual-FTIR-Spectrometer
  3. Install all npm dependencies

    npm install
  4. Run the server locally

    npm start

Usage

The intended audience for this application is undergraduate chemistry students studying spectroscopy. The following screenshots are not exhaustive but acknowledge most of the main features:

  • Experimental Setup (spectrometer parameters)

TODO

  • Instrument Window (top-down view of simplified spectrometer)

TODO

  • Spectra Window (plotted spectra)

TODO

Notes

The following sections will be about more complex features and implementations that new programmers to the project may need more explication.

Redux Toolkit

Redux Toolkit is used to provide centralized state between different components and routes withing the application. An official Redux Toolkit tutorial and a FreeCodeCamp Redux Toolkit course was used to setup state in our application.

SVG

SVG Diagrams

One of the major features of this project is the interactive SVG that students can use to learn more about the spectrometer. All SVG assets can be found in an accompanying GitHub repository.

SVG Optimization and Components

SVGs created in Inkscape have tags that are not supported in default React. Because of this, we need to optimize the SVG by removing these tags. This optimization can be done easily in SVGOMG's GUI (just remember to update the settings to not cleanup IDs).

We have implemented a solution that automates the optimization and/ or translation from native SVG to .jsx (allows for finer-grain control using JavaScript). (For both of the commands listed below, svgo.config.js is used to change some of the default SVGO settings.)

  • To optimize tooltip SVGs, place the SVGs in the src/images/tooltips/ directory and run npm run svgo.

  • To optimize and translate the Instrument Window SVG, place the SVG into the src/images/ directory and run npm run svgr. This command will remove the .svg file from the directory.

SVG Interactivity and Animation

Text Interactivity

To center text in the SVG, add the following style to the text element you want centered. This was completed by using Inkscape's XML Editor:

text-anchor: middle;
dominant-baseline: central;

Then using Inkscape's Align and Distribute tool, center the text in the "parent" element. To edit text in JavaScript, use the textContent interface:

export function textInteractivity(text) {
  // DOM elements
  const textElement = document.getElementById("text");

  // set text
  textElement.textContent = text;
}
SVG Interactivity

SVG interactivity is similar to text. The major difference is the use of the setAttribute() element or setting the style of a particular CSS property. For example:

// this is good for moving a group or rectangle
document.getElementById("id-1").style.transform = "translate(0px, 0px)";

// this is good for moving a path
document
  .getElementById("id-2")
  .setAttribute("d", "M20,230 Q40,205 50,230 T90,230");

You may need to change the location of a group/element depending on a boolean:

export function componentLocation(isVisible) {
  // DOM elements
  const componentID = document.getElementById("component-1");

  lectureBottleInUse
    ? componentID.setAttribute("d", "")
    : componentID.setAttribute("d", "");
}

You may need to change the visibility of a group/element depending on a user parameter:

export function componentVisibility(parameter) {
  // DOM element
  const componentID = document.getElementById("component-1");

  // constant parameter values
  const componentValue = PARAMETER_VALUE.constantValue;

  // ternary used to show/hide cell window in the Main SVG
  componentID.style.display = parameter === componentValue ? "inline" : "none";
}
Animation

SVG animation is set in JavaScript using the animate() method. Animations are set using keyframes around the starting and ending position of the object you want to move. A simplified version of this code is shown below:

export function squareAnimation() {
  // DOM element
  const square = document.getElementById("square");

  square.animate(
    [
      // keyframes
      { transform: "translate(0px, 0px)" },   // starting position
      { transform: "translate(100px, 0px)" }, // move square to the right 100 pixels
      { transform: "translate(0px, 0px)" },   // ending position
    ],
    {
      // timing options
      duration: 1000,       // duration of total animation in milliseconds
      iterations: Infinity, // how many times the animation occurs
    }
  );

SVG Tooltips

When certain parts of the Instrument Window are clicked, a popup with additional image(s) and a description will appear. The underlying component behind this is the MUI Dialog.

In the SVG, components are collated by setting group IDs (the <g> element). In JavaScript, the SVG is setup with an onClick listener that will target the parent element's ID (event.target.parentElement.id), which is the group's ID. A dictionary (src/dictionaries/tooltips.js) is used to store and format text and images associated with each tooltip.

A simplified version of this code is shown below:

// InstrumentWindow.jsx
import React, { useState } from "react";

// components
import { Dialog } from "@mui/material";
import MySVG from "../images/InstrumentSVG";

// constants
import { BAD_ID } from "../dictionaries/constants";

// dictionaries - holds contents of the tooltips
import { tooltips } from "../dictionaries/tooltips";

// style
import "../style/routes/InstrumentWindow.css";

export default function InstrumentWindow() {
  const [toggled, setToggled] = useState(false);
  const [element, setElement] = useState();

  // looks at click event and determines ID selected
  //   some IDs are considered "bad" (do not have tooltips)
  const handleClick = (event) => {
    if (!BAD_ID.includes(event.target.parentElement.id)) {
      setElement(event.target.parentElement.id);
      setToggled(!toggled);
    }
  };

  return (
    <div>
      <MySVG onClick={handleClick} />

      {element && (
        <Dialog
          onClose={handleClick}
          open={toggled}
          fullScreen={element === "display" ? true : false}
        >
          {toolTips[element].text}
        </Dialog>
      )}
    </div>
  );
}

Contributing

Upkeep of this project is intended for recruited undergraduate students, but pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

License

Licensed under TODO

Relevant third-party tools and resources we depend on:

  • GitHub Pages Deploy Action: GitHub Action used to automate deployment of web applications to GitHub Pages (Licensed MIT)

  • MUI: React user interface component library (Licensed MIT)

  • Plotly.js: JavaScript data visualization library (Licensed MIT)

  • Radis: Spectra generation (Licensed LGPL-3.0)

  • React: JavaScript library for building user interfaces (Licensed MIT)

  • React CSV: React components to build CSV files on the fly (Licensed MIT)

  • React Router: Declarative routing for React (Licensed MIT)

  • React to Print: React components for printing in the browser (Licensed MIT)

  • Redux Toolkit: Library for updating and managing application state (Licensed MIT)

  • SVGO: Node.js tool for optimizing SVG files (Licensed MIT)

  • SVGOMG: Web GUI for SVGO (Licensed MIT)

  • SVGR: Tool for transforming SVGs into React components (Licensed MIT)

Inspiration from:

  • Make a README: Inspiration for README.md template (Licensed MIT)

  • Radis app: Inspiration for user interface components like the dual slider for the wavenumber range (Licensed LGPL-3.0)

About

virtual Fourier Transform InfraRed (FTIR) spectrometer

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • JavaScript 95.8%
  • CSS 3.1%
  • HTML 1.1%