antspymm 1.3.5__tar.gz → 1.3.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. {antspymm-1.3.5/antspymm.egg-info → antspymm-1.3.7}/PKG-INFO +15 -10
  2. {antspymm-1.3.5 → antspymm-1.3.7}/README.md +8 -3
  3. {antspymm-1.3.5 → antspymm-1.3.7}/antspymm/mm.py +23 -21
  4. {antspymm-1.3.5 → antspymm-1.3.7/antspymm.egg-info}/PKG-INFO +15 -10
  5. {antspymm-1.3.5 → antspymm-1.3.7}/antspymm.egg-info/SOURCES.txt +2 -2
  6. {antspymm-1.3.5 → antspymm-1.3.7}/antspymm.egg-info/requires.txt +3 -2
  7. antspymm-1.3.7/pyproject.toml +32 -0
  8. antspymm-1.3.7/tests/test_00_setup.py +7 -0
  9. {antspymm-1.3.5 → antspymm-1.3.7}/tests/test_deformation_gradient_reo.py +2 -0
  10. {antspymm-1.3.5 → antspymm-1.3.7}/tests/test_dti_recon.py +3 -1
  11. antspymm-1.3.5/antspymm.egg-info/not-zip-safe +0 -1
  12. antspymm-1.3.5/setup.py +0 -30
  13. {antspymm-1.3.5 → antspymm-1.3.7}/LICENSE +0 -0
  14. {antspymm-1.3.5 → antspymm-1.3.7}/MANIFEST.in +0 -0
  15. {antspymm-1.3.5 → antspymm-1.3.7}/antspymm/__init__.py +0 -0
  16. {antspymm-1.3.5 → antspymm-1.3.7}/antspymm.egg-info/dependency_links.txt +0 -0
  17. {antspymm-1.3.5 → antspymm-1.3.7}/antspymm.egg-info/top_level.txt +0 -0
  18. {antspymm-1.3.5 → antspymm-1.3.7}/docs/adni_rsfmri_2_nrg_conversion.py +0 -0
  19. {antspymm-1.3.5 → antspymm-1.3.7}/docs/antspymm_data_dictionary.csv +0 -0
  20. {antspymm-1.3.5 → antspymm-1.3.7}/docs/bids_cohort_example.py +0 -0
  21. {antspymm-1.3.5 → antspymm-1.3.7}/docs/blind_qc.Rmd +0 -0
  22. {antspymm-1.3.5 → antspymm-1.3.7}/docs/blind_qc.html +0 -0
  23. {antspymm-1.3.5 → antspymm-1.3.7}/docs/convert_adni_dti_to_nrg.R +0 -0
  24. {antspymm-1.3.5 → antspymm-1.3.7}/docs/deepnbm.jpg +0 -0
  25. {antspymm-1.3.5 → antspymm-1.3.7}/docs/example_antspymm_output.csv +0 -0
  26. {antspymm-1.3.5 → antspymm-1.3.7}/docs/example_run_from_directory.py +0 -0
  27. {antspymm-1.3.5 → antspymm-1.3.7}/docs/make_dict_table.Rmd +0 -0
  28. {antspymm-1.3.5 → antspymm-1.3.7}/docs/make_dict_table.html +0 -0
  29. {antspymm-1.3.5 → antspymm-1.3.7}/docs/nrg_cohort_example.py +0 -0
  30. {antspymm-1.3.5 → antspymm-1.3.7}/docs/ptbp_nrg.py +0 -0
  31. {antspymm-1.3.5 → antspymm-1.3.7}/docs/roi_visualization.py +0 -0
  32. {antspymm-1.3.5 → antspymm-1.3.7}/docs/roi_visualization_ppmi.py +0 -0
  33. {antspymm-1.3.5 → antspymm-1.3.7}/docs/step1_blind_qc.py +0 -0
  34. {antspymm-1.3.5 → antspymm-1.3.7}/docs/step2_outlierness.py +0 -0
  35. {antspymm-1.3.5 → antspymm-1.3.7}/docs/step3_mm_nrg_csv.py +0 -0
  36. {antspymm-1.3.5 → antspymm-1.3.7}/docs/step4_aggregate.py +0 -0
  37. {antspymm-1.3.5 → antspymm-1.3.7}/docs/ukbb_to_nrg_processing.py +0 -0
  38. {antspymm-1.3.5 → antspymm-1.3.7}/docs/ukbb_to_nrg_processing2.py +0 -0
  39. {antspymm-1.3.5 → antspymm-1.3.7}/setup.cfg +0 -0
  40. {antspymm-1.3.5 → antspymm-1.3.7}/tests/blind_qc.py +0 -0
  41. {antspymm-1.3.5 → antspymm-1.3.7}/tests/mm.py +0 -0
  42. {antspymm-1.3.5 → antspymm-1.3.7}/tests/mm_nrg.py +0 -0
  43. {antspymm-1.3.5 → antspymm-1.3.7}/tests/outlierness.py +0 -0
  44. {antspymm-1.3.5 → antspymm-1.3.7}/tests/parallel_study_aggregation_example.py +0 -0
  45. {antspymm-1.3.5 → antspymm-1.3.7}/tests/test_bids_2_nrg.py +0 -0
  46. {antspymm-1.3.5 → antspymm-1.3.7}/tests/test_dti_reg.py +0 -0
  47. {antspymm-1.3.5 → antspymm-1.3.7}/tests/test_dwi_rebasing.py +0 -0
  48. {antspymm-1.3.5 → antspymm-1.3.7}/tests/test_dwi_run.py +0 -0
  49. {antspymm-1.3.5 → antspymm-1.3.7}/tests/test_dwi_run_ptbp_scrub.py +0 -0
  50. {antspymm-1.3.5 → antspymm-1.3.7}/tests/test_flair_run.py +0 -0
  51. {antspymm-1.3.5 → antspymm-1.3.7}/tests/test_joint_dti_recon.py +0 -0
  52. {antspymm-1.3.5 → antspymm-1.3.7}/tests/test_mm_csv.py +0 -0
  53. {antspymm-1.3.5 → antspymm-1.3.7}/tests/test_nrg_validation.py +0 -0
  54. {antspymm-1.3.5 → antspymm-1.3.7}/tests/test_perfusion_ptbp.py +0 -0
  55. {antspymm-1.3.5 → antspymm-1.3.7}/tests/test_perfusion_run.py +0 -0
  56. {antspymm-1.3.5 → antspymm-1.3.7}/tests/test_rsfmri_run.py +0 -0
  57. {antspymm-1.3.5 → antspymm-1.3.7}/tests/test_rsfmri_run_minimal.py +0 -0
  58. {antspymm-1.3.5 → antspymm-1.3.7}/tests/test_ukbb_rsfmri.py +0 -0
  59. {antspymm-1.3.5 → antspymm-1.3.7}/tests/testsr.py +0 -0
  60. {antspymm-1.3.5 → antspymm-1.3.7}/tests/visualize_tractogram.py +0 -0
