2
$\begingroup$

I have the following files names in a directory:

{"myfileaxis.data", "nb100", "nb1000", "nb1100", "nb1200", "nb1300", \
"nb1400", "nb1500", "nb1600", "nb1700", "nb1800", "nb200", "nb2000", \
"nb2100", "nb2200", "nb2300", "nb2400", "nb2500", "nb2600", "nb2700", \
"nb2800", "nb2900", "nb300", "nb3000", "nb3100", "nb3200", "nb3300", \
 "nb3400", "nb3500", "nb3600", "nb3700", "nb3800", "nb3900", "nb400", \
 "nb4000", "nb500", "nb600", "nb700", "nb800", "nb900", \
  "parmcnt.lammps"}

In each file I have the followings:

 {"dump.lammpstrj", "force.txt", "len.txt", "strain.txt", "stress.txt"}

I need to import the related len.txt and force.txt from each nb100, nb200,... folders, such that It can read len.txt and force.text from nb100 for instance, (and run the piece of program I have written to do calculations based on the text files data) and finally save the result as for example result100.

I have done this manually [in a stupid way] for each folder (read one folder nb100//do the calculation/save as reault100 , then I changed the name manually to read the next one and change the result200 name and so on...

for example I set the directory as:

  SetDirectory["/Users/Desktop/April10/coeff4000/nb100"]
  FileNames[]

and :

rawforce = Import["force.txt", "Data"];
rawlen = Import["len.txt", "Data"];
rawcntpos = Import["inipos.txt", "Data"];

But each time I have to change nb100 to nb200 , ... to read and store the related force.txt, len.txt and inipos.txt . I was wondering if there is an easier way to program the above.

Here is an example of the piece of code I have:

 SetDirectory["/Users/Desktop/April10/coeff4000/nb100"]
 FileNames[]
 
 rawforce = Import["force.txt", "Data"];
 rawlen = Import["len.txt", "Data"];
 rawcntpos = Import["inipos.txt", "Data"];

 (*****Calculation body****)
 t1 = Table[{rawcntpos[[i]][[3]], rawcntpos[[i]][[4]], 
 rawcntpos[[i]][[5]]}, {i, 1, Length[rawcntpos]}];
 neighList = ParallelTable[siteLoc = t1[[i]];
 checkDist = Table[rvec = t1[[k]] - siteLoc;
 dist2 = rvec . rvec; 
 And[dist2 > 0.1, dist2 < sp + m] , {k, 1, Length[t1]}];
 Sort[Flatten[Position[checkDist, True]]], {i, 1, Length[t1]}];

 crossbond = ParallelTable[siteLoc = t1[[i]];
 checklist = Table[rvec = t1[[k]] - siteLoc;
 dist = Sqrt[rvec . rvec]; 
 And[dist == 2*radf, i != k], {k, 1, Length[t1]}];
 Sort[Flatten[Position[checklist, True]]], {i, 1,     Length[t1]}];

  bondlist100 = Union[Join[crossbond, neighList]];

My question is how to write a program that automatically loop over all nb100, nb200 ,nb300 ...

and read force.txt len.txt and inipos.text and store the bondlist related to nb100, nb200, nb300...as bondlist100,bondlist200,bondlist300 ...

Thank you so much

$\endgroup$
1
  • 3
    $\begingroup$ Create a function that accepts a file name, performs the needed operations, and returns the result. Perhaps a list containing len.txt and force.txt. Then map that function onto a list of file names. This will return a list of results, one result for each file name. $\endgroup$ Commented Apr 10 at 23:27

1 Answer 1

1
$\begingroup$

Here is an example constructed to be similar to your requirement. I could not use your code directly because I do not have your data files or directory structure. But the method is here.

The key point is that you can construct a function which accepts as its argument a directory name as a string, and then Map that function onto a list of directories. The result is a list of results, each item in the list (which may be a list of several calculations) is the result of processing the files in one directory.

(* set to the the directory containing this notebook*)
SetDirectory[NotebookDirectory[]];

(* all the directorys and files in this directory*)
FileNames[]

{"data directory", "process files.nb"}

(*"data directory" contains the directories containing data*)
SetDirectory["data directory"];
dataDirectories = FileNames[]

(* {"dir1","dir2","dir3"} *)

(*each directory contains an Excel file named "data.xlsx" \
with a list of numbers. I want the sum for each list*)

(*this function accepts a directory name, and processes the \
data file found in that directory*)

 getSum[dir_] := Module[{dataFile, data},
  (*construct the file name*)
  dataFile = FileNameJoin[{dir, "data.xlsx"}];
  (*import the data file*)
  data = Import[dataFile] ;
  (*sum the numbers*)
  Total@Flatten[data]
  (*no semicolon means function returns sum*)
  (* it could return a list of results*)
  ]

(* NOW MAP THE FUNCTION ONTO THE LIST OF DIRECTORY NAMES *)
(* /@ is short for Map *)

getSum /@ dataDirectories

(*{10.`,36.`,78.`}*)
$\endgroup$
3
  • $\begingroup$ Thank you so much, great help $\endgroup$ Commented Apr 11 at 17:59
  • 2
    $\begingroup$ One can avoid needing to define a dataDirectories variable by using FileSystemMap (if you want to return values) or FIleSystemScan(if you don't). Set the IncludeDirectories -> True option to include directories and set the FileNameForms-> "nb*" to restrict the pattern, as desired. $\endgroup$ Commented Apr 12 at 0:58
  • $\begingroup$ I think that’s very useful. Thanks. $\endgroup$ Commented Apr 12 at 19:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.