scholi / pySPM

Python library to handle Scanning Probe Microscopy Images. Can read nanoscan .xml data, Bruker AFM images, Nanonis SXM files as well as iontof images(ITA, ITM and ITS).
Apache License 2.0
58 stars 33 forks source link

get_channel does not work for specific afm channel - value error #37

Closed muzaffarmaksumov closed 6 months ago

muzaffarmaksumov commented 7 months ago

I am trying to open from my Bruker .spm data some channel (Input 2).

when I write:

Current = ScanB.get_channel(channel='Input2')

it shows me following error message:

"""Current = ScanB.get_channel(channel='Input2')

File ~\AppData\Roaming\Python\Python311\site-packages\pySPM\Bruker.py:165 in get_channel data = self._get_raw_layer(i, debug=debug) scale scale2

File ~\AppData\Roaming\Python\Python311\site-packages\pySPM\Bruker.py:64 in _get_raw_layer rows = int(self.layers[i][b'Samps/line'][0])

ValueError: invalid literal for int() with base 10: b'0 0' """

Could you please help me to solve this problem? Input2 is getting from cyclic voltammetry. I am saving potential into Input1, and get_channel in this case is working.

Thanks in advance.

dineshpinto commented 7 months ago

So this looks like an issue with the parser.

The reverse engineering in the parser is done on a best effort basis, as these are proprietary file formats, causing bugs like these.

If you send me the bruker file I can take a look and try and debug what's happening - annual.fallout_0z@icloud.com

scholi commented 7 months ago

So your data are not an image but are one dimensional? Get_channel was meant to work with images.... Here your rows is not a single value but is a double 0 which is hard for me to interprete.... I imagine that this means 2- one dimensional data. so your voltametric hysterisis.

As suggested by dineshpinto I think the best is to get such a file for better support.

muzaffarmaksumov commented 7 months ago

Hi everyone,

Input2 channel also contains an image, I could open it Nanoscope (software from Bruker). As our Bruker does not have an integrated potentiostat, we use SP300 Biologic Potentiostat and connect it to Bruker via two extra channels (low freq. analog), named Input1 and Input2.

I have sent my .spm file to email of dineshpinto as suggested.

thanks a lot for your help.

dineshpinto commented 7 months ago

So I took a look at the file.

>>> p = Path("Data", "test.spm")
>>> scan = pySPM.Bruker(p)
>>> scan.list_channels()

Channels
========
S [ZSensor] "Height Sensor"
S [DeflectionError] "Deflection Error"
S [Lateral] "Friction"
S [Lateral] "Friction"
S [Input1] "Input1"
S [Input2] "Input2"

Extracting the data stored in layer 5 (i.e. Input 2), there is something quite wrong with the data here. The offset, data length, samples per line are all 0.

>>> scan.layers[5]

{b'Data offset': [b'0'],
 b'Data length': [b'0'],
 b'Bytes/pixel': [b'2'],
 b'Start context': [b'ECCON'],
 b'Data type': [b'STM'],
 b'Plane fit': [b'0 0 0 0'],
 b'Frame direction': [b'Up'],
 b'Capture start line': [b'0'],
 b'Color Table Index': [b'12'],
 b'Relative frame time': [b'15265.4'],
 b'Invalid Data Flag': [b'None'],
 b'Invalid Data Fill': [b'None'],
 b'Samps/line': [b'0 0'],
 b'Number of lines': [b'256'],
 b'Aspect Ratio': [b'1:1'],
 b'Scan Size': [b'2 2 ~m'],
 b'Scan Line': [b'Main'],
 b'Line Direction': [b'Trace'],
 b'Highpass': [b'0'],
 b'Lowpass': [b'0'],
 b'Realtime Planefit': [b'None'],
 b'Offline Planefit': [b'None'],
 b'Valid data start X': [b'0'],
 b'Valid data start Y': [b'0'],
 b'Valid data len X': [b'256'],
 b'Valid data len Y': [b'256'],
 b'Tip x width correction factor': [b'1'],
 b'Tip y width correction factor': [b'1'],
 b'Tip x width correction factor sigma': [b'1'],
 b'Tip y width correction factor sigma': [b'1'],
 b'@2:Image Data': [b'S [Input2] "Input2"'],
 b'@Z magnify': [b'C [2:Z scale] 0.0002848307'],
 b'@2:Z scale': [b'V [Sens. Input2] (0.0003750000 V/LSB) 24.57600 V'],
 b'@2:Z offset': [b'V [Sens. Input2] (0.0003750000 V/LSB) 0.004500000 V'],
 b'Voltam current range': [b'0 26666.7 32767 32767 32767 32767 32767 32767 32767'],
 b'Z magnify image': [b'1'],
 b'Temporal volt range': [b'2'],
 b'Voltam volt min': [b'-2666.67'],
 b'Voltam volt max': [b'2666.67'],
 b'Smoothing filter': [b'0'],
 b'Scope coupling': [b'DC'],
 b'Voltam function': [b'Current'],
 b'Temporal current range': [b'0 26666.7 32767 32767 32767 32767 32767 32767 0'],
 b'Temporal time range': [b'100'],
 b'Temporal time start': [b'0'],
 b'Temporal time end': [b'100'],
 b'Temporal function': [b'Current']}

There is something wrong with this channel in the data file, you need to double check this.

For reference, I compared it to the output of layer 4 (i.e. Input 1) and you can see all those fields have values in them.

>>> scan.layers[4]

{b'Data offset': [b'1129536'],
 b'Data length': [b'262144'],
 b'Bytes/pixel': [b'2'],
 b'Start context': [b'OL'],
 b'Data type': [b'AFM'],
 b'Plane fit': [b'0 0 0 5'],
 b'Frame direction': [b'Up'],
 b'Capture start line': [b'0'],
 b'Color Table Index': [b'12'],
 b'Relative frame time': [b'15265.4'],
 b'Invalid Data Flag': [b'None'],
 b'Invalid Data Fill': [b'None'],
 b'Samps/line': [b'256'],
 b'Number of lines': [b'256'],
 b'Aspect Ratio': [b'1:1'],
 b'Scan Size': [b'2 2 ~m'],
 b'Scan Line': [b'Main'],
 b'Line Direction': [b'Trace'],
 b'Highpass': [b'0'],
 b'Lowpass': [b'0'],
 b'Realtime Planefit': [b'None'],
 b'Offline Planefit': [b'None'],
 b'Valid data start X': [b'0'],
 b'Valid data start Y': [b'0'],
 b'Valid data len X': [b'256'],
 b'Valid data len Y': [b'256'],
 b'Tip x width correction factor': [b'1'],
 b'Tip y width correction factor': [b'1'],
 b'Tip x width correction factor sigma': [b'1'],
 b'Tip y width correction factor sigma': [b'1'],
 b'@2:Image Data': [b'S [Input1] "Input1"'],
 b'@Z magnify': [b'C [2:Z scale] 0.01505534'],
 b'@2:Z scale': [b'V [Sens. Input1] (0.0003750000 V/LSB) 24.57600 V'],
 b'@2:Z offset': [b'V [Sens. Input1] (0.0003750000 V/LSB) 0.1138125 V']}
scholi commented 7 months ago

Could you send me the file?

dineshpinto commented 7 months ago

Email?

muzaffarmaksumov commented 6 months ago

Hi dineshpinto, I see you have closed the issue recently. Could you please share what was the result of this problem? Thank you

dineshpinto commented 6 months ago

So I have already shared my thoughts in https://github.com/scholi/pySPM/issues/37#issuecomment-1851328783, I am not convinced this is an issue with pySPM.

@scholi also has the file, maybe he can weigh in too?

scholi commented 6 months ago

There is a bug in the library somehow. So Input2 has a proper Data Length and offset. The Input2 is followed by \*EC AFM plot V vs. T list which is not understood by the library and the data of the AFM plot (so 1D data) overwrite the data ot Input2.

from pySPM import Bruker
import os
import numpy as np
import struct
import matplotlib.pyplot as plt
%matplotlib inline

A = Bruker(os.path.expanduser("~/Downloads/test.spm"))
A.get_channel("Input2").show()

image

I could correct it locally. I need to push the changes...

scholi commented 6 months ago

OK I have pushed the data to github. Could you try it? (So don't use pip, but use the library from github)

muzaffarmaksumov commented 6 months ago

hi scholi, I have checked, it is working now. thanks a lot for your help!