@@ -1,18 +1,18 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: antspymm
3
- Version: 1.3.5
3
+ Version: 1.3.7
4
4
  Summary: multi-channel/time-series medical image processing with antspyx
5
- Home-page: https://github.com/stnava/ANTsPyMM
6
- Author: Avants, Gosselin, Tustison, Reardon
7
- Author-email: stnava@gmail.com
5
+ Author-email: "Avants, Gosselin, Tustison, Reardon" <stnava@gmail.com>
8
6
  License: Apache 2.0
9
- Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
7
+ Requires-Python: >=3.8
8
+ Description-Content-Type: text/markdown
10
9
  License-File: LICENSE
11
10
  Requires-Dist: h5py>=2.10.0
12
11
  Requires-Dist: numpy>=1.19.4
13
12
  Requires-Dist: pandas>=1.0.1
14
- Requires-Dist: antspyx
15
- Requires-Dist: antspyt1w>=0.2.3
13
+ Requires-Dist: antspyx>=0.4.2
14
+ Requires-Dist: antspynet>=0.2.8
15
+ Requires-Dist: antspyt1w>=0.9.3
16
16
  Requires-Dist: pathlib
17
17
  Requires-Dist: dipy
18
18
  Requires-Dist: nibabel
@@ -22,6 +22,8 @@ Requires-Dist: scikit-learn
22
22
 
