Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
VerisimilitudeX committed Feb 18, 2025
2 parents 1090ef0 + 423d9eb commit c33a043
Show file tree
Hide file tree
Showing 9 changed files with 308 additions and 194 deletions.
3 changes: 2 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"configurations": [

{
"type": "java",
"name": "DNADataUploader",
Expand All @@ -20,7 +21,7 @@
"request": "launch",
"mainClass": "DNAnalyzer.Main",
"projectName": "DNAnalyzer",
"args": "assets/dna/random/dnalong.fa --amino=ser --min=16450 --max=520218 -r --rcomplement --version"
"args": "assets/dna/random/dnalong.fa --amino=ser --min=16450 --max=520218 -r --rcomplement --version --mutate 10"
}
]
}
81 changes: 37 additions & 44 deletions src/main/java/DNAnalyzer/adapter/ApiKeyController.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package DNAnalyzer.adapter;

import DNAnalyzer.core.ApiKeyService;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
Expand All @@ -11,53 +11,46 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import DNAnalyzer.core.ApiKeyService;

/**
* REST controller for managing OpenAI API key.
*/
/** REST controller for managing OpenAI API key. */
@RestController
@RequestMapping("/api-key")
@CrossOrigin(origins = "*")
public class ApiKeyController {

private final ApiKeyService apiKeyService;

@Autowired
public ApiKeyController(ApiKeyService apiKeyService) {
this.apiKeyService = apiKeyService;
}

/**
* Get the current API key status.
*
* @return Response indicating if API key is configured
*/
@GetMapping
public ResponseEntity<ApiKeyResponse> getApiKeyStatus() {
boolean hasKey = apiKeyService.hasApiKey();
return ResponseEntity.ok(new ApiKeyResponse(hasKey));
}

/**
* Set a new API key.
*
* @param request Request containing the new API key
* @return Response indicating success
*/
@PostMapping
public ResponseEntity<?> setApiKey(@RequestBody SetApiKeyRequest request) {
try {
apiKeyService.setApiKey(request.getApiKey());
return ResponseEntity.ok(Map.of(
"status", "success",
"message", "API key updated successfully"
));
} catch (IllegalArgumentException e) {
return ResponseEntity.badRequest().body(Map.of(
"status", "error",
"message", e.getMessage()
));
}
private final ApiKeyService apiKeyService;

@Autowired
public ApiKeyController(ApiKeyService apiKeyService) {
this.apiKeyService = apiKeyService;
}

/**
* Get the current API key status.
*
* @return Response indicating if API key is configured
*/
@GetMapping
public ResponseEntity<ApiKeyResponse> getApiKeyStatus() {
boolean hasKey = apiKeyService.hasApiKey();
return ResponseEntity.ok(new ApiKeyResponse(hasKey));
}

/**
* Set a new API key.
*
* @param request Request containing the new API key
* @return Response indicating success
*/
@PostMapping
public ResponseEntity<?> setApiKey(@RequestBody SetApiKeyRequest request) {
try {
apiKeyService.setApiKey(request.getApiKey());
return ResponseEntity.ok(
Map.of(
"status", "success",
"message", "API key updated successfully"));
} catch (IllegalArgumentException e) {
return ResponseEntity.badRequest().body(Map.of("status", "error", "message", e.getMessage()));
}
}
}
18 changes: 8 additions & 10 deletions src/main/java/DNAnalyzer/adapter/ApiKeyResponse.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
package DNAnalyzer.adapter;

/**
* Response object for API key status.
*/
/** Response object for API key status. */
public class ApiKeyResponse {
private final boolean configured;
private final boolean configured;

public ApiKeyResponse(boolean configured) {
this.configured = configured;
}
public ApiKeyResponse(boolean configured) {
this.configured = configured;
}

public boolean isConfigured() {
return configured;
}
public boolean isConfigured() {
return configured;
}
}
18 changes: 8 additions & 10 deletions src/main/java/DNAnalyzer/adapter/SetApiKeyRequest.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
package DNAnalyzer.adapter;

/**
* Request object for setting API key.
*/
/** Request object for setting API key. */
public class SetApiKeyRequest {
private String apiKey;
private String apiKey;

public String getApiKey() {
return apiKey;
}
public String getApiKey() {
return apiKey;
}

public void setApiKey(String apiKey) {
this.apiKey = apiKey;
}
public void setApiKey(String apiKey) {
this.apiKey = apiKey;
}
}
18 changes: 9 additions & 9 deletions src/main/java/DNAnalyzer/adapter/StatusController.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
package DNAnalyzer.adapter;

import java.util.Map;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;

@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "*")
public class StatusController {

@GetMapping("/status")
public ResponseEntity<?> getStatus() {
return ResponseEntity.ok(Map.of(

@GetMapping("/status")
public ResponseEntity<?> getStatus() {
return ResponseEntity.ok(
Map.of(
"status", "online",
"version", "1.0.0"
));
}
}
"version", "1.0.0"));
}
}
112 changes: 112 additions & 0 deletions src/main/java/DNAnalyzer/core/DNAMutation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package DNAnalyzer.core;

import DNAnalyzer.utils.core.DNATools;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

