-
Notifications
You must be signed in to change notification settings - Fork 25
Add block for processing GPC/SEC data from Agilent Technologies 1260 Infinity II multidetector SEC/GPC system #1409
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -6,14 +6,16 @@ | |||||||||
| import pandas as pd | ||||||||||
| from bokeh.models import HoverTool, LogColorMapper | ||||||||||
|
|
||||||||||
| import codecs | ||||||||||
|
|
||||||||||
| from pydatalab.blocks.base import DataBlock | ||||||||||
| from pydatalab.bokeh_plots import DATALAB_BOKEH_THEME, selectable_axes_plot | ||||||||||
| from pydatalab.file_utils import get_file_info_by_id | ||||||||||
| from pydatalab.logger import LOGGER | ||||||||||
|
|
||||||||||
|
|
||||||||||
| class FTIRBlock(DataBlock): | ||||||||||
| accepted_file_extensions: tuple[str, ...] = (".asp",) | ||||||||||
| accepted_file_extensions: tuple[str, ...] = (".asp",".txt") | ||||||||||
| blocktype = "ftir" | ||||||||||
| name = "FTIR" | ||||||||||
| description = ( | ||||||||||
|
|
@@ -36,7 +38,7 @@ def parse_ftir_asp(cls, filename: Path) -> pd.DataFrame: | |||||||||
| filename: Path to the .asp file | ||||||||||
|
|
||||||||||
| Returns: | ||||||||||
| FTIR dataframe with columns "Wavenumber" and "Absorbance"" with the wavenumber in cm^-1 | ||||||||||
| FTIR dataframe with columns "Wavenumber" and "Absorbance"" with the wavenumber in cm^-1 and string 'default' for the x and y units | ||||||||||
| """ | ||||||||||
|
|
||||||||||
| ftir = pd.read_csv(filename, header=None) | ||||||||||
|
|
@@ -46,10 +48,37 @@ def parse_ftir_asp(cls, filename: Path) -> pd.DataFrame: | |||||||||
| x_range = np.linspace(start_wavenumber, end_wavenumber, number_of_points) | ||||||||||
| y = ftir[0].iloc[-number_of_points:] | ||||||||||
| ftir = pd.DataFrame.from_dict({"Wavenumber": x_range, "Absorbance": y}) | ||||||||||
| return ftir | ||||||||||
| return ftir, 'default', 'default' | ||||||||||
|
|
||||||||||
| @classmethod | ||||||||||
| def parse_ftir_txt(cls, filename: Path) -> pd.DataFrame: | ||||||||||
| """Parses .txt FTIR data generated by a Shimadzu IR Tracer-100 FT-IR spectrophotometer | ||||||||||
|
|
||||||||||
| The file consists of a header with metadata: a title, data type, x units and y units, | ||||||||||
| and then the IR data | ||||||||||
| This function reads the file and extracts the data as a pandas DataFrame, and the x units and y units as strings. | ||||||||||
| This function does not read the original .ispd file generated by the spectrometer | ||||||||||
|
|
||||||||||
| Args: | ||||||||||
| filename: Path to the .txt file | ||||||||||
|
|
||||||||||
| Returns: | ||||||||||
| FTIR dataframe with columns "Wavenumber" and "Absorbance", and strings giving the x and y units | ||||||||||
| """ | ||||||||||
| with open(filename,'r') as f: | ||||||||||
| alldata = f.readlines() | ||||||||||
| title = alldata[0].split('=')[1] | ||||||||||
| dtype = alldata[1].split('=')[1] | ||||||||||
| xunits = alldata[2].split('=')[1] | ||||||||||
| yunits = alldata[3].split('=')[1] | ||||||||||
| data = alldata[4:] | ||||||||||
| x = [float(line.split()[0]) for line in data] | ||||||||||
| y = [float(line.split()[1]) for line in data] | ||||||||||
| ftir = pd.DataFrame.from_dict({'Wavenumber':x, 'Absorbance':y}) | ||||||||||
| return ftir, xunits, yunits | ||||||||||
|
|
||||||||||
| @classmethod | ||||||||||
| def _format_ftir_plot(self, ftir_data: pd.DataFrame) -> bokeh.layouts.layout: | ||||||||||
| def _format_ftir_plot(self, ftir_data: pd.DataFrame,xunits:str,yunits:str) -> bokeh.layouts.layout: | ||||||||||
| """Formats FTIR data for plotting in Bokeh, inverted x-axis with a buffer of 50 cm^-1 on either side | ||||||||||
|
|
||||||||||
| Args: | ||||||||||
|
|
@@ -58,6 +87,14 @@ def _format_ftir_plot(self, ftir_data: pd.DataFrame) -> bokeh.layouts.layout: | |||||||||
| Returns: | ||||||||||
| bokeh.layouts.layout: Bokeh layout with FTIR data plotted | ||||||||||
| """ | ||||||||||
| if xunits == 'default': | ||||||||||
| toollabsx = "Wavenumber / cm⁻¹" | ||||||||||
| else: | ||||||||||
| toollabsx = "Wavenumber /{0}".format(xunits) | ||||||||||
| if yunits == 'default': | ||||||||||
| toollabsy = "Absorbance" | ||||||||||
| else: | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changed the unit to display a superscript like in the other format
Suggested change
|
||||||||||
| toollabsy = yunits | ||||||||||
| layout = selectable_axes_plot( | ||||||||||
| ftir_data, | ||||||||||
| x_options=["Wavenumber"], | ||||||||||
|
|
@@ -69,16 +106,22 @@ def _format_ftir_plot(self, ftir_data: pd.DataFrame) -> bokeh.layouts.layout: | |||||||||
| plot_line=True, | ||||||||||
| tools=HoverTool( | ||||||||||
| tooltips=[ | ||||||||||
| ("Wavenumber / cm⁻¹", "@Wavenumber{0.00}"), | ||||||||||
| ("Absorbance", "@Absorbance{0.0000}"), | ||||||||||
| (toollabsx, "@Wavenumber{0.00}"), | ||||||||||
| (toollabsy, "@Absorbance{0.0000}"), | ||||||||||
| ], # Display x and y values to specified decimal places | ||||||||||
| mode="vline", # Ensures hover follows the x-axis | ||||||||||
| ), | ||||||||||
| ) | ||||||||||
| # Adding cm^-1 to the x-axis label using unicode characters - might be a more logical way | ||||||||||
| layout.children[1].xaxis.axis_label = "Wavenumber / cm⁻¹" | ||||||||||
| if xunits == 'default': | ||||||||||
| # Adding cm^-1 to the x-axis label using unicode characters - might be a more logical way | ||||||||||
| layout.children[1].xaxis.axis_label = "Wavenumber / cm⁻¹" | ||||||||||
| else: | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just made this change so that the label appears the same with a superscript as in the other mode.
Suggested change
|
||||||||||
| layout.children[1].xaxis.axis_label = "Wavenumber /{0}".format(xunits) | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
| if yunits != 'default': | ||||||||||
| layout.children[1].yaxis.axis_label = yunits | ||||||||||
| return layout | ||||||||||
|
|
||||||||||
|
|
||||||||||
| def generate_ftir_plot(self): | ||||||||||
| file_info = None | ||||||||||
| # all_files = None | ||||||||||
|
|
@@ -97,9 +140,12 @@ def generate_ftir_plot(self): | |||||||||
| ext, | ||||||||||
| ) | ||||||||||
| return | ||||||||||
| elif ext == '.asp': | ||||||||||
| ftir_data,xunits,yunits = self.parse_ftir_asp(Path(file_info["location"])) | ||||||||||
| elif ext == '.txt': | ||||||||||
| ftir_data,xunits,yunits = self.parse_ftir_txt(Path(file_info["location"])) | ||||||||||
|
|
||||||||||
| ftir_data = self.parse_ftir_asp(Path(file_info["location"])) | ||||||||||
|
|
||||||||||
| print(ftir_data) | ||||||||||
| if ftir_data is not None: | ||||||||||
| layout = self._format_ftir_plot(ftir_data) | ||||||||||
| layout = self._format_ftir_plot(ftir_data,xunits,yunits) | ||||||||||
| self.data["bokeh_plot_data"] = bokeh.embed.json_item(layout, theme=DATALAB_BOKEH_THEME) | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we want to include this in the PR, I think the gitignore should've caught it but I can remove it from the other branch. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a space between the / and the unit. This is just to keep it consistent with other datalab blocks.