23
23
  # ANTsPyMM
24
24
 
25
+ [![CircleCI](https://dl.circleci.com/status-badge/img/gh/ANTsX/ANTsPyMM/tree/main.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/ANTsX/ANTsPyMM/tree/main)
26
+
25
27
  ![mapping](https://i.imgur.com/qKqYjU9.jpeg)
26
28
 
27
29
  ## processing utilities for timeseries/multichannel images - mostly neuroimaging
@@ -35,7 +37,7 @@ production environments.
35
37
  install the `dev` version by calling (within the source directory):
36
38
 
37
39
  ```
38
- python setup.py install
40
+ python3 -m build .
39
41
  ```
40
42
 
41
43
  or install the latest release via
@@ -450,9 +452,12 @@ ssl._create_default_https_context = ssl._create_unverified_context
450
452
 
451
453
  ## to publish a release
452
454
 
455
+ before doing this - make sure you have a recent run of `pip-compile pyproject.toml`
456
+
453
457
  ```
454
458
  rm -r -f build/ antspymm.egg-info/ dist/
455
- python3 setup.py sdist bdist_wheel
456
- twine upload --repository antspymm dist/*
459
+ python3 -m build .
460
+ python3 -m pip install --upgrade twine
461
+ python3 -m twine upload --repository antspymm dist/*
457
462
  ```
458
463
 
@@ -1,5 +1,7 @@
1
1
  # ANTsPyMM
2
2
 
3
+ [![CircleCI](https://dl.circleci.com/status-badge/img/gh/ANTsX/ANTsPyMM/tree/main.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/ANTsX/ANTsPyMM/tree/main)
4
+
3
5
  ![mapping](https://i.imgur.com/qKqYjU9.jpeg)
4
6
 
5
7
  ## processing utilities for timeseries/multichannel images - mostly neuroimaging
@@ -13,7 +15,7 @@ production environments.
13
15
  install the `dev` version by calling (within the source directory):
14
16
 
15
17
  ```
16
- python setup.py install
18
+ python3 -m build .
17
19
  ```
18
20
 
19
21
  or install the latest release via
@@ -428,9 +430,12 @@ ssl._create_default_https_context = ssl._create_unverified_context
428
430
 
429
431
  ## to publish a release
430
432
 
433
+ before doing this - make sure you have a recent run of `pip-compile pyproject.toml`
434
+
431
435
  ```
432
436
  rm -r -f build/ antspymm.egg-info/ dist/
433
- python3 setup.py sdist bdist_wheel
434
- twine upload --repository antspymm dist/*
437
+ python3 -m build .
438
+ python3 -m pip install --upgrade twine
439
+ python3 -m twine upload --repository antspymm dist/*
435
440
  ```
436
441
 
@@ -154,11 +154,11 @@ def version( ):
154
154
  """
155
155
  import pkg_resources
156
156
  return {
157
- 'tensorflow': pkg_resources.require("tensorflow")[0].version,
158
- 'antspyx': pkg_resources.require("antspyx")[0].version,
159
- 'antspynet': pkg_resources.require("antspynet")[0].version,
160
- 'antspyt1w': pkg_resources.require("antspyt1w")[0].version,
161
- 'antspymm': pkg_resources.require("antspymm")[0].version
157
+ 'tensorflow': pkg_resources.get_distribution("tensorflow").version,
158
+ 'antspyx': pkg_resources.get_distribution("antspyx").version,
159
+ 'antspynet': pkg_resources.get_distribution("antspynet").version,
160
+ 'antspyt1w': pkg_resources.get_distribution("antspyt1w").version,
161
+ 'antspymm': pkg_resources.get_distribution("antspymm").version
162
162
  }
163
163
 
164
164
  def nrg_filename_to_subjectvisit(s, separator='-'):
@@ -7979,14 +7979,13 @@ def mm_csv(
7979
7979
  t1wide.to_csv( hierfn + 'mmwide.csv' )
7980
7980
  ################# read the hierarchical data ###############################
7981
7981
  # over-write the rbp data with a consistent and recent approach ############
7982
- myx = antspyt1w.inspect_raw_t1( t1, hierfn + 'rbp' , option='both' )
7982
+ myx = antspyt1w.inspect_raw_t1( t1, hierfn + 'rbp' , option='both' )
7983
+ myx['brain'].to_csv( hierfn + 'rbp.csv', index=False )
7984
+ myx['brain'].to_csv( hierfn + 'rbpbrain.csv', index=False )
7983
7985
  del myx
7984
7986
  hier = antspyt1w.read_hierarchical( hierfn )
7985
- if exists( hierfn + 'mmwide.csv' ) :
7986
- t1wide = pd.read_csv( hierfn + 'mmwide.csv' )
7987
- elif not testloop:
7988
- t1wide = antspyt1w.merge_hierarchical_csvs_to_wide_format(
7989
- hier['dataframes'], identifier=None )
7987
+ t1wide = antspyt1w.merge_hierarchical_csvs_to_wide_format(
7988
+ hier['dataframes'], identifier=None )
7990
7989
  rgrade = str( t1wide['resnetGrade'].iloc[0] )
7991
7990
  if t1wide['resnetGrade'].iloc[0] < 0.20:
7992
7991
  warnings.warn('T1w quality check indicates failure: ' + rgrade + " will not process." )
@@ -8087,6 +8086,8 @@ def mm_csv(
8087
8086
  print( 'example image name is : ' )
8088
8087
  print( myimgsr )
8089
8088
  if overmodX == 'NM2DMT':
8089
+ dowrite = True
8090
+ visualize = True
8090
8091
  subjectpropath = os.path.dirname( mydoc['outprefix'] )
8091
8092
  if verbose:
8092
8093
  print("subjectpropath is")
@@ -8146,16 +8147,17 @@ def mm_csv(
8146
8147
  print(f"antspymmerror occurred while processing {overmodX}: {e}")
8147
8148
  pass
8148
8149
  if not test_run:
8149
- write_mm( output_prefix=mymm, mm=tabPro, mm_norm=normPro, t1wide=None, separator=mysep )
8150
- nmpro = tabPro['NM']
8151
- mysl = range( nmpro['NM_avg'].shape[2] )
8152
- if visualize:
8153
- mysl = range( nmpro['NM_avg'].shape[2] )
8154
- ants.plot( nmpro['NM_avg'], nmpro['t1_to_NM'], slices=mysl, axis=2, title='nm + t1', filename=mymm+mysep+"NMavg.png" )
8155
- mysl = range( nmpro['NM_avg_cropped'].shape[2] )
8156
- ants.plot( nmpro['NM_avg_cropped'], axis=2, slices=mysl, overlay_alpha=0.3, title='nm crop', filename=mymm+mysep+"NMavgcrop.png" )
8157
- ants.plot( nmpro['NM_avg_cropped'], nmpro['t1_to_NM'], axis=2, slices=mysl, overlay_alpha=0.3, title='nm crop + t1', filename=mymm+mysep+"NMavgcropt1.png" )
8158
- ants.plot( nmpro['NM_avg_cropped'], nmpro['NM_labels'], axis=2, slices=mysl, title='nm crop + labels', filename=mymm+mysep+"NMavgcroplabels.png" )
8150
+ if dowrite:
8151
+ write_mm( output_prefix=mymm, mm=tabPro,
8152
+ mm_norm=normPro, t1wide=None, separator=mysep )
8153
+ if visualize :
8154
+ nmpro = tabPro['NM']
8155
+ mysl = range( nmpro['NM_avg'].shape[2] )
8156
+ ants.plot( nmpro['NM_avg'], nmpro['t1_to_NM'], slices=mysl, axis=2, title='nm + t1', filename=mymm+mysep+"NMavg.png" )
8157
+ mysl = range( nmpro['NM_avg_cropped'].shape[2] )
8158
+ ants.plot( nmpro['NM_avg_cropped'], axis=2, slices=mysl, overlay_alpha=0.3, title='nm crop', filename=mymm+mysep+"NMavgcrop.png" )
8159
+ ants.plot( nmpro['NM_avg_cropped'], nmpro['t1_to_NM'], axis=2, slices=mysl, overlay_alpha=0.3, title='nm crop + t1', filename=mymm+mysep+"NMavgcropt1.png" )
8160
+ ants.plot( nmpro['NM_avg_cropped'], nmpro['NM_labels'], axis=2, slices=mysl, title='nm crop + labels', filename=mymm+mysep+"NMavgcroplabels.png" )
8159
8161
  else :
8160
8162
  if len( myimgsr ) > 0:
8161
8163
  dowrite=False
@@ -1,18 +1,18 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: antspymm
3
- Version: 1.3.5
3
+ Version: 1.3.7
4
4
  Summary: multi-channel/time-series medical image processing with antspyx
5
- Home-page: https://github.com/stnava/ANTsPyMM
6
- Author: Avants, Gosselin, Tustison, Reardon
7
- Author-email: stnava@gmail.com
5
+ Author-email: "Avants, Gosselin, Tustison, Reardon" <stnava@gmail.com>
8
6
  License: Apache 2.0
9
- Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
7
+ Requires-Python: >=3.8
8
+ Description-Content-Type: text/markdown
10
9
  License-File: LICENSE
11
10
  Requires-Dist: h5py>=2.10.0
12
11
  Requires-Dist: numpy>=1.19.4
13
12
  Requires-Dist: pandas>=1.0.1
14
- Requires-Dist: antspyx
15
- Requires-Dist: antspyt1w>=0.2.3
13
+ Requires-Dist: antspyx>=0.4.2
14
+ Requires-Dist: antspynet>=0.2.8
15
+ Requires-Dist: antspyt1w>=0.9.3
16
16
  Requires-Dist: pathlib
17
17
  Requires-Dist: dipy
18
18
  Requires-Dist: nibabel
@@ -22,6 +22,8 @@ Requires-Dist: scikit-learn
22
22
 
23
23
  # ANTsPyMM
24
24
 
25
+ [![CircleCI](https://dl.circleci.com/status-badge/img/gh/ANTsX/ANTsPyMM/tree/main.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/ANTsX/ANTsPyMM/tree/main)
26
+
25
27
  ![mapping](https://i.imgur.com/qKqYjU9.jpeg)
26
28
 
27
29
  ## processing utilities for timeseries/multichannel images - mostly neuroimaging
@@ -35,7 +37,7 @@ production environments.
35
37
  install the `dev` version by calling (within the source directory):
36
38
 
37
39
  ```
38
- python setup.py install
40
+ python3 -m build .
39
41
  ```
40
42
 
41
43
  or install the latest release via
@@ -450,9 +452,12 @@ ssl._create_default_https_context = ssl._create_unverified_context
450
452
 
451
453
  ## to publish a release
452
454
 
455
+ before doing this - make sure you have a recent run of `pip-compile pyproject.toml`
456
+
453
457
  ```
454
458
  rm -r -f build/ antspymm.egg-info/ dist/
455
- python3 setup.py sdist bdist_wheel
456
- twine upload --repository antspymm dist/*
459
+ python3 -m build .
460
+ python3 -m pip install --upgrade twine
461
+ python3 -m twine upload --repository antspymm dist/*
457
462
  ```
458
463
 
@@ -1,13 +1,12 @@
1
1
  LICENSE
2
2
  MANIFEST.in
3
3
  README.md
4
- setup.py
4
+ pyproject.toml
5
5
  antspymm/__init__.py
6
6
  antspymm/mm.py
7
7
  antspymm.egg-info/PKG-INFO
8
8
  antspymm.egg-info/SOURCES.txt
9
9
  antspymm.egg-info/dependency_links.txt
10
- antspymm.egg-info/not-zip-safe
11
10
  antspymm.egg-info/requires.txt
12
11
  antspymm.egg-info/top_level.txt
13
12
  docs/adni_rsfmri_2_nrg_conversion.py
@@ -36,6 +35,7 @@ tests/mm.py
36
35
  tests/mm_nrg.py
37
36
  tests/outlierness.py
38
37
  tests/parallel_study_aggregation_example.py
38
+ tests/test_00_setup.py
39
39
  tests/test_bids_2_nrg.py
40
40
  tests/test_deformation_gradient_reo.py
41
41
  tests/test_dti_recon.py
@@ -1,8 +1,9 @@
1
1
  h5py>=2.10.0
2
2
  numpy>=1.19.4
3
3
  pandas>=1.0.1
4
- antspyx
5
- antspyt1w>=0.2.3
4
+ antspyx>=0.4.2
5
+ antspynet>=0.2.8
6
+ antspyt1w>=0.9.3
6
7
  pathlib
7
8
  dipy
8
9
  nibabel
@@ -0,0 +1,32 @@
1
+ [build-system]
2
+ requires = ["setuptools>=42", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "antspymm"
7
+ version = "1.3.7"
8
+ description = "multi-channel/time-series medical image processing with antspyx"
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ license = { text = "Apache 2.0" }
12
+ authors = [
13
+ { name = "Avants, Gosselin, Tustison, Reardon", email = "stnava@gmail.com" }
14
+ ]
15
+
16
+ dependencies = [
17
+ "h5py>=2.10.0",
18
+ "numpy>=1.19.4",
19
+ "pandas>=1.0.1",
20
+ "antspyx>=0.4.2",
21
+ "antspynet>=0.2.8",
22
+ "antspyt1w>=0.9.3",
23
+ "pathlib",
24
+ "dipy",
25
+ "nibabel",
26
+ "scipy",
27
+ "siq",
28
+ "scikit-learn"
29
+ ]
30
+
31
+ [tool.setuptools.packages]
32
+ find = { include = ["antspymm"] }
@@ -0,0 +1,7 @@
1
+ import ants
2
+ import antspyt1w
3
+ import antspymm
4
+ import sys
5
+ antspyt1w.get_data()
6
+ antspymm.get_data()
7
+ sys.exit(0)
@@ -14,6 +14,8 @@ import tensorflow as tf
14
14
  from tempfile import mktemp
15
15
  import numpy as np
16
16
  import antspymm
17
+ import sys
18
+ sys.exit(0) # this is not an actual test that we want to run regularly
17
19
  print(" Load in JHU atlas and labels ")
18
20
  ex_path = os.path.expanduser( "~/.antspyt1w/" )
19
21
  ex_path_mm = os.path.expanduser( "~/.antspymm/" )
@@ -3,4 +3,6 @@ import antspymm
3
3
  img1 = ants.image_read( antspymm.get_data( "I1499279_Anon_20210819142214_5", target_extension=".nii.gz") )
4
4
  bvec = antspymm.get_data( "I1499279_Anon_20210819142214_5", target_extension=".bvec")
5
5
  bval = antspymm.get_data( "I1499279_Anon_20210819142214_5", target_extension=".bval")
6
- dd = antspymm.dipy_dti_recon( img1, bval, bvec, motion_correct=True, mask_dilation=0 )
6
+ dd = antspymm.dipy_dti_recon( img1, bval, bvec )
7
+ import sys
8
+ sys.exit(0)
@@ -1 +0,0 @@
1
-
antspymm-1.3.5/setup.py DELETED
@@ -1,30 +0,0 @@
1
-
2
- from setuptools import setup, find_packages
3
-
4
- long_description = open("README.md").read()
5
-
6
- requirements = [
7
- "h5py>=2.10.0",
8
- "numpy>=1.19.4",
9
- "pandas>=1.0.1",
10
- "antspyx",
11
- "antspyt1w>=0.2.3",
12
- "pathlib",
13
- "dipy",
14
- "nibabel",
15
- "scipy",
16
- "siq",
17
- "scikit-learn"]
18
-
19
- setup(name='antspymm',
20
- version='1.3.5',
21
- description='multi-channel/time-series medical image processing with antspyx',
22
- long_description=long_description,
23
- long_description_content_type="text/markdown; charset=UTF-8; variant=GFM",
24
- url='https://github.com/stnava/ANTsPyMM',
25
- author='Avants, Gosselin, Tustison, Reardon',
26
- author_email='stnava@gmail.com',
27
- license='Apache 2.0',
28
- install_requires=requirements,
29
- packages=['antspymm'],
30
- zip_safe=False)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes