def test_hdf5_metadata_contains(): jpkfile = datadir / "spot3-0192.jpk-force" fdat = afmformats.load_data(jpkfile, modality="force-distance")[0] _, path = tempfile.mkstemp(suffix=".h5", prefix="afmformats_test_") fdat.export_data(path, metadata=True, fmt="hdf5") fdat2 = afmformats.load_data(path, modality="force-distance")[0] assert "force" in fdat2
def test_detect_jpk(name, is_valid): jpkfile = data_path / name if is_valid: afmlist = afmformats.load_data(path=jpkfile) assert afmlist else: with pytest.raises(afmformats.errors.FileFormatNotSupportedError): afmformats.load_data(path=jpkfile)
def test_subgroup(): group = AFMGroup() group += load_data(data_dir / "map-data-reference-points.jpk-force-map") group += load_data(data_dir / "map2x2_extracted.jpk-force-map") group += load_data(data_dir / "flipsign_2015.05.22-15.31.49.352.jpk-force") exp = data_dir / "map2x2_extracted.jpk-force-map" subgrp = group.subgroup_with_path(path=exp) assert len(group) == 8 assert len(subgrp) == 4 assert subgrp[0].path == exp
def test_save_open_with_metadata(): jpkfile = datadir / "spot3-0192.jpk-force" fdat = afmformats.load_data(jpkfile, modality="force-distance")[0] _, path = tempfile.mkstemp(suffix=".tab", prefix="afmformats_test_") fdat.export_data(path, metadata=True, fmt="tab") fdat2 = afmformats.load_data(path, modality="force-distance")[0] # compare metadata for key in fdat.metadata: if key in ["path", "format"]: assert fdat.metadata[key] != fdat2.metadata[key] else: assert fdat.metadata[key] == fdat2.metadata[key] for col in fdat.columns: assert np.allclose(fdat[col], fdat2[col], atol=0)
def test_export(): ds1 = nanite.IndentationGroup(jpkfile) idnt = ds1[0] # tip-sample separation idnt.apply_preprocessing(["compute_tip_position"]) # create temporary file _, path = tempfile.mkstemp(suffix=".tab", prefix="nanite_idnt_export") idnt.export(path) data = afmformats.load_data(path)[0] assert len(data) == 4000 assert np.allclose(data["force"][100], -4.853736717639109e-10) assert np.allclose(data["height (measured)"][100], 2.256791903750211e-05, atol=1e-10, rtol=0) assert data["segment"][100] == 0 assert np.allclose(data["time"][100], 0.04999999999999999) assert np.allclose(data["tip position"][100], 2.255675939721752e-05, atol=1e-10, rtol=0) assert data["segment"][3000] == 1 try: pathlib.Path(path).unlink() except OSError: pass
def test_repr_str(): jpkfile = data_dir / "spot3-0192.jpk-force" fd = afmformats.load_data(jpkfile)[0] assert "AFMForceDistance" in str(fd) assert "spot3-0192.jpk-force" in str(fd) assert "AFMForceDistance" in repr(fd) assert "spot3-0192.jpk-force" in repr(fd)
def load_data(path, callback=None, meta_override=None): """Load data and return list of :class:`afmformats.AFMForceDistance` This is essentially a wrapper around :func:`afmformats.formats.find_data` and :func:`afmformats.formats.load_data` that returns force-distance datasets. Parameters ---------- path: str or pathlib.Path or list of str or list of pathlib.Path path to data files or directory containing data files; if directories are given, they are searched recursively callback: callable function for progress tracking; must accept a float in [0, 1] as an argument. meta_override: dict if specified, contains key-value pairs of metadata that are used when loading the files (see :data:`afmformats.meta.META_FIELDS`) """ paths = afmformats.find_data(path, modality=DEFAULT_MODALITY) data = [] for ii, pp in enumerate(paths): measurements = afmformats.load_data( pp, # recurse callback function with None as default callback=lambda x: callback((ii + x) / len(paths)) if callback else None, meta_override=meta_override, **get_load_data_modality_kwargs()) data += measurements return data
def test_open_simple(): tf = generate_tab_file() data = afmformats.load_data(tf)[0] assert np.sum(data["segment"]) == 49 assert np.allclose(data["force"][0], 0) assert np.allclose(data["force"][1], 1e-9) assert np.allclose(data["tip position"][1], np.pi * 1e-6)
def test_open_simple(): path = datadir / "2015_01_17_gel4-0,1_mQ_adh_6B_Curve_DFL_Height_51.txt" meta_override = {} meta_override["spring constant"] = 0.055 meta_override["sensitivity"] = 61 data = afmformats.load_data(path=path, meta_override=meta_override)[0] assert data["force"].size == 1644 assert np.sum(~data["segment"]) == np.argmax(data["force"]) + 1
def test_load_all_with_callback(path): """Make sure that the callback function is properly implemented""" calls = [] def callback(value): calls.append(value) try: afmformats.load_data(path=path, callback=callback) except afmformats.errors.MissingMetaDataError: afmformats.load_data(path=path, callback=callback, meta_override={ "spring constant": 20, "sensitivity": .01e-6 }) assert calls[-1] == 1
def test_open_jpk_map_enum(): jpkfile = datadir / "map2x2_extracted.jpk-force-map" data = afmformats.load_data(jpkfile) # Correct enumeration assert data[0].metadata["enum"] == 0 assert data[1].metadata["enum"] == 1 assert data[2].metadata["enum"] == 2 assert data[3].metadata["enum"] == 3
def test_open_jpk_map_enum(): jpkfile = datadir / "2020.02.07-16.29.05.036.jpk-qi-data" data = afmformats.load_data(jpkfile) # Correct enumeration assert data[0].metadata["enum"] == 0 assert data[1].metadata["enum"] == 1 assert data[2].metadata["enum"] == 2 assert data[3].metadata["enum"] == 3
def test_length(name, size, meta): jpkfile = data_dir / name fdat = afmformats.load_data( jpkfile, modality="force-distance", meta_override=meta, )[0] assert len(fdat) == size assert np.all(fdat["index"] == np.arange(size))
def test_meta_extracted_single(): jpkfile = datadir / "spot3-0192.jpk-force" md = afmformats.load_data(jpkfile)[0].metadata summary = md.get_summary() for sec in ["acquisition", "dataset", "setup", "storage"]: for kk in summary[sec]: v = summary[sec][kk] if not isinstance(v, (str, pathlib.Path)): assert not np.isnan(v), "should not be nan: '{}'".format(kk)
def test_save_open_with_metadata(): jpkfile = datadir / "spot3-0192.jpk-force" fdat = afmformats.load_data(jpkfile, mode="force-distance")[0] _, path = tempfile.mkstemp(suffix=".h5", prefix="afmformats_test_") fdat.export(path, metadata=True, fmt="hdf5") fdat2 = afmformats.load_data(path, mode="force-distance")[0] # compare metadata for key in fdat.metadata: if key in ["path", "format"]: assert fdat.metadata[key] != fdat2.metadata[key] else: assert fdat.metadata[key] == fdat2.metadata[key] for col in fdat.columns: assert np.allclose(fdat[col], fdat2[col], atol=0) # cleanup try: pathlib.Path(path).unlink() except OSError: pass
def load_data(path, callback=None): """Load data and return list of :class:`afmformats.AFMForceDistance`""" paths = get_data_paths(path) data = [] for pp in paths: measurements = afmformats.load_data(pp, callback=callback) for dd in measurements: if dd.mode == "force-distance": data.append(dd) return data
def test_single_conversion(): tf = datadir / "AFM-workshop_FD_single_2018-08-01_13.06.09.csv" k = 20 sens = .01e-6 data = afmformats.load_data(tf, meta_override={ "spring constant": k, "sensitivity": sens })[0] assert data.metadata["spring constant"] == k assert "force" in data.columns assert np.allclose(data["force"][0], 0.6861 * sens * k)
def test_open_simple(): tf = generate_tab_file() data = afmformats.load_data(tf)[0] assert np.sum(data["segment"]) == 49 assert np.allclose(data["force"][0], 0) assert np.allclose(data["force"][1], 1e-9) assert np.allclose(data["tip position"][1], np.pi * 1e-6) # cleanup try: pathlib.Path(tf).unlink() except OSError: pass
def test_open_with_metadata(): jpkfile = datadir / "U3_3_p10004.ibw" fdat = afmformats.load_data(jpkfile, modality="force-distance")[0] for col in ['force', 'height (measured)', 'height (piezo)', 'segment']: assert col in fdat assert fdat.metadata["sensitivity"] == 2.0364e-07 assert fdat.metadata["spring constant"] == 0.31451 assert fdat.metadata["setpoint"] == 1.8e-07 assert np.allclose(fdat["force"].max(), 1.778407e-07, rtol=1e-7, atol=0) assert fdat.metadata["point count"] == 10097 assert fdat.metadata["time"] == '18:18:49' assert np.allclose(fdat["height (measured)"].min(), -1.0322237e-06, rtol=1e-7, atol=0)
def test_load_jpk_map(): jpkfile = data_path / "map2x2_extracted.jpk-force-map" afmlist = afmformats.load_data(path=jpkfile) assert len(afmlist) == 4 ds = afmlist[2] ds2 = afmlist[3] assert ds.metadata["enum"] == 2 assert np.allclose(ds.metadata["duration"], 1.6089775561097257) # Verified with visual inspection of force curve in JPK software assert np.allclose(ds["force"][0], -5.8540192943834714e-10) assert np.allclose(ds["height (measured)"][0], 0.0001001727719556085) # make sure curve id is different assert ds.metadata["curve id"] != ds2.metadata["curve id"] assert ds.metadata["session id"] == ds2.metadata["session id"]
def _convert_merge(self): file, _ = QtWidgets.QFileDialog.getSaveFileName( self.parent(), "Output file", "", "HDF5 file (*.h5)") if not file: return False if not file.endswith(".h5"): file += ".h5" # HDF5 format with h5py.File(file, "w") as h5: for path in self.file_list: fdlist = afmformats.load_data(path) for fdist in fdlist: fdist.export(h5, metadata=self.get_metadata_keys(fdist), fmt="hdf5") return True
def test_map_open(): tf = datadir / "AFM-workshop_FD_mapping_16_2018-08-01_13.07.zip" k = 20 sens = .01e-6 data = afmformats.load_data(tf, meta_override={ "spring constant": k, "sensitivity": sens }) assert len(data) == 16 # these changes were made manually offset = 13761.9288 for ii in range(len(data)): assert data[ii]["height (measured)"][0] == -(offset + ii) * 1e-9 assert data[0]["height (measured)"][0] != data[1]["height (measured)"][0] assert np.allclose(data[0]["force"][0], 0.6875 * sens * k)
def test_export_hdf5(): """Test for hotfixes in 0.7.1""" jpkfile = datadir / "spot3-0192.jpk-force" fdat = afmformats.load_data(jpkfile, mode="force-distance")[0] _, path = tempfile.mkstemp(suffix=".h5", prefix="afmformats_test_") with h5py.File(path, "w") as h5: fdat.export(h5, metadata=True, fmt="hdf5") fdat.export(h5, metadata=True, fmt="hdf5") with h5py.File(path, "r") as h5: assert h5["0"].attrs["enum"] == 0 assert h5["1"].attrs["enum"] == 1 assert h5["0"]["force"].attrs["unit"] == "N" # cleanup try: pathlib.Path(path).unlink() except OSError: pass
def _convert_curve(self): out_dir = QtWidgets.QFileDialog.getExistingDirectory( self.parent(), "Select output directory", "") if out_dir: for path in self.file_list: path = pathlib.Path(path) epath = codecs.encode(str(path), encoding="utf-8", errors="ignore") stem = path.name + "_" + hashlib.md5(epath).hexdigest()[:5] fdlist = afmformats.load_data(path) for fdist in fdlist: name = "{}_{}.{}".format(stem, fdist.enum, self.format) opath = pathlib.Path(out_dir) / name fdist.export(opath, metadata=self.get_metadata_keys(fdist), fmt=self.format) return True else: return False # do not close the dialog
def test_base(): grp1 = AFMGroup(data_dir / "map2x2_extracted.jpk-force-map") grp2 = load_data(data_dir / "spot3-0192.jpk-force") grp3 = grp1 + grp2 assert len(grp3) == 5 assert len(grp2) == 1 assert len(grp1) == 4 grp2 += grp1 assert len(grp3) == 5 assert len(grp2) == 5 for afmd in grp3: assert isinstance(afmd, AFMForceDistance) # test repr assert "AFMGroup" in repr(grp3) # test str assert "AFMGroup" in str(grp3) assert "spot3-0192.jpk-force" in str(grp3)
def test_load_jpk_simple(): jpkfile = data_path / "spot3-0192.jpk-force" afmlist = afmformats.load_data(path=jpkfile) ds = afmlist[0] assert ds.metadata["enum"] == 0 assert np.allclose(ds["height (measured)"][0], 2.2815672438768612e-05)
def test_open_issue_8(): # test file provided by María Tenorio (CC0) jpkfile = datadir / "SiN_FD_plot.ibw" fdat = afmformats.load_data(jpkfile, modality="force-distance")[0] assert fdat.metadata["time"] == "10:47:31"
def test_missing_sens(): tf = datadir / "AFM-workshop_FD_single_2018-08-01_13.06.09.csv" try: afmformats.load_data(tf) except afmformats.errors.MissingMetaDataError: pass
def test_load_jpk_piezo(): jpkfile = data_path / "spot3-0192.jpk-force" afmlist = afmformats.load_data(path=jpkfile) ds = afmlist[0] assert np.allclose(ds["height (piezo)"][0], 2.878322343068329e-05)
def test_single_open(): tf = datadir / "AFM-workshop_FD_single_2020-02-14_13.41.25.csv" data = afmformats.load_data(tf)[0] assert "force" in data.columns assert np.allclose(data["force"][0], 1276.4373e-9)