/** This class provides provides functionality for generating mutated DNA sequences. */
public class DNAMutation {

private static final char[] BASES = {'A', 'T', 'C', 'G', 'N'};
private static Random random = new Random();

/**
* Generates a list of 10 mutated DNA sequences based on the specified number of base mutations
* and prints them to the console.
*
* @param dnaString Original DNA sequence to mutate
* @param numMutations The number of base mutations to apply to each mutated sequence
*/
public static void generateAndWriteMutatedSequences(
String dnaString, int numMutations, PrintStream out) {
List<String> mutatedSequences = new ArrayList<>();

out.println("\nMutating DNA sequence...");

// Generate 10 mutated sequences
for (int i = 0; i < 10; i++) {
DNATools mutatedDna = new DNATools(mutate(dnaString, numMutations));
mutatedSequences.add(mutatedDna.dna()); // Store the mutated DNA sequence to the list
}

// Dynamically generate the file name based on the current timestamp
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String fileName = "mutated_dna_" + timestamp + ".fa";

// Write the mutated sequences to a file
try (FileWriter writer = new FileWriter(fileName)) {
for (int i = 0; i < mutatedSequences.size(); i++) {
writer.write(">mutation_" + (i + 1) + "\n"); // Write a header for each mutated sequence
String mutatedSequence = mutatedSequences.get(i);

// Write the sequence over multiple lines (e.g., 80 characters per line)
for (int j = 0; j < mutatedSequence.length(); j += 80) {
writer.write(
mutatedSequence.substring(j, Math.min(j + 80, mutatedSequence.length())) + "\n");
}
}
out.println("Mutated DNA sequences have been written to: " + fileName + "\n");
} catch (IOException e) {
out.println("Error writing to file: " + e.getMessage() + "\n");
}
}

/**
* Mutates a DNA sequence with a specified number of random base mutations.
*
* @param dnaString Original DNA sequence to mutate
* @param numMutations The number of mutations (substitutions) to apply to the sequence
* @return A new mutated DNA sequence
*/
private static String mutate(String dnaString, int numMutations) {
StringBuilder mutatedDna = new StringBuilder(dnaString);

if (numMutations > mutatedDna.length()) {
System.out.println(
"Warning: Number of requested mutations exceeds DNA length. Limiting to "
+ mutatedDna.length());
numMutations = mutatedDna.length();
}

// Create a list of all possible positions
List<Integer> availablePositions = new ArrayList<>();
for (int i = 0; i < dnaString.length(); i++) {
availablePositions.add(i);
}

// Perform mutations
for (int i = 0; i < numMutations; i++) {
// Select a random position from the available positions
int randomPosition = random.nextInt(availablePositions.size());
int position = availablePositions.remove(randomPosition);

char originalBase = dnaString.charAt(position);
char mutatedBase = getDifferentBase(originalBase);

mutatedDna.setCharAt(position, mutatedBase);
}

return mutatedDna.toString();
}

/**
* Returns a random base different from the original base.
*
* @param originalBase Original base to mutate from
* @return A mutated base (different from the original)
*/
private static char getDifferentBase(char originalBase) {
int index = new String(BASES).indexOf(originalBase);

// Pick a random index that isn’t the same as the original
int newIndex = (index + 1 + random.nextInt(BASES.length - 1)) % BASES.length;

return BASES[newIndex];
}
}
21 changes: 17 additions & 4 deletions src/main/java/DNAnalyzer/ui/cli/CmdArgs.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,17 @@

package DNAnalyzer.ui.cli;

import java.io.File;
import java.io.IOException;
import java.util.Objects;
import static DNAnalyzer.data.Parser.parseFile;

import DNAnalyzer.core.DNAAnalysis;
import DNAnalyzer.core.DNAMutation;
import DNAnalyzer.core.Properties;
import static DNAnalyzer.data.Parser.parseFile;
import DNAnalyzer.ui.gui.DNAnalyzerGUI;
import DNAnalyzer.utils.core.DNATools;
import DNAnalyzer.utils.core.Utils;
import java.io.File;
import java.io.IOException;
import java.util.Objects;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
import picocli.CommandLine.Parameters;
Expand Down Expand Up @@ -89,6 +90,13 @@ public class CmdArgs implements Runnable {
description = "Prints the complement of the DNA sequence.")
boolean rcomplement;

@Option(
names = {"--mutate"},
description =
"Generates 10 mutations of the DNA sequence, each with the specified number of mutations,"
+ " and saves them to a file.")
int mutationCount = 0;

@Option(
names = {"--verbose", "-V"},
description = "Enable verbose mode (detailed output)")
Expand Down Expand Up @@ -127,6 +135,11 @@ public void run() {
} else {
DNAAnalysis dnaAnalyzer = dnaAnalyzer(aminoAcid).isValidDna().replaceDNA("u", "t");

if (mutationCount > 0) {
DNAMutation.generateAndWriteMutatedSequences(
dnaAnalyzer.dna().getDna(), mutationCount, System.out);
}

if (reverse) {
dnaAnalyzer = dnaAnalyzer.reverseDna();
}
Expand Down
Loading

0 comments on commit c33a043

Please sign in to comment.